SOP-004 — Secrets management (add / rotate / scope)
Runbook · owner: Operations (Process Engineer) + Security (planned). Policy:
hr/policies/security.md. Layer: SOP/Runbook (docs/canon.md).
Purpose
Add, rotate, and scope secrets through managed stores — never the repo — so CI and the app can use credentials safely and auditably.
The stores (managers)
- GitHub Actions encrypted secrets — for workflows. Scope production-only
secrets with a GitHub Environment (e.g.
production) when appropriate. - Vercel project environment variables — for the intranet runtime.
- Process env — for local/agent runtime.
Register of org secrets
| Secret | Used by | Store | Status |
|---|---|---|---|
ANTHROPIC_API_KEY |
daily-reports workflow | GitHub Actions secret | set by Principal to enable |
NOTION_TOKEN |
daily-reports + session-end hook | GitHub Actions secret / env | set by Principal to enable |
NOTION_REPORTS_PAGE |
daily-reports workflow | GitHub Actions secret | set by Principal to enable |
NOTION_SESSION_LOG_PAGE |
session-end hook | env | optional |
Add or rotate a secret
- Need + scope — file an access request (SOP-001); least privilege.
- Store it in the right manager:
- GitHub: Repo → Settings → Secrets and variables → Actions (or an Environment for prod-scoped). Never paste a secret into code, a PR, an issue, a log, or a doc.
- Vercel: Project → Settings → Environment Variables.
- Reference it as
${{ secrets.NAME }}(Actions) orprocess.env.NAME; keep the consumer gated (no-op when the secret is absent). - Record the grant in
hr/access/requests.md— that it exists and where — never the value. - Rotate on suspected exposure: revoke at the provider, replace in the store, update the register’s date.
Guardrails
- A leaked secret is revoked first, then replaced — do not just delete the commit.
- CI logs are public-ish; secrets are masked by GitHub but never
echothem.