10 Commits

Author SHA1 Message Date
tiennm99 e191a138e9 fix(keys): match reconcile to current key name via shared prefix constant
Reconcile filtered app keys by the old "llmapikey:" prefix while mint now names
them "llmapikey/gh-<id>", so orphan/cost-leak detection silently missed every
new key. Centralize the prefix in lib/keys/key-name.js (KEY_NAME_PREFIX +
keyName) and use it in both mint and reconcile so they can't drift.
2026-06-14 14:18:13 +07:00
tiennm99 b710537f63 refactor(keys): rename openrouter_key_hash to openrouter_delete_hash
The column holds OpenRouter's delete handle (data.hash) used to revoke a key,
not a hash of the key. Migration 0003 renames the column; update repository,
admin revoke action, and the reconcile script.
2026-06-14 14:14:20 +07:00
tiennm99 3eda216dc6 feat(keys): store raw OpenRouter key and make it retrievable
Persist the raw key (migration 0002 adds openrouter_key) so users can copy it
again from the dashboard instead of a one-time-only reveal; admin console shows
the full key. Retain openrouter_key_hash for revocation. Keys remain in the
unexposed llmapikey schema (deny-all RLS, server-only direct connection).

- activate() stores the raw key; dashboard + generate-key return the full key.
- key-display warning updated (no longer shown-once).
- admin table renders the full key.
2026-06-14 14:10:46 +07:00
tiennm99 d0fdcb4041 feat(keys): create minted OpenRouter keys in a configured workspace
Pass create-key workspace_id (from OPENROUTER_WORKSPACE_ID, defaulting to the
project workspace) so minted keys land in the intended workspace instead of the
management key's default. Rename key to non-PII llmapikey/gh-<id>.

- buildCreateKeyBody emits workspace_id only when set (omission keeps default).
- createKey threads workspaceId; mintAndPersist sources it from env.
- Test asserts workspace_id presence/omission; document the new env var.
2026-06-14 12:40:03 +07:00
tiennm99 a3ab7cde9e chore(config): align env var names and enable Vercel deploys
- Rename DATABASE_URL -> POSTGRES_URL and OPENROUTER_PROVISIONING_KEY ->
  OPENROUTER_MANAGEMENT_KEY to match the documented setup.
- Inline repo URL and model constants (drop NEXT_PUBLIC_ indirection).
- vercel.json: framework nextjs; enable git deployments.
2026-06-14 12:19:58 +07:00
tiennm99 559bac8104 feat(auth): replace Supabase Auth with app-native GitHub OAuth
Self-contained GitHub OAuth (Arctic) with a stateless HS256 signed-cookie
session (jose); Supabase is downgraded to the Postgres host only.

- Origin-derived callback (no redirect-uri env); read:user scope; access
  token read once at callback and discarded (no token storage).
- CSRF via single-use state cookie; open-redirect guard on next.
- getCurrentGithubIdentity() now reads the session cookie, preserving the
  numeric provider_id identity contract for admin/dashboard/mint.
- Remove @supabase/ssr + @supabase/supabase-js, middleware, and the
  supabase-dependent rls test; delete lib/supabase clients.
2026-06-14 12:19:40 +07:00
tiennm99 616f133989 feat: add gated admin console for api_keys registry (list/search/filter/revoke/mint)
- env-allowlist authz via ADMIN_GITHUB_USER_IDS on numeric provider_id (no migration)
- server-side re-gated revoke + manual-mint actions
- parameterized search/filter/paginate queries
- shared mint-key extraction (DRY) from generate-key
- notFound() for non-admins (404 never leaks route existence)
- 3 unit-test suites (authz/queries/integration)
2026-06-13 21:16:57 +07:00
tiennm99 e03c606ea9 docs: clarify intent of stale-pending windows, ceiling-check, and error JSDoc
- note generate-key 2-min reclaim vs reconcile 10-min report split
- comment intentional >=/> asymmetry in the kill-switch re-check
- document getCurrentGithubIdentity throw path and ProvisioningError status
2026-06-13 19:20:41 +07:00
tiennm99 8fcc705e2c refactor: simplify comments, styling, and conflict-resolution control flow
- replace stale plan-reference comments with intent-describing ones
- move inline nav style to a .site-nav CSS class
- drop dummy placeholder return in generate-key resolveConflict
2026-06-13 14:49:15 +07:00
tiennm99 02fa52ccf9 feat: scaffold OpenRouter key giveaway site (gated, code-only)
- Next.js 15 App Router (JS+JSDoc): landing, auth-gated dashboard, docs
- GitHub OAuth via Supabase; identity anchored on numeric provider_id
- key provisioning: reserve-then-mint-persist-compensate, one key per account
- api_keys in unexposed llmapikey schema via direct Postgres; RLS deny-all
- live minting gated behind PROVISIONING_ENABLED; Vercel auto-deploy disabled
- unit tests (mask, request-body), RLS deny-all test, reconcile script
2026-06-13 14:18:52 +07:00