07-secrets-and-config.md
markdown
sha256:7d5985ef251de9f0154f9b185a75cf36174bf73e0c34f5eca133e7bd20224bf4
Merge branch 'feat/opengraph-repo-cards' into dev
Human
22 days ago
Section 7 — Secrets and Application Configuration
Companion to
musehub-production-readiness-checklist.md.
Full secrets inventory (corrected, see docs/infrastructure.md)
| Secret | Purpose | Where it lives today |
|---|---|---|
DB_PASSWORD |
Postgres auth | Hand-provisioned .env, per instance |
WEBHOOK_SECRET_KEY |
Fernet key for webhook signing | Hand-provisioned .env; also in SSM (/musehub/staging/) |
RUNNER_TOKEN |
musehub-runner CI auth |
Hand-provisioned .env |
BLOB_STORAGE_ACCESS_KEY_ID / _SECRET_ACCESS_KEY |
Cloudflare R2 API credentials | Hand-provisioned .env |
WORKER_INTERNAL_KEY |
Cloudflare Worker → MuseHub callback shared secret | Hand-provisioned .env; also in SSM |
PACK_WORKER_URL |
Public URL of the mpack-receiver Worker | In SSM only (non-secret config, stored as SecureString anyway) |
No OAuth client secrets, no payment provider keys, no email provider keys — none of those integrations exist (Section 0).
Checklist assessment
- [x] Inventory all secrets. — done, above.
- [x] Remove secrets from source control and repository history. — confirmed via grep, no secrets committed;
.envis never tracked. - [ ] Store secrets in AWS Secrets Manager or SSM Parameter Store as appropriate. — partially drafted, not live.
deploy/secrets.shimplements this correctly but only 3 of 7 required parameters actually exist in SSM, and the script would fail its own preflight check against the current live state. This is the actual work item for this section. - [ ] Encrypt secrets with KMS. — the 3 SSM params that do exist are SecureString (KMS-encrypted by default); the rest aren't in SSM at all yet.
- [x] Use separate staging and production secrets. — confirmed: separate
.envper instance, separate R2 buckets (musehub-staging/musehub-prod), separate SSM path prefixes (/musehub/<env>/). - [ ] Give workloads access only to the secrets they require. — the app reads its own
.envwholesale; no per-secret access scoping exists (nor would it, for a single-process app on one instance) — likely N/A given the architecture, but flagging rather than assuming. - [x] Do not expose production secrets to pull-request workflows. — N/A, no GitHub Actions/PR workflows exist; MuseHub-native CI (Section 9) doesn't exist yet either, so there's nothing to expose secrets to yet.
- [ ] Do not print secrets in logs. — not verified in this pass; would need a log-content review once Section 12's centralized logging exists (currently no logs are collected at all, so nothing to audit yet).
- [ ] Configure secret rotation where supported. — not done.
- [ ] Rotate credentials during the production launch. — not done; deferred to Section 18 (Cutover Plan).
- [ ] Document emergency rotation procedures. — not done.
- [x] Separate secrets from nonsecret configuration. —
musehub/config.py'sSettingsclass clearly separates secret fields (db_password,blob_storage_secret_access_key, etc.) from operational config (rate limits, quotas, timeouts) — this is already well-structured in code, even though the deployment-time delivery mechanism (hand-provisioned.env) isn't hardened yet. - [x] Validate required configuration at application startup. —
pydantic_settings.BaseSettingsdoes this by construction; missing required fields fail at import/startup, not at first use. - [x] Fail safely when critical configuration is missing. — same mechanism; also
deploy/secrets.sh's own preflight check (dieon missingDB_PASSWORD) is a fail-safe for the SSM path specifically, once that path is actually used. - [x] Remove default credentials and sample keys. — no default/sample secrets found in
config.py(secret fields default toNone, not placeholder values); the backup script's weak-password check (musehub,changeme123, etc.) insecrets.shis a good sign of intent here even though that script isn't live yet. - [ ] Audit OAuth callback URLs and API allowlists for production. — N/A, no OAuth exists (Section 0).
- [ ] Audit every external webhook secret. —
WORKER_INTERNAL_KEYis the one webhook-adjacent secret (Cloudflare Worker callback); not independently audited in this pass — needs a closer look at howmusehub/worker.pyvalidates it. - [ ] Document ownership and rotation frequency for every production secret. — not done; blocked on Section 1's ownership-recording work generally.
The actual work item here
Wire deploy/secrets.sh in for real: populate the missing SSM parameters (DB_PASSWORD,
BLOB_STORAGE_ACCESS_KEY_ID, BLOB_STORAGE_SECRET_ACCESS_KEY, RUNNER_TOKEN) for staging, run
secrets.sh against staging to prove the pipeline actually works end-to-end, then decide (per
Section 0's open item) whether production adopts this from its very first deploy rather than
repeating staging's hand-provisioning. This is real infrastructure work, correctly deferred to the
build phase per the doc-first workflow.
File History
1 commit
sha256:be1b2fdf6ab1fc652b3b35a945d0277a36fbf5d96e63692020d36cd7ebe03534
Merge 'docs/security-monitoring-verified' into 'dev' — prop…
Human
2 days ago