feat: developer tokens with independent OAuth grants (#367)
* feat: developer token management with listing and revocation
adds full lifecycle management for developer tokens:
**backend**
- add `is_developer_token` and `token_name` fields to UserSession model
- add GET /auth/developer-tokens endpoint to list user's tokens
- add DELETE /auth/developer-tokens/{prefix} to revoke tokens
- update POST /auth/developer-token to accept optional name parameter
- add AuthSettings config for token expiration limits
- fix connection pool leak in test fixtures (was causing TooManyConnectionsError)
**frontend**
- show existing tokens in portal with names, creation/expiration dates
- add token name input field when creating new tokens
- add revoke button for each active token
- add loading state indicator while fetching tokens
**tests**
- add 9 tests for developer token API (create, list, revoke)
- add integration test for upload/delete flow
- add `just backend integration` recipe
**docs**
- update authentication.md with token management section
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add cyclopts CLI for upload/download/list/delete
- PEP 723 inline script deps (just uv run it)
- pydantic-settings for PLYR_TOKEN/PLYR_API_URL config
- rich tables and status spinners
* refactor: rename RelaySettingsSection to AppSettingsSection
relay is the old project name
* refactor: use separate OAuth grants for developer tokens
Developer tokens now get their own OAuth credentials via a fresh
authorization flow, rather than copying credentials from the browser
session. This prevents tokens from going stale when browser sessions
refresh their tokens independently.
Changes:
- Add PendingDevToken model to store OAuth flow metadata by state
- Add POST /auth/developer-token/start to initiate OAuth for dev tokens
- Modify /auth/callback to detect dev token flows and create independent sessions
- Update frontend to redirect to PDS authorization and handle callback
- Remove old credential-copying endpoint
- Rewrite tests for new OAuth-based flow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update authentication.md for OAuth-based dev tokens
- Update creating token flow to mention PDS authorization step
- Update API example to show /auth/developer-token/start endpoint
- Explain that tokens have independent OAuth grants, not inherited credentials
- Add PR #367 reference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: default CLI to localhost, document env overrides
- Default PLYR_API_URL to http://localhost:8001 (local dev)
- Add docstring examples for staging and production overrides
- Prevents accidental production API calls during development
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: prevent dev token exchange from overwriting browser cookie
When creating a dev token via OAuth, the exchange endpoint was setting
a cookie with the dev token's session_id, overwriting the browser's
session cookie. This caused logout to delete the dev token instead of
the browser session.
Fix:
- Add is_dev_token flag to ExchangeToken model
- Pass is_dev_token=True when creating exchange token for dev tokens
- Skip cookie setting in /auth/exchange for dev token exchanges
Now dev tokens are fully independent of browser sessions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update dev token section with CLI usage and cookie isolation
- Replace sandbox script reference with scripts/plyr.py CLI
- Add CLI examples for list/upload/download/delete
- Mention cookie isolation in how it works section
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
authored by
zzstoatzz.io
Claude
and committed by
GitHub
6a82cf4f
2171d311