Property PrismDev Hub

Secrets Management

Inventory of all production secrets, where they live, who owns them, and how to rotate each one.

Updated Apr 3, 2026

Owner: Ops / Backend Lead Last Edited: April 2, 2026 Last Reviewed: April 2, 2026


1. Principles

  • No secret ever lives in the repo. .env files are gitignored. .env.example contains only placeholders.
  • All secrets are managed in Infisical as the single source of truth.
  • Infisical syncs secrets to deployment platforms (Render, Cloudflare Pages) via native integrations. Secrets are never manually edited in platform dashboards.
  • VITE_* frontend variables are public by nature — never put secrets there.
  • Break-glass access (emergency direct DB credentials, etc.) must be documented, audited, and rotated after use.

2. Infisical Organisation

Environments

EnvironmentStatusPurposeSyncs to
prodActiveProduction secretsRender (backend), Cloudflare Pages (frontend)
previewDeferredQA / preview branch buildsWill sync to preview deployment platform when branch-based QA is needed
devDeferredLocal developmentWill use infisical run --env=dev CLI injection when local .env elimination is prioritized

Folder Structure

/backend/     → Go backend secrets (synced to Render)
/frontend/    → Frontend secrets + config (synced to Cloudflare Pages)
/ops/         → Monitoring / alerting secrets (deferred — migrate when monitoring stack is productionised)

3. Secret Inventory

Backend (/backend/ → Render)

SecretOwnerSensitive?Rotation cadence
DATABASE_URLBackend LeadYes (embedded password)90 days or on compromise. Auto-rotation planned when DB migrated off Supabase
REDIS_URLBackend LeadYes (embedded password)90 days or on compromise
CLERK_SECRET_KEYBackend LeadYesOn staff change or compromise
CLERK_ISSUERBackend LeadNoOn Clerk tenant change
CLERK_JWKS_URLBackend LeadNoOn Clerk tenant change
SENTRY_DSNBackend LeadNo
SENTRY_RELEASEBackend LeadNo
ALLOWED_ORIGINSBackend LeadNo
ENVBackend LeadNo
LOG_LEVELBackend LeadNo
RATE_LIMIT_BURSTBackend LeadNo
RATE_LIMIT_PER_SECONDBackend LeadNo
STRICT_CLERK_SCOPESBackend LeadNo

Frontend (/frontend/ → Cloudflare Pages)

SecretOwnerSensitive?Rotation cadence
CLERK_SECRET_KEYBackend LeadYesOn staff change or compromise. Used by Cloudflare Pages Function (/__clerk proxy)
SENTRY_AUTH_TOKENBackend LeadYesOn compromise
SENTRY_ORGBackend LeadNo
SENTRY_PROJECT_FRONTENDBackend LeadNo
VITE_API_BASE_URLBackend LeadNo
VITE_CLERK_PROXY_URLBackend LeadNo
VITE_CLERK_PUBLISHABLE_KEYBackend LeadNo
VITE_SENTRY_DSNBackend LeadNo

Note: GIT_SHA is computed at build time by Cloudflare ($(git rev-parse --short HEAD)) and is not managed in Infisical.

Other Secrets (not yet in Infisical)

SecretOwnerCurrent locationMigration plan
Slack webhook URLsOpsgo-backend/ops/.env (local only)Move to Infisical /ops/ when monitoring stack is productionised
GRAFANA_ADMIN_PASSWORDOpsgo-backend/ops/.env (local only)Move to Infisical /ops/ when monitoring stack is productionised
METRICS_SCRAPE_TOKENOpsNot currently set in prodAdd to Infisical /backend/ when Prometheus scraping is enabled
READY_CHECK_TOKENOpsNot currently set in prodAdd to Infisical /backend/ when LB health check auth is enabled
Cloudflare Tunnel tokenOpsCloudflare dashboardConsider moving to Infisical
GitHub Actions secretsBackend LeadGitHub repo/org secretsKeep in GitHub — Infisical GitHub integration available if needed
Prism API keys (per-org)Per-org adminDatabase (api_keys table, hashed)N/A — application-managed

4. Rotation Playbooks

4.1 General Process (Infisical-managed secrets)

All secrets managed by Infisical follow this process:

  1. Rotate the credential in the upstream service (Supabase, Clerk, Sentry, Redis provider, etc.).
  2. Update the secret value in Infisical (prod environment, appropriate folder).
  3. Infisical automatically syncs the new value to Render / Cloudflare Pages.
  4. Redeploy the affected service to pick up the new value.
  5. Verify the service is healthy (/ready for backend, auth flow for frontend).
  6. Infisical's version history serves as the rotation log.

4.2 Database credentials (DATABASE_URL)

  1. Rotate password in Supabase dashboard (or new DB provider when migrated).
  2. Update DATABASE_URL in Infisical → /backend/prod.
  3. Infisical syncs to Render.
  4. Redeploy API on Render. Verify /ready returns 200.
  5. Future: Auto-rotation will be configured when the database is migrated off Supabase to a provider that supports direct Postgres access.

4.3 Clerk (CLERK_SECRET_KEY)

  1. Generate a new secret key in Clerk dashboard → API Keys.
  2. Update CLERK_SECRET_KEY in Infisical → /backend/prod AND /frontend/prod.
  3. Infisical syncs to Render and Cloudflare Pages.
  4. Redeploy both services.
  5. Verify auth flows work end-to-end (login, JWT validation, /__clerk proxy).
  6. Revoke the old key in Clerk dashboard.

4.4 Redis credentials (REDIS_URL)

  1. Rotate password in managed Redis console.
  2. Update REDIS_URL in Infisical → /backend/prod.
  3. Infisical syncs to Render.
  4. Redeploy API. Verify /ready returns 200.

4.5 Sentry auth token (SENTRY_AUTH_TOKEN)

  1. Generate a new auth token in Sentry → Settings → Auth Tokens.
  2. Update SENTRY_AUTH_TOKEN in Infisical → /frontend/prod.
  3. Infisical syncs to Cloudflare Pages.
  4. Next frontend build will use the new token for source map uploads.

4.6 Slack webhooks (local ops only — not yet in Infisical)

  1. Go to Slack workspace → Apps → Incoming Webhooks → Revoke old URL.
  2. Generate a new webhook URL.
  3. Update in go-backend/ops/.env (or Infisical /ops/ once migrated).
  4. Restart Alertmanager:
    cd go-backend/ops
    docker compose up -d alertmanager
    docker compose logs --tail=50 alertmanager
    
  5. Trigger a test alert to confirm delivery.

4.7 Prism API keys (per-org, in-app)

  1. Revoke the key via admin API: DELETE /api/v1/api-keys/{id} (requires api_keys:manage scope).
  2. Issue a new key via: POST /api/v1/api-keys with the required scopes and expiry.
  3. Distribute the new key to the service that uses it.
  4. Confirm the old key returns 401.

5. Secret Scanning

GitHub secret scanning and push protection are configured for this repo (see .github/secret_scanning.yml). Push protection blocks commits containing known secret patterns before they land.

If a secret is detected in a scan alert:

  1. Treat it as compromised — rotate immediately using the playbook above.
  2. Remove it from git history using git filter-repo or GitHub's "Remove secret" flow.
  3. Audit access logs for the affected service for the window it was exposed.
  4. Record the incident.

6. Rotation Log

Rotation evidence is now tracked in Infisical's version history per secret. Each update records:

  • Timestamp
  • Who made the change
  • Previous and new value (encrypted)

For auditing purposes, Infisical's audit log serves as the authoritative rotation record.


7. Future Work

  • Dev environment: Set up Infisical dev environment with separate Supabase project (or local Postgres). Use infisical run --env=dev for local development to eliminate .env files on disk.
  • Preview environment: Set up Infisical preview environment for QA branch builds with isolated database.
  • DB auto-rotation: Configure Infisical native Postgres rotation when database is migrated off Supabase.
  • Ops secrets: Migrate Slack webhooks, Grafana password, and metrics tokens to Infisical /ops/ when monitoring stack is productionised.
  • MAPBOX_TOKEN: Add to Infisical /backend/ when routing feature is enabled.

  • go-backend/.env.example — canonical env var reference with placeholder values
  • docs/ops/production-runbook.md — deploy and restart procedures
  • docs/security/incident-response.md — what to do if a secret is confirmed compromised
  • docs/ops/go-backend-runbook.md — Slack/Alertmanager restart steps