# Secret Management Runbook **Status:** Stub — populate as part of Phase 1.F.12 **Owner:** Platform team **Source pattern:** [`learning_ai_notes/docs/runbooks/SECRET_MANAGEMENT.md`](../../../../../learning_ai_notes/docs/runbooks/SECRET_MANAGEMENT.md) (commit `bcad7d3`) --- ## Purpose This runbook documents how secrets flow from **Azure KeyVault → env → process** for tracker-web (Next.js client/server) and the platform-service backend it proxies, and how to rotate them safely. --- ## Secret Inventory | Secret | Used by | Storage | Rotation cadence | | ----------------------------------- | ----------------------------------------- | --------------------------------------- | ---------------------------------------------------- | | `JWT_SECRET` | platform-service + tracker-web API routes | KeyVault `bytelyst-jwt-secret` | Quarterly | | `TRACKER_MEK_ID_` | tracker-service field encryption | KeyVault per-product MEK keys | Quarterly (see [MEK_ROTATION.md](./MEK_ROTATION.md)) | | `POSTHOG_KEY` | tracker-web client-side telemetry | KeyVault `tracker-posthog-key` | On compromise only | | `COSMOS_CONNECTION_STRING` | platform-service Cosmos client | KeyVault `bytelyst-cosmos-conn` | On compromise only | | `VALKEY_PASSWORD` | platform-service session/cache | KeyVault `bytelyst-valkey-password` | Quarterly | | `TURNSTILE_SECRET` (Phase 1.4) | tracker-web public submission CAPTCHA | KeyVault `tracker-turnstile-secret` | On compromise only | | `GITHUB_WEBHOOK_SECRET` (Phase 3.3) | tracker-service inbound webhook HMAC | KeyVault `tracker-gh-webhook-secret` | On compromise only | | `GITEA_WEBHOOK_SECRET` (Phase 3.3) | tracker-service inbound webhook HMAC | KeyVault `tracker-gitea-webhook-secret` | On compromise only | | Agent API keys (Phase 3.1) | end-user-managed; stored hashed in Cosmos | Cosmos `apikeys` collection | User-managed | --- ## Resolution Path ``` KeyVault → Docker build args (NEXT_PUBLIC_*) → baked into next-build ╲ → docker-compose env_file → process.env at runtime ↘ systemd EnvironmentFile → process.env at runtime ``` - **Build-time secrets** (`NEXT_PUBLIC_*`) are baked into the Next.js standalone build via Dockerfile `ARG` + `ENV` (Phase 1.C.3 / 1.2). Once baked they are visible in client JS; only put truly public-safe values here. - **Runtime secrets** flow via docker-compose `env_file` or systemd `EnvironmentFile` so they are not visible in client bundles. - **No secret ever** appears in `git`, `.env.example`, log lines, or container `inspect` output. --- ## Rotation Procedure > **TODO** — adapt full procedure from `learning_ai_notes/docs/runbooks/SECRET_MANAGEMENT.md` > once tracker-service ships secret-aware deployment in Phase 1.F. 1. **Create new secret version in KeyVault** 2. **Update env source** (docker-compose `.env`, systemd unit, or CI/CD secret store) 3. **Rolling restart** affected services 4. **Verify** — `pnpm run smoke:local` passes against rotated stack 5. **Revoke previous secret version** in KeyVault after 24 h soak --- ## On Suspected Compromise 1. **Immediately revoke** the suspected secret in KeyVault 2. **Rotate** all dependent secrets in the same blast radius 3. **Force-revoke** all JWT tokens (bump `JWT_SECRET` → all sessions invalidated) 4. **Audit** access logs since suspected compromise window 5. **File a tracker bug** type `chore`, label `security`, priority `critical` --- ## PII Scrubbing Rule Per Phase 1.F.10: emails, names, and any field marked `pii: true` in the schema must NEVER appear as plaintext in: - Log lines (use `@bytelyst/logger` redaction map) - Telemetry events sent to PostHog - Error messages bubbled to clients - Webhook delivery logs (Phase 3.4 / 3.5) --- _See [`MEK_ROTATION.md`](./MEK_ROTATION.md) for field-level encryption key rotation specifically._