Public: anyone can read this; the crew can change it.
secret.key leaves the snapshot bucket: whoever reads the bucket must not hold the key and the data together #366
Check · Review · Land · Live done — Landed and live in production.
Snapshots no longer put the raw `secret.key` in the bucket. `test/snapshot.test.ts` and `test/web.test.ts` pass. I did not get `bun x tsc --noEmit` to run here (it fails with "Cannot find type definition file for 'bun'"), so the full `forge.json` check has not been run.
shipped production is serving it deploy 9f16946
Sign in to join this conversation.
new above
offline
Snapshots no longer put the raw
secret.keyin the bucket.test/snapshot.test.tsandtest/web.test.tspass. I did not getbun x tsc --noEmitto run here (it fails with "Cannot find type definition file for 'bun'"), so the fullforge.jsoncheck has not been run.What changed
FORGE_SNAPSHOT_PASSPHRASEset, a snapshot writessecret.key.wrappedinstead (newsrc/snapshot/wrap.ts). It is AES-256-GCM under a scrypt-derived key and uses onlynode:crypto, so there is no new dependency. Each snapshot checks the wrapped key opens before it is written.keyfield (wrapped,none, orrawfor older snapshots).- With the right passphrase,
secret.keyis rebuilt at mode 0600 and sealed values open. - A wrong passphrase refuses the restore before anything is written. - With no passphrase, repos, issues and app data restore. The command lists every sealed value by name (NAME (app slug)orNAME (scope secret)) that must be set again. The restored forge makes a new key on first boot.docs/SNAPSHOT.mdhas a new "The key" section covering where the passphrase lives and what is lost without it.docs/EXTRACT.mdnow has the restore command with the passphrase.What I left out
To try it
Take a snapshot from Settings → Backups, then run
FORGE_SNAPSHOT_PASSPHRASE=… bun run src/snapshot/restore.ts <name> <empty-dir>with the sameFORGE_SNAPSHOT_DIR.🤖 Generated with Claude Code
Closes #337