SEC-3: secrets threat model + reviewer FAQ (docs only) #54

Merged
plat merged 1 commit from feat/sec-3-secrets-threat-model into main 2026-07-01 17:05:47 +00:00
Owner

SEC-3 (roadmap #45): secrets threat model + reviewer FAQ

Doc-only. Adds docs/security/secrets-threat-model.md so a reviewer can state what decrypts what, who sees plaintext & when, how rotation/backup work, and why Vault is deferred — without reading source.

Covers (all anchored to real code):

  • Sovereignty invariant — every clusters/** sops value sealed to the one fork key; enforced empirically by fork_verify_all_sealed (bin/lib.sh:338). Includes a "what decrypts what" table.
  • Plaintext exposure windows — exactly three: operator workstation at seal time (bin/lib.sh:180/207), the transient admin-run sync-env CI job (_app-template/.forgejo/workflows/sync-env.yml:100, mcp/src/secrets-cli.ts → syncAppEnv mcp/src/server.ts:1829), and the running app pod. Nowhere else (Forgejo secrets are write-only).
  • dev/prod PLAT_DEV boundary — prod-only vs agent-readable dev overlay (mcp/src/secrets-cli.ts:141, mcp/src/server.ts:1892/1911).
  • Rotation/backup posture (post-SEC-1) — custody gate fork_backup_key (bin/lib.sh:681), lock-out-safe rotate_age_key (bin/lib.sh:809).
  • Vault non-decision — moves+multiplies the SPOF, adds stateful risk, breaks self-replication; revisit triggers: multi-operator quorum, secret TTLs, dynamic/leased creds.

Closes #45.

🤖 Generated with Claude Code

## SEC-3 (roadmap #45): secrets threat model + reviewer FAQ Doc-only. Adds `docs/security/secrets-threat-model.md` so a reviewer can state **what decrypts what, who sees plaintext & when, how rotation/backup work, and why Vault is deferred — without reading source.** **Covers (all anchored to real code):** - **Sovereignty invariant** — every `clusters/**` sops value sealed to the one fork key; enforced empirically by `fork_verify_all_sealed` (`bin/lib.sh:338`). Includes a "what decrypts what" table. - **Plaintext exposure windows** — exactly three: operator workstation at seal time (`bin/lib.sh:180/207`), the **transient** admin-run `sync-env` CI job (`_app-template/.forgejo/workflows/sync-env.yml:100`, `mcp/src/secrets-cli.ts` → `syncAppEnv` `mcp/src/server.ts:1829`), and the running app pod. Nowhere else (Forgejo secrets are write-only). - **dev/prod PLAT_DEV boundary** — prod-only vs agent-readable dev overlay (`mcp/src/secrets-cli.ts:141`, `mcp/src/server.ts:1892/1911`). - **Rotation/backup posture (post-SEC-1)** — custody gate `fork_backup_key` (`bin/lib.sh:681`), lock-out-safe `rotate_age_key` (`bin/lib.sh:809`). - **Vault non-decision** — moves+multiplies the SPOF, adds stateful risk, breaks self-replication; revisit triggers: multi-operator quorum, secret TTLs, dynamic/leased creds. Closes #45. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
One-page account of the sealed-git secrets model: the one-key sovereignty
invariant, who sees plaintext and when (workstation seal / transient sync-env CI
job / running pod), the dev/prod PLAT_DEV scope boundary, the post-SEC-1
rotation+backup custody posture, and the explicit Vault non-decision plus its
revisit triggers. Anchored to bin/lib.sh fork_*/rotate_age_key, mcp
secrets-cli/syncAppEnv, and _app-template sync-env.yml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
plat merged commit 5f529ba17a into main 2026-07-01 17:05:47 +00:00
Sign in to join this conversation.
No description provided.