molecule-core/canvas
Hongming Wang f72fa4cd70 feat(auth): organization-scoped API keys for admin access
Adds user-facing API keys with full-org admin scope. Replaces the
single ADMIN_TOKEN env var with named, revocable, audited tokens
that users can mint/rotate from the canvas UI without ops
intervention.

Designed for the beta growth phase — one token tier (full admin).
Future work will split into scoped roles (admin / workspace-write
/ read-only) and per-workspace bindings. See docs/architecture/
org-api-keys.md for the design + follow-up roadmap.

## Surface

  POST   /org/tokens        mint (plaintext returned once)
  GET    /org/tokens        list live keys (prefix-only)
  DELETE /org/tokens/:id    revoke (idempotent)

All AdminAuth-gated. Bootstrap path: mint the first token via
ADMIN_TOKEN or canvas session; tokens can mint more tokens after.

## Validation as a new AdminAuth tier (2a)

AdminAuth evaluation order:
  Tier 0  lazy-bootstrap fail-open (only when no live tokens AND
          no ADMIN_TOKEN env)
  Tier 1  verified WorkOS session via /cp/auth/tenant-member
  Tier 2a org_api_tokens SELECT — NEW
  Tier 2b ADMIN_TOKEN env (bootstrap / CLI break-glass)
  Tier 3  any live workspace token (deprecated, only when ADMIN_TOKEN
          unset)

Tier 2a runs ONE indexed lookup (partial index on
token_hash WHERE revoked_at IS NULL) + an async last_used_at
bump. No measurable latency cost on the hot path.

## UI

New "Org API Keys" tab in the settings panel. Label field for
human-readable naming. Plaintext shown once + clipboard copy.
Revoke with confirm dialog. Mirrors the existing workspace-
TokensTab flow so users who've used one get the other for free.

## Security properties

  - Plaintext never stored. sha256 hash + 8-char display prefix.
  - Revocation is immediate: partial index on revoked_at IS NULL
    means the next request validates or fails in microseconds.
  - created_by audit field captures provenance: "org-token:<short>"
    when a token mints another, "session" for browser-UI mints,
    "admin-token" for the ADMIN_TOKEN bootstrap path.
  - Validate() collapses all failure shapes into ErrInvalidToken
    so response-shape can't distinguish "never existed" from
    "revoked".

## Tests

  - internal/orgtoken: 9 unit tests (hash storage, empty field
    null-ing, validation happy path, empty plaintext, unknown hash,
    revoked filtering, list ordering, revoke idempotency, has-any-
    live short-circuit).
  - AdminAuth tier-2a integration covered by existing middleware
    tests unchanged (fail-open + bearer paths).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 14:01:41 -07:00
..
e2e test(e2e): add Playwright smoke for FilesTab split 2026-04-13 18:14:54 -07:00
public chore: replace brand icon and add HANDOFF.md 2026-04-13 13:03:40 -07:00
src feat(auth): organization-scoped API keys for admin access 2026-04-20 14:01:41 -07:00
.env.example fix(canvas): close 4 gaps in WS status indicator (env, toast, tests) 2026-04-14 08:26:38 +00:00
.gitignore feat(canvas): SaaS cross-origin — slug header + cookie credentials (Phase F) 2026-04-14 20:08:39 -07:00
components.json chore(canvas): initialize shadcn/ui — components.json + cn utility 2026-04-18 07:57:17 -07:00
Dockerfile fix(canvas): CSP_DEV_MODE + admin token for local Docker (#1052 follow-up) 2026-04-20 12:23:43 -07:00
next.config.ts initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
package-lock.json chore(canvas): initialize shadcn/ui — components.json + cn utility 2026-04-18 07:57:17 -07:00
package.json Merge pull request #967 from Molecule-AI/chore/shadcn-init 2026-04-19 00:27:07 -07:00
playwright.config.ts initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
postcss.config.js initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
tailwind.config.ts initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
tsconfig.json initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
vitest.config.ts initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00