Ledger · overnight-content-sealing
The orchestrator reviewed rollback compatibility and requires this correction before implementation. Replace automatic conversion on app boot with TWO DEPLOYMENT PHASES using one compatibility-capable release. No key default in production. Schema columns and key-check marker table present. Normal startup reads marker: absent => legacy compatibility mode (legacy reads/writes and visible operator diagnostic that sealing not activated); present => verifies key O(1), runtime reads/writes only encoding1 and rejects plaintext rows. An explicit offline maintenance command, with server and replication stopped by operator, verifies/converts rows transactionally and writes activated key-check marker, then optionally performs scrub as separate operation. Restarts read activated marker and cannot downgrade. Before activation, the deployed compatibility release is smoke-tested, its exact release retained as rollback target, and secret/fingerprint/recovery verified. Same release supports both legacy and sealed states; rollback to plaintext-only pre-compatibility releases is forbidden. No fresh release needed to activate. Keys and historical backups preserved. Restored preconversion backup is explicitly observed as legacy mode and requires maintenance activation again (never silently claim encrypted). All crypto and read-boundary corrections from prior review unchanged. This temporarily supports legacy rows only in the pre-activation database state. The spec runtime encoding1-only invariant applies to activated databases, with tests covering marker downgrade/unknown-state fail-closed. Missing marker on nonempty encrypted DB fails startup, never reinterprets ciphertext as legacy. No production changes yet. Please APPROVE this amended implementation spec or give blockers, <=400 words. No file reads needed beyond already reviewed context.
Accepting your blocker and pins, with implementation before any deploy: - Both legacy update insertion and legacy snapshot insertion re-read activation marker inside their existing write transaction and refuse if present. This covers a stale preactivation process racing offline conversion; no plaintext row can commit after marker activation. Cipher mode remains fixed per process and cannot auto-switch. - Production validates configured content key before DB opening in BOTH modes. Development alone may use fixed dev key. - Activated startup verifies marker keycheck then checks for any content_encoding !=1 and refuses before serving. Fingerprint mismatch is a distinct fixed operator error, separate from AEAD failure. No content bytes in errors. - Explicit maintenance only (never startup) rerun on activated DB verifies all already-sealed rows, converts remaining encoding0 rows atomically and rejects unknown encodings; keeps original marker/keycheck/fingerprint unchanged even on failure. Marker remains unchanged after scrub except its scrubbed bookkeeping bit. Tests pin these properties. This is an explicit maintenance repair, never runtime downgrade. Mixed-state boot error identifies the docs-seal command. - Legacy diagnostic is Error at every boot, with structured encoding and fingerprint fields, no UI strings. No deactivate verb or marker-removal code. docs-seal uses only explicit DB path, production content key env and expected fingerprint guard; it never binds a listener or starts replication. Operator stops server/replicator; the transaction check additionally prevents stale legacy writers from violating activation. The prepared conversion helpers are not called anywhere in server startup. Please confirm APPROVE of this amended spec before runtime wiring. <=200 words. Same independent model identity and scope as prior review.
Independent whole-branch review, read-only. Model Claude Fable. Review the complete Docs overnight-content-sealing branch versus origin/main, not only its last commit. Checkout /home/paulca/amadan.net/oficina/docs/.claude/worktrees/overnight-content-sealing. Read AGENTS.md. Root coordinates merge/deploy; no production mutations or private-data inspection allowed. This implements the approved content-sealing spec and final rollout amendment. Spec history is in /tmp/oficina-docs-sealing-spec-review.txt, /tmp/oficina-docs-sealing-spec-revision.txt, /tmp/oficina-docs-sealing-spec-rollout.txt and /tmp/oficina-docs-sealing-spec-rollout-pins.txt. Explicit final APPROVE by claude-fable-5-1 session 8aa40554-38b1-4597-9cb8-439ab594e268 is /tmp/oficina-docs-sealing-spec-rollout-pins.json. Amadan docs39 tracks this work. Scope: AES-GCM sealing only document update and snapshot bodies; separate production DOCS_CONTENT_KEY; authenticated immutable GUID/seq/kind/ABI; additive encoding + activation marker migration; pre-activation legacy compatibility runtime; marker/key/mixed-encoding startup checks; legacy transaction guards against writes after activation; decryption at Store replay/snapshot and sync GET boundaries; explicit docs-seal subcommand with DB path/expected fingerprint, no server or replication startup; atomic conversion/repair; explicit checked WAL/VACUUM scrub. No UI strings changed. Titles/other metadata and historical plaintext backups are outside this body-sealing scope and are not claimed encrypted. Historical backups preserved. Rollout: deploy compatibility-capable release with production key first, smoke it and retain that exact binary as rollback target; only then stop server/replicator and perform explicit conversion/scrub. Same binary works after activation. Never rollback to plaintext-only precompatibility release. Operator must rerun scrub on every restored copy; scrubbed marker is not proof about a restored DB's raw pages. No deactivate verb. Tests include real process-exit rollback, raw SQLite/WAL canary, pinned-reader checkpoint refusal, restored DB/key/content rehearsal, real HTTP encrypted round trip/snapshot/tamper refusal, stale legacy Store and snapshot refusal, mixed boot/repair and immutable marker, production key requirement, explicit CLI and unknown/deactivate rejection. Eight runtime mutations were observed red: write sealing, snapshot sealing, sync decryption, stale guard, mixed boot, repair, legacy diagnostic, CLI dispatch. Earlier cipher/migration/scrub/crash/key-binding mutations were also observed red. Raw new evidence /tmp/oficina-docs-runtime-mutations.txt and -followup.txt. Initial invalid compile-only mutation was corrected and is not counted as evidence. Current final test/CI evidence will be supplied by coordinator with exact commit. Focus on all persistence read/write paths, snapshot fallback confidentiality, transaction boundaries, activation races, CLI startup separation, operator diagnostics, schema/rollback compatibility, crash/error handling and tests that could pass despite missing behavior. Read complete branch, do not infer approval from the plan or tests. Return APPROVE or REQUEST CHANGES with severity, file/line and concrete reason. State actual model identity and review scope. Do not implement fixes or deploy.
Please complete the whole-branch review by reading the exact complete diff now available at /tmp/oficina-docs-sealing-complete.diff. It is generated by git diff origin/main...HEAD and contains ALL branch changes, including the new follow-up commit after094accf. Prior approval was appropriately limited because Read/Grep/Glob had no git-diff access. Read this diff and any referenced source needed before reaffirming complete-branch approval. Both medium test gaps closed: TestStaleLegacyStoreRefusesSealedUpdatesAndSnapshots uses the actual stale Store snapshot read and HTTP raw-update GET; TestContentStartupRejectsPlaintextSnapshotWithoutLegacyUpdates tests the snapshot-only mixed database. Each relevant guard was removed separately and the tests failed behaviorally: legacy update GET200; legacy snapshot readnil; plaintext snapshot bootnil. /tmp/oficina-docs-review-gap-mutations.txt records this; guards restored exactly, focused tests pass. Earlier extra mutation evidence /tmp/oficina-docs-runtime-extra-mutations.txt covers production boot key validation, explicit CLI inputs and activated repair atomicity. Approved technical spec now lives at docs/superpowers/specs/2026-09-07-content-sealing.md. Removed stale plaintext-scope comments and the false PRODUCT assertion that no plaintext-grep test exists. No new product claims or UI copy; no operator runbook prose added because shared copy has a separate review gate. Root owns concrete rollout evidence, key provision, compatible rollback binary and canary. Scope remains only update/snapshot bodies, not metadata/historical backups. Do not change files or deploy. Return APPROVE or REQUEST CHANGES for the complete diff with actual model identity. Remote CI passed094accf; new exact-head gate is running and will separately be required before merge.