fix(cli): end-to-end prx publish with device-code login#1
Closed
primeobsession wants to merge 2 commits into
Closed
fix(cli): end-to-end prx publish with device-code login#1primeobsession wants to merge 2 commits into
primeobsession wants to merge 2 commits into
Conversation
Makes `prx publish` (and the rest of the hub write-path commands) actually
work against prxhub.com for the first time. Previously every write attached
an arbitrary string as `Authorization: Bearer` and prxhub's API rejected
all of them because it only accepts session cookies or Ed25519-signed
requests.
Changes:
- Add `prx login` / `logout` / `whoami` (device-code OAuth against prxhub).
Token stored at `~/.config/prx/auth.json` with chmod 0600. Handles
authorization_pending, slow_down, access_denied, expired_token, and
hard timeout. Codes the protocol described in CLI-AUTH-CONTRACT.md.
- Rewrite `src/prx/api/__init__.py` to pull the bearer token from the
auth store via a shared `_auth_headers()` helper. Read endpoints
(search, get bundle, public download) work without a token. Write
helpers raise `AuthRequired` with "Run `prx login` first" when no token
is available and "Your session expired" when the stored token is past
its expiry. Backwards-compatible positional `api_key` still accepted.
- `prx keys generate`: fix tuple-unpack crash (prx_spec.generate_keypair
returns (signing_key, verify_key, key_id), not a single object).
- `prx keys list`: use the unified key directory (prx_spec's
DEFAULT_KEY_DIR = ~/.config/parallect/keys/) so keys produced by the
parallect CLI are visible to prx. Match the real filenames
(prx_signing.key / prx_signing.pub) instead of the stale *.pub glob.
- `prx keys register`: real implementation. Reads the local Ed25519
public key, builds an RFC 8037 OKP/Ed25519 JWK, and POSTs to
/api/keys with the bearer token + default label "<hostname> via prx CLI".
- `prx keys revoke`: real implementation via DELETE /api/keys/{id}.
- `prx publish`: validate zip magic, require login, route through the
new auth client, map 401/403 to actionable messages (expired session /
"register this key" on signature mismatch).
- README: document the device-code flow, the unified key dir, and the
real command set.
- Tests: 26 new tests covering the token store, device-code flow
(happy / slow_down / denied / expired / timeout), bearer-header
injection, `keys register`, and `publish` auth plumbing. Full suite:
44 -> 70 tests, all green.
Unified-key-storage decision: adopt the parallect CLI's existing path
(`~/.config/parallect/keys/`) as canonical for the whole ecosystem
rather than inventing a new location. prx imports DEFAULT_KEY_DIR from
prx_spec so there is one source of truth. No migration needed.
Gated on the server-side PR implementing /api/auth/cli/start and
/api/auth/cli/poll (see prxhub/CLI-AUTH-CONTRACT.md).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Primary product flow is 'create collection → fire research into it'. The CLI now supports publishing directly into a collection: prx publish report.prx --collection warehouse-ai prx publish report.prx --collection warehouse-ai --no-create-collection If the collection doesn't exist and --no-create-collection is not set, the CLI creates it with the publish's visibility and links the bundle. Success output includes the collection URL alongside the bundle URL. Requires the CLI to be logged in (`prx login`) — the bearer token authorizes both the bundle upload and the collection create/link. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Superseded by #2 — main diverged to a signing-based auth approach (Julian's commit) that already works end-to-end. New PR keeps that approach intact and just adds the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
prx publish(and the rest of the hub write-path commands) actually work against prxhub for the first time. The old code sent an arbitrary string asAuthorization: Bearerand the server rejected every write.prx login/logout/whoamiusing the device-code OAuth flow defined inprxhub/CLI-AUTH-CONTRACT.md. Token stored at~/.config/prx/auth.json(chmod 0600).src/prx/api/__init__.pyaround a shared_auth_headers()helper that pulls the bearer token from the on-disk auth store. Read endpoints (search, publicget, publicdownload) work without a token.prx keysbugs: tuple-unpack crash ingenerate, wrong/stale path + glob inlist, stubregister(now a real implementation that POSTs an RFC 8037 Ed25519 JWK to/api/keys). Also wire up a realkeys revoke.~/.config/parallect/keys/as canonical by importingDEFAULT_KEY_DIRfromprx_spec. No migration — a bundle signed by parallect can now be registered and published by prx.prx publisherror codes to actionable messages: 401 -> "Runprx loginagain"; 403 with signature/key in body -> "Runprx keys registerto register this key".Test plan
uv run pytest tests/(70/70 passing; was 44)keys register,publishauth plumbing/api/auth/cli/start,/api/auth/cli/poll, and/cli/device. Once that lands:prx login-> browser opens, approve -> token savedprx keys register-> succeeds, key appears on prxhub.com/settingsprx publish /tmp/byok-3p.prx-> bundle URL returned, appears on prxhubNotes
CLI-AUTH-CONTRACT.md) wasn't yet checked intoprxhub/at time of writing; coded to the brief. Any divergence will be a small follow-up inauth.py/login.py.--with-parallectfederation is stubbed withNotImplementedErrorpending server support.api_keyargument on API helpers is preserved so existing call sites (and tests) keep working — it's just treated as a bearer token.🤖 Generated with Claude Code