Skip to content

run-redaction: crash between parent retirement and child realign permanently fail-closes the lineage #652

Description

@solomonneas

Post-merge grading review of #644 (PR for #638) found one Major crash window introduced by the new retirement digest cross-check.

In _retire_rewritten_digest_aliases (src/brigade/run_redaction.py) the parent record is rewritten (adding rewritten_digest_retired_by) before _realign_child_parent_record_digest runs. A crash between those two fsync'd writes leaves the child's parent_record_sha256 pinned to the parent's pre-retirement digest. The new cross-check in _load_operation_inventory (child_record.get("parent_record_sha256") != record_digests.get(operation_id)) then raises "redaction transaction state/record mismatch" on every subsequent inventory load, including the retry that would have realigned it. Pre-#644 this state was recoverable; now it requires manual record surgery. Quarantine data stays intact, so this fails closed, but redaction is the safety-critical path and a permanent fail-closed lineage with no automated repair is not acceptable.

Fix: tolerate the parent's pre-retirement record digest during the split window (accept either digest while a retirement marker is mid-flight), or realign-on-load. Add a crash-injection test that kills between the two writes and asserts the next inventory load succeeds and completes the realignment.

Also fold in (Minor): the no-op early return added to _refresh_chained_anchors happens before _assert_active_owner, dropping the ownership assertion on the read-only pass.

From the post-merge grading review of PR #644. Refs #638.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions