SEC-009 established the convention "ALL of a site's secrets live in ~/<site>-creds/ (0700, files 0600), no loose env files in ~." But nothing ENFORCED it, and it had two blind spots that a checklist alone would not catch:
/root/netbox-secrets/api.token) has no forcing function to get pulled into the jumphost folder. It went un-consolidated until the C2 fidelity re-check needed it (SEC-009 addendum, 2026-07-15).*.env/*.token in ~ outside a *-creds/ folder -- the ORIGINAL SEC-009 exposure -- had no standing detector.Standing up DC0 and DC1 multiplies both (each mints MAAS API keys, per-DC NetBox tokens, node/edge SSH keys, OPNsense creds, tailscale authkeys on multiple VMs). The operator asked directly how we stop the spread recurring for the DCs. Answer: a manifest + an audit + a mint-time runbook step.
creds-manifests/<site>.manifest -- declares EXACTLY the secrets a site must hold: <filename> <octal-mode> <source>, where source is local or <vm>:<path> for VM-minted secrets (making the easy-to-miss class explicit and provenance-tracked). creds-manifests/vr1-office1.manifest seeded with 11 entries from the live folder; it audits CLEAN.scripts/creds-audit.sh <site> -- verifies the live ~/<site>-creds/ against the manifest: folder is 0700, every entry present with its declared mode and non-empty; flags any UNDECLARED file in the folder; and scans the home root for SPRAWL (*.env/*.token/*authkey*/*appcred*/*-cred*.txt loose outside any *-creds/). Reads NO secret values -- metadata only (stat/size), verified by a harness assertion (T7: no cat/head/tail/od/xxd in the script). Env overrides CREDS_ROOT/MANIFEST_DIR make it fully offline-testable.tests/creds-audit/run-tests.sh (7/7) -- synthetic folders under a tmp root: complete+correct -> CLEAN; missing (VM-sourced) entry -> fail; wrong mode -> fail; undeclared file -> fail; home-root sprawl -> fail; non-0700 folder -> fail; metadata-only. Auto-discovered by the gauntlet.runbooks/dc-dc-phase3-maas-enlist-deploy.md GATE now carries a non-negotiable close-out: consolidate + manifest each secret AT MINT TIME, and bash scripts/creds-audit.sh $DC MUST be CLEAN before a DC is declared done.docs/security-ledger.md -- SEC-009 ENFORCEMENT note recording the above.tests/creds-audit/run-tests.sh -> 7/7 PASS.bash scripts/creds-audit.sh vr1-office1 -> CLEAN (folder 0700, 11/11 entries present + correct + non-empty, no undeclared files, no sprawl). This also CONFIRMS the SEC-009 sandbox-token gap is now closed and tool-verified.git rm scripts/creds-audit.sh tests/creds-audit/run-tests.sh creds-manifests/vr1-office1.manifest docs/changelog-20260715-creds-audit.md (remove creds-manifests/ if now empty).git checkout HEAD -- docs/security-ledger.md runbooks/dc-dc-phase3-maas-enlist-deploy.md reverts the SEC-009 enforcement note and the runbook close-out.Nothing here reads, moves, or mutates any secret; the audit is read-only metadata inspection and the manifest holds only filenames/modes/provenance.