v0.6 session 2: state-in-backend via path binding + boot migration (#153, #154) #162

Merged
Cordy merged 1 commit from feat/v06-session2 into main 2026-08-09 04:16:52 +00:00
Owner

Closes #153 and #154.

#153 — the port, via a path-binding shim. Instead of rewriting nine store structs, statestore gains Bind/Read/Write: main binds each configured state path to the encrypted Backend at boot (s3 only), before any store opens; the stores' file I/O idiom (os.ReadFile + temp-then-rename) is swapped for statestore.Read/Write — one read-line and one write-block per store, nothing else touched. Unbound paths fall back to byte-identical local file behavior, so every existing test passes unchanged and posix instances are untouched. Bound against the RAW driver below all decorators (content encryption must not double-wrap state), sealed to recovery+deployment identities (legacy identities decrypt-only), with the ADR D3 refusal when an s3 instance has no identities. No boot reordering needed after all — the raw driver already exists before every store construction; the bind block slots right after driver creation.

#154 — migration. statestore.MigrateFile at boot, per path: local-only → upload + retire to .migrated; backend-only/fresh → no-op; identical → retire; differing → refuse to start with both SHA-256 digests and the exact operator instruction. Tested across all four cases; the shim's routing + os.IsNotExist compatibility tested too.

Also: encrypt.RecipientOf exported (state seals to the same identities content encryption trusts). goimports pass grouped imports in the generated peerpb files — cosmetic only.

Deploy note: the first boot of this release on the dogfood migrates its live state (license included) into the Garage bucket under .cairn-state/ as ciphertext, leaving .migrated files on the PVC.

Closes #153 and #154. **#153 — the port, via a path-binding shim.** Instead of rewriting nine store structs, `statestore` gains `Bind/Read/Write`: main binds each configured state path to the encrypted `Backend` at boot (s3 only), *before any store opens*; the stores' file I/O idiom (`os.ReadFile` + temp-then-rename) is swapped for `statestore.Read/Write` — one read-line and one write-block per store, nothing else touched. Unbound paths fall back to byte-identical local file behavior, so **every existing test passes unchanged and posix instances are untouched**. Bound against the RAW driver below all decorators (content encryption must not double-wrap state), sealed to recovery+deployment identities (legacy identities decrypt-only), with the ADR D3 refusal when an s3 instance has no identities. No boot reordering needed after all — the raw driver already exists before every store construction; the bind block slots right after driver creation. **#154 — migration.** `statestore.MigrateFile` at boot, per path: local-only → upload + retire to `.migrated`; backend-only/fresh → no-op; identical → retire; **differing → refuse to start** with both SHA-256 digests and the exact operator instruction. Tested across all four cases; the shim's routing + `os.IsNotExist` compatibility tested too. Also: `encrypt.RecipientOf` exported (state seals to the same identities content encryption trusts). goimports pass grouped imports in the generated peerpb files — cosmetic only. **Deploy note:** the first boot of this release on the dogfood migrates its live state (license included) into the Garage bucket under `.cairn-state/` as ciphertext, leaving `.migrated` files on the PVC.
Cordy merged commit 112a0cf3ab into main 2026-08-09 04:16:52 +00:00
Cordy deleted branch feat/v06-session2 2026-08-09 04:16:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#162
No description provided.