Skip to content

feat(platform): API keys for programmatic access#485

Merged
seonghobae merged 1 commit into
feat/entities-on-mainfrom
feat/api-keys
Jul 6, 2026
Merged

feat(platform): API keys for programmatic access#485
seonghobae merged 1 commit into
feat/entities-on-mainfrom
feat/api-keys

Conversation

@seonghobae

Copy link
Copy Markdown
Collaborator

Stacked on #467 (needs the 0004→0006 alembic chain; auto-retargets to main when #467 merges — approved pattern).

Why this matters for platform value

Everything so far requires a session cookie — even the CI drift gate. API keys unlock programmatic access: CI/CD integrations, SDKs, external ecosystem. API-first is table stakes for a platform valuation.

Design (security-first)

  • Authorization: Bearer pgerd_… accepted by get_current_user alongside OIDC — one added branch, OIDC path untouched.
  • Secret never stored: SHA-256 hash only (unique-indexed lookup); plaintext returned exactly once at creation; key_prefix for recognition; any lookup failure = the same 401 (no key probing).
  • Revocation = auditable timestamp, idempotent; rows kept.
  • IDOR-safe: another user's key → uniform 404.

Also fixes a latent main bug

0003_revoked_token had down_revision="0002" (nonexistent — actual id 0002_auth_share), which breaks alembic upgrade head on any fresh database. Fix carried here (and pushed to #467).

Verification

Migration 0007_api_key applied against real Postgres; backend pytest 236 passed (+5: hash properties, secret-once, revoked/unknown-key 401s, IDOR revoke, metadata-only list); mypy clean.

🤖 Generated with Claude Code

P2 roadmap item — API-first platform access. Bearer pgerd_* keys accepted by get_current_user alongside OIDC (non-invasive branch). Secrets never stored: SHA-256 hash only, plaintext returned exactly once at creation, key_prefix for recognition, revocation is an auditable timestamp (idempotent). /api/api-keys: POST create, GET list (metadata only), DELETE revoke (uniform 404 for other users' keys). Also carries the 0003_revoked_token down_revision fix ('0002' -> '0002_auth_share') without which alembic upgrade head breaks on a fresh DB. Migration 0007 verified against real Postgres. +5 tests; backend suite 236; mypy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
@seonghobae seonghobae merged commit 20a67aa into feat/entities-on-main Jul 6, 2026
3 checks passed
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