Skip to content

feat(auth): user-facing API key management (create / list / revoke) #3116

Description

@SebastienMelki

Context

With the login gate removed in #3115, all visitors can now sign in. The next step is letting authenticated users create and manage their own API keys so they can integrate with the WorldMonitor API programmatically.

Per @koala73's direction — open things up and let users self-serve.

What exists today

  • Clerk-based user auth (login, JWT, roles)
  • OAuth 2.0 token flow (auth code + refresh tokens via Redis)
  • Entitlements/tier system in Convex (apiAccess, apiRateLimit per plan)
  • API key validation middleware (X-WorldMonitor-Key checked against static WORLDMONITOR_VALID_KEYS env var)
  • SHA-256 key hashing in the OAuth flow
  • Product catalog with API-tier plans (API Starter, API Business, Enterprise)

What's missing

Backend

  • Convex userApiKeys table — schema: userId, name, keyPrefix (first 8 chars for display), keyHash (SHA-256), createdAt, lastUsedAt, revokedAt
  • Convex mutationscreateApiKey, listUserApiKeys, revokeApiKey
  • API route(s) — authenticated endpoints that call the Convex mutations (return plaintext key only on creation)
  • Validation middleware update — extend _api-key.js / premium-check.ts to look up user-owned keys in Convex (not just static env var list)
  • Per-key rate limiting — enforce the existing apiRateLimit from entitlements (currently stored but never checked)

Frontend

  • API Keys panel in settings/account — create, list, copy, revoke
  • Copy-on-creation UX — show the full key exactly once with a copy button, then only show the prefix
  • Revoke confirmation — destructive action needs a confirmation step

Out of scope (for now)

  • Usage-based / metered billing via Dodo (currently all plans are flat-rate)
  • Per-endpoint scoping of API keys
  • API usage dashboard / analytics

Notes

  • Key format: wm_<random base64url> (consistent with existing openssl rand -hex 24 | sed 's/^/wm_/' convention in docs)
  • Store only SHA-256 hash in DB, never plaintext
  • Entitlements already define rate limits per tier (0 / 60 / 300 / 1000 req/min) — just need to enforce them

🤖 Generated with Claude Code

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions