docs/security/keys.md: every key the project depends on (the folder, the gh
keyring, the Vercel env of three projects, the GitHub secrets) with where it
lives, what it unlocks, the blast radius lost and leaked, who rotates it and
the rotation status, written from the files and the scripts that read them.
No value, no private fingerprint. Section 4: the second OTA signing key kept
offline, the app change (a key list plus revocation in the manifest), 0.3.9
as the carrier, and the emergency path if the one key leaks today (a manifest
signed with a new key is useless to 0.3.x apps; the mitigation in order).
tools/keys/backup.sh: ~/Desktop/igneum-keys-<date>.dmg, AES-256, hdiutil's
own prompt (never argv, history or a file), the folder minus build-slots,
dlsite-dir and pytools/, plus a README; attached read-only, every file
compared by sha256, listed, detached. --dry-run lists. restore.sh: --check
compares the image against the live folder without printing values, --to
copies back with 0600/0644 and 0700. test-backup.sh: the end-to-end test on a
scratch folder with a throwaway passphrase, 8 steps, passed.
tools/ci/no-secrets-check.sh, in ci.yml: no tracked file named like a key of
~/.config/igneum, no 64-hex value assigned to a token/key/secret name outside
tests and the allowlist (the OTA public key, the published Hardhat and Anvil
accounts); a --self-test fires on a known-bad tree first. 776 files, 0 hits.
Also: ~/.config/igneum, vercel/ and txgen/ are 0700 now (were 0755).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>