mirror of
https://github.com/tiennm99/llmapikey.git
synced 2026-08-01 18:22:53 +00:00
616f1339894fd74703b6b05f7a4c6925b5e36ea2
- 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)
llmapikey
Free, capped OpenRouter API key giveaway — one key per GitHub account.
Next.js (App Router, JS + JSDoc) on Vercel. GitHub sign-in via Supabase Auth.
Per-user OpenRouter keys are minted from the owner's master Provisioning key,
each capped at a daily USD limit. Key records live in a dedicated, unexposed
llmapikey Postgres schema reached only by a server-side direct connection.
Status: code build only. Live key minting is gated behind
PROVISIONING_ENABLED=falseuntil the OpenRouter ToS approval gate (plan Phase 1) clears. Do not deploy a public giveaway before that.
Stack
- Next.js 15 App Router, plain JS + JSDoc (no TypeScript)
- Supabase Auth — GitHub OAuth provider (sessions via
@supabase/ssr) - Postgres (
postgresnpm) — direct connection to the unexposedllmapikeyschema; the anon role can never reachapi_keys - OpenRouter Provisioning API — mints per-user keys
Architecture notes
- Identity anchor: the numeric, immutable GitHub
provider_id(not the mutable login). One key pergithub_user_id, enforced by a DB unique constraint. - Server-only secrets:
DATABASE_URLandOPENROUTER_PROVISIONING_KEYare guarded by theserver-onlypackage and never reach the client bundle. - Reserve-then-mint: a
pendingrow is inserted (ON CONFLICT DO NOTHING) before minting, so concurrent double-submits yield exactly one OpenRouter key. - Schema isolation:
llmapikeyis NOT added to PostgREST exposed schemas; RLS is deny-all as defense in depth. - Admin console: route
/admin(unlisted — no nav link) lists, searches, filters, revokes, and manually mints keys. Access is gated by theADMIN_GITHUB_USER_IDSallowlist against the same numericprovider_idanchor; non-admins getnotFound()(a 404, never a redirect that would leak the route's existence). Every admin server action re-checks the allowlist server-side, so the page gate is defense-in-depth only.
Setup
- Install
npm install - Environment — copy
.env.exampleto.env.localand fill in values.Var Purpose NEXT_PUBLIC_SUPABASE_URLSupabase project URL (public) NEXT_PUBLIC_SUPABASE_ANON_KEYSupabase anon key (public, auth UI only) DATABASE_URLSupabase transaction pooler string (server-only) OPENROUTER_PROVISIONING_KEYMaster Provisioning key (server-only) NEXT_PUBLIC_REPO_URLRepo URL for the soft star nudge NEXT_PUBLIC_OPENROUTER_MODELModel id shown in /docsPROVISIONING_ENABLEDfalseuntil Phase 1 ToS gate clearsMAX_TOTAL_KEYSKill-switch: stop minting past N active keys KEY_DAILY_LIMIT_USDPer-key daily cap sent to OpenRouter KEY_EXPIRY_DAYSKey lifetime (sets expires_at)ADMIN_GITHUB_USER_IDSAdmin allowlist — numeric GitHub provider_ids, CSV (server-only) - Database — apply the migration to a staging branch first, then prod
(Supabase SQL editor or
psql "$DATABASE_URL" -f ...):Do NOT addpsql "$DATABASE_URL" -f supabase/migrations/0001_llmapikey_schema_and_api_keys.up.sqlllmapikeyto the project's PostgREST "Exposed schemas". Rollback:...0001_...down.sql. - GitHub OAuth — register a GitHub OAuth App; set the client id/secret in
the Supabase dashboard (Auth > Providers > GitHub), callback
https://<project>.supabase.co/auth/v1/callback. Add localhost + your Vercel domain to Supabase Auth redirect URLs. - Run
npm run dev # http://localhost:3000 npm test # unit tests
Deploy (gated)
Auto-build on Vercel is intentionally disabled (see vercel.json). Promote
manually once the Phase 1 ToS gate clears and PROVISIONING_ENABLED=true.
Description
No description provided
api-gatewayapi-keysarchivedgithub-oauthjavascriptllm-gatewaynextjsoauth2openrouterpendingpostgresproject-pausedprovisioningsupabasevercel
Readme
466 KiB
Languages
JavaScript
96.1%
CSS
3.9%