Skip to content

fix(cli): end-to-end prx publish with device-code login#1

Closed
primeobsession wants to merge 2 commits into
mainfrom
fix/prx-cli-publish-end-to-end
Closed

fix(cli): end-to-end prx publish with device-code login#1
primeobsession wants to merge 2 commits into
mainfrom
fix/prx-cli-publish-end-to-end

Conversation

@primeobsession
Copy link
Copy Markdown
Contributor

Summary

  • Make 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 as Authorization: Bearer and the server rejected every write.
  • Add prx login / logout / whoami using the device-code OAuth flow defined in prxhub/CLI-AUTH-CONTRACT.md. Token stored at ~/.config/prx/auth.json (chmod 0600).
  • Rewrite src/prx/api/__init__.py around a shared _auth_headers() helper that pulls the bearer token from the on-disk auth store. Read endpoints (search, public get, public download) work without a token.
  • Fix three prx keys bugs: tuple-unpack crash in generate, wrong/stale path + glob in list, stub register (now a real implementation that POSTs an RFC 8037 Ed25519 JWK to /api/keys). Also wire up a real keys revoke.
  • Unify key storage: adopt parallect's existing ~/.config/parallect/keys/ as canonical by importing DEFAULT_KEY_DIR from prx_spec. No migration — a bundle signed by parallect can now be registered and published by prx.
  • Map prx publish error codes to actionable messages: 401 -> "Run prx login again"; 403 with signature/key in body -> "Run prx keys register to register this key".
  • Update README to document the new auth model, command set, and key dir.

Test plan

  • uv run pytest tests/ (70/70 passing; was 44)
  • 26 new tests cover token store, device-code flow (happy / slow_down / denied / expired / timeout), bearer-header injection, keys register, publish auth plumbing
  • Manual end-to-end against live prxhub — blocked on the parallel server-side PR that implements /api/auth/cli/start, /api/auth/cli/poll, and /cli/device. Once that lands:
    1. prx login -> browser opens, approve -> token saved
    2. prx keys register -> succeeds, key appears on prxhub.com/settings
    3. prx publish /tmp/byok-3p.prx -> bundle URL returned, appears on prxhub

Notes

  • Server contract (CLI-AUTH-CONTRACT.md) wasn't yet checked into prxhub/ at time of writing; coded to the brief. Any divergence will be a small follow-up in auth.py / login.py.
  • --with-parallect federation is stubbed with NotImplementedError pending server support.
  • The legacy positional api_key argument 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

primeobsession and others added 2 commits April 15, 2026 20:22
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>
@primeobsession
Copy link
Copy Markdown
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 --collection flag on top. Bearer-token + device-code flow work from this PR will land as a separate enhancement later.

@primeobsession primeobsession deleted the fix/prx-cli-publish-end-to-end branch April 16, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant