Skip to content

Secrets Management

Secrets management in GOVERN follows the principle of least privilege: every secret is scoped to exactly the component that needs it, and no secret lives in source code, commit history, or build logs.

Secret Storage Locations

LocationWhat lives thereAccess
Wrangler secretsWorker runtime secrets (Cloudflare-encrypted)Engineers via wrangler secret
Cloudflare Pages env varsFrontend build-time env varsCloudflare dashboard
1Password (team vault)Master copies, rotation recordsEngineers with vault access
Local .dev.varsDevelopment-only overrides (gitignored)Local machine only

Never: .env committed to git, secrets in wrangler.toml, secrets in build logs.

Full Secrets Inventory

API Gateway (Cloudflare Worker)

Secret namePurposeRotation frequency
SUPABASE_URLSupabase project URLNever (stable)
SUPABASE_SERVICE_ROLE_KEYFull DB access (server-side only)Annually or on breach
ANTHROPIC_API_KEYClaude API callsEvery 90 days
OPENAI_API_KEYTTS-1 voice synthesisEvery 90 days
AUTH_SECRETBearer token for API authEvery 90 days
CHAIRMAN_USER_IDChairman’s Supabase UUIDNever (stable)
UPSTASH_REDIS_REST_URLRedis endpointNever (stable)
UPSTASH_REDIS_REST_TOKENRedis auth tokenAnnually
LANGFUSE_HOSTLangfuse observability endpointNever (stable)
LANGFUSE_PUBLIC_KEYLangfuse public keyAnnually
LANGFUSE_SECRET_KEYLangfuse secret keyAnnually
GROQ_API_KEYGroqChairman substrate callsEvery 90 days
INNGEST_EVENT_KEYInngest event submissionAnnually
INNGEST_SIGNING_KEYInngest webhook verificationAnnually

Cloudflare Pages (Frontend)

VariablePurpose
VITE_API_URLAPI Gateway URL (not secret, but env-specific)
VITE_SUPABASE_URLSupabase URL (not secret)
VITE_SUPABASE_ANON_KEYSupabase anon key (public by design)

Probe Container

VariablePurpose
GOVERN_API_URLGOVERN API endpoint
GOVERN_API_KEYPer-customer probe auth key
GOVERN_SYSTEM_IDIdentifies which AI system this probe monitors

Managing Wrangler Secrets

List current secrets

expressiveCode.terminalWindowFallbackTitle
# Production environment
npx wrangler secret list --env production
# Staging environment
npx wrangler secret list --env staging

Set a secret

expressiveCode.terminalWindowFallbackTitle
# Interactive (prompted for value — preferred, avoids shell history)
npx wrangler secret put ANTHROPIC_API_KEY --env production
# From stdin (useful in CI)
echo "sk-ant-..." | npx wrangler secret put ANTHROPIC_API_KEY --env production

Delete a secret

expressiveCode.terminalWindowFallbackTitle
npx wrangler secret delete OLD_SECRET_NAME --env production

Verify a secret is accessible in the Worker

expressiveCode.terminalWindowFallbackTitle
# The health endpoint checks key bindings
curl https://jarvis-api-gateway.ben-c1f.workers.dev/health | jq '.checks'
# A missing or invalid secret will show as "error" in the checks object

Local Development Setup

For local development, create .dev.vars in each package that needs secrets:

expressiveCode.terminalWindowFallbackTitle
# packages/api-gateway/.dev.vars (gitignored)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
ANTHROPIC_API_KEY=sk-ant-...
AUTH_SECRET=local-dev-secret-do-not-use-in-prod
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=AX...

The .dev.vars file is read by wrangler dev automatically. It is listed in .gitignore at the repo root.

Never commit .dev.vars. If you accidentally commit it, rotate all secrets immediately.

Rotation Procedures

Rotating an Anthropic API key

  1. Log into console.anthropic.com
  2. Generate a new API key
  3. Copy the new key to 1Password
  4. Set the new key in Wrangler: npx wrangler secret put ANTHROPIC_API_KEY --env production
  5. The Worker picks up new secrets immediately (no redeploy needed for secrets)
  6. Test: curl https://jarvis-api-gateway.ben-c1f.workers.dev/health
  7. After 24 hours of confirmed healthy operation, revoke the old key in Anthropic console
  8. Record the rotation date in 1Password

Rotating AUTH_SECRET

AUTH_SECRET rotation requires coordinating with all clients that use it:

  1. Generate new secret: openssl rand -hex 32
  2. Update in Wrangler (staging first, test, then production)
  3. Update in all CI/CD pipelines that call the API
  4. Update in the Internal Dashboard’s stored credentials
  5. Update in any cron jobs or monitoring tools
  6. Verify all systems still healthy
  7. Record rotation in 1Password

Emergency rotation (suspected breach)

If a secret is suspected to be compromised:

  1. Immediately rotate the secret — do not wait
  2. Check access logs for unauthorized use
  3. Post in #ops-alerts: “Emergency rotation: [SECRET_NAME] suspected compromised. Rotating now.”
  4. After rotation, audit what the compromised key could have accessed
  5. File an incident report within 24 hours

Security Policy

  1. Least privilege — Each component gets only the secrets it needs. The API gateway does not have deploy keys. CI does not have the service role key.

  2. No secrets in code — Enforce with git-secrets or trufflehog pre-commit hooks.

  3. Rotate on team changes — When an engineer leaves, rotate all secrets they had access to.

  4. Audit secret usage — Quarterly review of which secrets are still needed. Remove unused secrets.

  5. Different secrets per environment — Development, staging, and production always use different credentials. Never share a production secret with a development environment.

Pre-commit Secret Scanning

expressiveCode.terminalWindowFallbackTitle
# Install trufflehog (run once)
brew install trufflehog
# Scan before committing
trufflehog filesystem . --only-verified
# Or use the git-secrets tool
git secrets --scan

Add to .git/hooks/pre-commit for automatic scanning on every commit.