setup-guides

Secrets Handling

How we treat credentials. Short, but not optional — one leaked service-role key exposes every user's data. If you're a new contributor, read this before asking anyone for keys.

The one rule

Never share a secret over chat, DM, email, screenshare, a ticket, or a commit. Not the .env, not "just the one key," not "temporarily." If a secret needs to move, it moves through a secret manager (the deploy provider's env settings, a password manager share), never a channel that keeps history.

What counts as a secret

Secret — never sharePublic — safe to embed
SUPABASE_SERVICE_ROLE_KEY (bypasses RLS — full DB access)NEXT_PUBLIC_SUPABASE_URL
SUPABASE_JWT_SECRET, *_HOOK_SECRET, *_CRON_SECRET, IMPERSONATION_SECRETNEXT_PUBLIC_SUPABASE_ANON_KEY (RLS protects the data)
API keys: OPENAI_API_KEY, ANTHROPIC_API_KEY, ELEVENLABS_API_KEY, REPLICATE_API_TOKEN, RESEND_API_KEY, ZENQUOTES_KEYAny other NEXT_PUBLIC_* value
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET
OAuth client secrets + refresh tokens (Google, YouTube, Spotify), BSKY_APP_PASSWORD

Rule of thumb: anything not prefixed NEXT_PUBLIC_ is a secret. The NEXT_PUBLIC_ prefix means Next.js bakes it into the browser bundle, so it is public by definition — never hide a real secret behind that prefix.

Contributors don't get production secrets

Local dev runs against your own free Supabase project, never production (pfyocleyejmtxmbxrdcm…). See LOCAL_DEV_SETUP.md. Most tasks need no third-party keys at all; the ones that do are handed out per-feature, scoped to a sandbox/test account, when you reach that work — never the production set, never up front.

If a secret leaks (assume the worst, rotate)

A secret that has touched any persistent channel is compromised — deleting the message does not undo it (it's already in history, search, backups, and any integration that ingested it). Rotate immediately:

  • Supabase — Dashboard → Project Settings → API → roll the service_role / JWT secret. Update the deploy env (Railway/Vercel) with the new value.
  • Stripe / OpenAI / Anthropic / ElevenLabs / Resend / Replicate — revoke the key in that provider's dashboard and issue a new one; update the deploy env.
  • OAuth — rotate the client secret + any stored refresh tokens.
  • Then tell the team so everyone updates their env.

Where secrets actually live

  • Local: in your gitignored .env / .env.local only. .gitignore blocks .env* except the committed, value-free *.env.example templates.
  • Production: the deploy provider's env settings — backend on Railway, frontend on Vercel. Not in the repo, ever.

If you accidentally commit a secret, rotate it (above) — scrubbing git history is secondary; the key is already exposed the moment it's pushed.

SECRETS HANDLING — Docs | HiveJournal