Skip to content

Add crash-tested segment-store recovery - #67

Merged
flyingrobots merged 49 commits into
mainfrom
feature/crash-recovery-matrix
Jul 30, 2026
Merged

Add crash-tested segment-store recovery#67
flyingrobots merged 49 commits into
mainfrom
feature/crash-recovery-matrix

Conversation

@flyingrobots

Copy link
Copy Markdown
Owner

Closes #17.

Problem and invariant

Keep lacked an executable recovery boundary proving that every named durable transition either reconstructs the exact bytes selected by the current catalog or refuses ambiguous state.

Approach

Adds typed initialization, bounded inventory and classification, explicit discard/completion/head-finalization/resume plans, writer-authorized filesystem adapters, and a deterministic 105-case process-death matrix. CI exercises the matrix in debug and optimized profiles, and the living recovery contract records the evidence and host-power-loss limit.

Heuristic newest-artifact selection, silent truncation or repair, serializer-owned state, and a Python harness were rejected.

Failure modes and recovery

Corruption, resource excess, symlinks, namespace replacement, identity drift, conflicting pools, stale generations, and incomplete evidence produce typed refusals. Recovery transitions are explicit, ordered, retry-safe, and receipt-bearing. Host power loss and torn media remain out of scope.

Validation

  • cargo test --workspace --all-features --locked
  • cargo test --workspace --all-features --release --locked
  • all-feature and no-default-feature Clippy with -D warnings
  • cargo xtask verify
  • cargo xtask documentation-integrity-check
  • formatting, whole-history whitespace, and pure-Rust source checks

Compatibility, performance, and security

The format bytes remain unchanged; public recovery APIs and KEEP-CRASH-001 through KEEP-CRASH-035 are additive. No benchmark baseline changes or performance claims are included; inventory and fingerprinting remain bounded and streaming. Filesystem adapters use no-follow capability-relative handles, stable identity checks, exclusive writer authority, and the admitted writable non-casefolded Linux ext4 profile.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 242 files, which is 142 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ce2e268c-c690-40f1-8f84-4d83944963a6

📥 Commits

Reviewing files that changed from the base of the PR and between 3a42bd4 and 1c8937d.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • fuzz/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (242)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • Cargo.toml
  • README.md
  • conformance/segment-store/v1/README.md
  • docs/dependencies/cap-std-and-cap-fs-ext-4.0.2.md
  • docs/formats/segment-store-v1/rationale.md
  • docs/formats/segment-store-v1/recovery.md
  • docs/formats/segment-store-v1/requirements.md
  • src/adapters/admitted_recovery_stage_bytes.rs
  • src/adapters/catalog_decoder.rs
  • src/adapters/catalog_header_decoder.rs
  • src/adapters/catalog_publication.rs
  • src/adapters/catalog_snapshot.rs
  • src/adapters/catalog_transition.rs
  • src/adapters/filesystem_catalog_artifact.rs
  • src/adapters/filesystem_catalog_catalog.rs
  • src/adapters/filesystem_catalog_head.rs
  • src/adapters/filesystem_catalog_publisher.rs
  • src/adapters/filesystem_catalog_publisher_tests.rs
  • src/adapters/filesystem_initialization_namespace.rs
  • src/adapters/filesystem_initialization_storage.rs
  • src/adapters/filesystem_platform_admission.rs
  • src/adapters/filesystem_platform_admission_error.rs
  • src/adapters/filesystem_platform_profile.rs
  • src/adapters/filesystem_recovery_inventory_reader.rs
  • src/adapters/filesystem_recovery_inventory_scan.rs
  • src/adapters/filesystem_recovery_inventory_tests.rs
  • src/adapters/filesystem_recovery_namespace.rs
  • src/adapters/filesystem_recovery_next_head_candidate.rs
  • src/adapters/filesystem_recovery_next_head_finalization_open_error.rs
  • src/adapters/filesystem_recovery_next_head_finalization_storage.rs
  • src/adapters/filesystem_recovery_next_head_finalization_tests.rs
  • src/adapters/filesystem_recovery_next_head_finalization_tests/fixture.rs
  • src/adapters/filesystem_recovery_next_head_finalization_tests/namespace_laws.rs
  • src/adapters/filesystem_recovery_next_head_finalization_tests/refusal_laws.rs
  • src/adapters/filesystem_recovery_next_head_finalization_tests/replacement_laws.rs
  • src/adapters/filesystem_recovery_next_head_finalizer.rs
  • src/adapters/filesystem_recovery_segment_resume_open_error.rs
  • src/adapters/filesystem_recovery_segment_resume_storage.rs
  • src/adapters/filesystem_recovery_segment_resume_tests.rs
  • src/adapters/filesystem_recovery_segment_resume_tests/fixture.rs
  • src/adapters/filesystem_recovery_segment_resume_tests/refusal_laws.rs
  • src/adapters/filesystem_recovery_segment_resumer.rs
  • src/adapters/filesystem_recovery_segment_stage.rs
  • src/adapters/filesystem_recovery_stage.rs
  • src/adapters/filesystem_recovery_stage_completer.rs
  • src/adapters/filesystem_recovery_stage_completion_open_error.rs
  • src/adapters/filesystem_recovery_stage_completion_pool.rs
  • src/adapters/filesystem_recovery_stage_completion_storage.rs
  • src/adapters/filesystem_recovery_stage_completion_tests.rs
  • src/adapters/filesystem_recovery_stage_completion_tests/fixture.rs
  • src/adapters/filesystem_recovery_stage_completion_tests/refusal_laws.rs
  • src/adapters/filesystem_recovery_stage_completion_tests/replacement_laws.rs
  • src/adapters/filesystem_recovery_stage_discard_open_error.rs
  • src/adapters/filesystem_recovery_stage_discard_storage.rs
  • src/adapters/filesystem_recovery_stage_discard_tests.rs
  • src/adapters/filesystem_recovery_stage_discard_tests/fixture.rs
  • src/adapters/filesystem_recovery_stage_discarder.rs
  • src/adapters/filesystem_recovery_stage_error.rs
  • src/adapters/filesystem_recovery_stage_error_display.rs
  • src/adapters/filesystem_recovery_stage_materialization.rs
  • src/adapters/filesystem_recovery_stage_sync.rs
  • src/adapters/filesystem_recovery_stage_tests.rs
  • src/adapters/filesystem_store_initializer.rs
  • src/adapters/filesystem_store_initializer_tests.rs
  • src/adapters/filesystem_writer_lock.rs
  • src/adapters/filesystem_writer_lock_tests.rs
  • src/adapters/framed_blake3.rs
  • src/adapters/mod.rs
  • src/adapters/opened_reusable_segment.rs
  • src/adapters/recovery_catalog_stage.rs
  • src/adapters/recovery_catalog_stage_error.rs
  • src/adapters/recovery_entry_name.rs
  • src/adapters/recovery_entry_role.rs
  • src/adapters/recovery_fixed_field_prefix.rs
  • src/adapters/recovery_inventory.rs
  • src/adapters/recovery_inventory_error.rs
  • src/adapters/recovery_inventory_limit.rs
  • src/adapters/recovery_inventory_operation.rs
  • src/adapters/recovery_inventory_storage.rs
  • src/adapters/recovery_name_classification.rs
  • src/adapters/recovery_name_classification_error.rs
  • src/adapters/recovery_name_manifest.rs
  • src/adapters/recovery_namespace.rs
  • src/adapters/recovery_next_head_finalization_error.rs
  • src/adapters/recovery_next_head_finalization_executor.rs
  • src/adapters/recovery_next_head_finalization_outcome.rs
  • src/adapters/recovery_next_head_finalization_plan_error.rs
  • src/adapters/recovery_next_head_finalization_planner.rs
  • src/adapters/recovery_next_head_finalization_readiness.rs
  • src/adapters/recovery_next_head_finalization_receipt.rs
  • src/adapters/recovery_next_head_finalization_request.rs
  • src/adapters/recovery_next_head_finalization_storage.rs
  • src/adapters/recovery_next_head_finalization_storage_error.rs
  • src/adapters/recovery_next_head_finalization_target.rs
  • src/adapters/recovery_next_head_stage.rs
  • src/adapters/recovery_next_head_stage_error.rs
  • src/adapters/recovery_pool_name.rs
  • src/adapters/recovery_pool_name_error.rs
  • src/adapters/recovery_publication_fixed_framing.rs
  • src/adapters/recovery_publication_stage_classifier.rs
  • src/adapters/recovery_required_entry.rs
  • src/adapters/recovery_segment_classifier.rs
  • src/adapters/recovery_segment_fixed_framing.rs
  • src/adapters/recovery_segment_resume_error.rs
  • src/adapters/recovery_segment_resume_executor.rs
  • src/adapters/recovery_segment_resume_plan_error.rs
  • src/adapters/recovery_segment_resume_planner.rs
  • src/adapters/recovery_segment_resume_request.rs
  • src/adapters/recovery_segment_resume_state.rs
  • src/adapters/recovery_segment_resume_storage.rs
  • src/adapters/recovery_segment_resume_storage_error.rs
  • src/adapters/recovery_segment_stage.rs
  • src/adapters/recovery_segment_stage_error.rs
  • src/adapters/recovery_segment_truncation.rs
  • src/adapters/recovery_stage.rs
  • src/adapters/recovery_stage_assessment.rs
  • src/adapters/recovery_stage_assessment_error.rs
  • src/adapters/recovery_stage_assessor.rs
  • src/adapters/recovery_stage_byte_admission.rs
  • src/adapters/recovery_stage_byte_admission_error.rs
  • src/adapters/recovery_stage_completion_error.rs
  • src/adapters/recovery_stage_completion_executor.rs
  • src/adapters/recovery_stage_completion_plan_error.rs
  • src/adapters/recovery_stage_completion_planner.rs
  • src/adapters/recovery_stage_completion_pool.rs
  • src/adapters/recovery_stage_completion_receipt.rs
  • src/adapters/recovery_stage_completion_request.rs
  • src/adapters/recovery_stage_completion_storage.rs
  • src/adapters/recovery_stage_completion_storage_error.rs
  • src/adapters/recovery_stage_completion_target.rs
  • src/adapters/recovery_stage_discard_error.rs
  • src/adapters/recovery_stage_discard_executor.rs
  • src/adapters/recovery_stage_discard_outcome.rs
  • src/adapters/recovery_stage_discard_plan_error.rs
  • src/adapters/recovery_stage_discard_planner.rs
  • src/adapters/recovery_stage_discard_reason.rs
  • src/adapters/recovery_stage_discard_receipt.rs
  • src/adapters/recovery_stage_discard_request.rs
  • src/adapters/recovery_stage_discard_storage.rs
  • src/adapters/recovery_stage_discard_storage_error.rs
  • src/adapters/recovery_stage_evidence.rs
  • src/adapters/recovery_stage_fingerprint.rs
  • src/adapters/recovery_stage_fingerprint_algorithm.rs
  • src/adapters/recovery_stage_fingerprint_error.rs
  • src/adapters/recovery_stage_fingerprinter.rs
  • src/adapters/recovery_stage_length.rs
  • src/adapters/recovery_stage_metadata.rs
  • src/adapters/recovery_stage_metadata_error.rs
  • src/adapters/recovery_stage_parent.rs
  • src/adapters/recovery_stage_pool_outcome.rs
  • src/adapters/recovery_stage_synchronization_outcome.rs
  • src/adapters/repository_initialization_storage.rs
  • src/adapters/sealed_segment.rs
  • src/adapters/staged_segment.rs
  • src/adapters/store_initialization.rs
  • src/adapters/store_initialization_error.rs
  • src/adapters/store_initialization_phase.rs
  • src/adapters/store_initialization_receipt.rs
  • src/adapters/store_initialization_storage.rs
  • src/adapters/writer_lock_acquire_phase.rs
  • src/lib.rs
  • tests/catalog_writer_lock.rs
  • tests/recovery_inventory.rs
  • tests/recovery_inventory/inventory_double.rs
  • tests/recovery_inventory/refusal_laws.rs
  • tests/recovery_name_classification.rs
  • tests/recovery_name_classification/grammar_laws.rs
  • tests/recovery_name_classification/refusal_laws.rs
  • tests/recovery_name_classification_memory.rs
  • tests/recovery_next_head_finalization.rs
  • tests/recovery_next_head_finalization/execution_laws.rs
  • tests/recovery_next_head_finalization/planning_laws.rs
  • tests/recovery_next_head_finalization/storage_double.rs
  • tests/recovery_publication_stage_classification.rs
  • tests/recovery_publication_stage_classification/catalog_laws.rs
  • tests/recovery_publication_stage_classification/next_head_laws.rs
  • tests/recovery_segment_classification.rs
  • tests/recovery_segment_classification/refusal_laws.rs
  • tests/recovery_segment_classification/state_laws.rs
  • tests/recovery_segment_resume.rs
  • tests/recovery_segment_resume/execution_laws.rs
  • tests/recovery_segment_resume/planning_laws.rs
  • tests/recovery_segment_resume/storage_double.rs
  • tests/recovery_stage_assessment.rs
  • tests/recovery_stage_assessment/admission_laws.rs
  • tests/recovery_stage_assessment/assessment_laws.rs
  • tests/recovery_stage_completion.rs
  • tests/recovery_stage_completion/execution_laws.rs
  • tests/recovery_stage_completion/planning_laws.rs
  • tests/recovery_stage_completion/retry_laws.rs
  • tests/recovery_stage_completion/storage_double.rs
  • tests/recovery_stage_discard.rs
  • tests/recovery_stage_discard/execution_laws.rs
  • tests/recovery_stage_discard/planning_laws.rs
  • tests/recovery_stage_discard/storage_double.rs
  • tests/recovery_stage_fingerprint.rs
  • tests/recovery_stage_fingerprint/reader_laws.rs
  • tests/recovery_stage_fingerprint_memory.rs
  • tests/store_initialization.rs
  • xtask/Cargo.toml
  • xtask/src/bounded_process.rs
  • xtask/src/bounded_process/process_group.rs
  • xtask/src/durability_crash_case.rs
  • xtask/src/durability_crash_case_error.rs
  • xtask/src/durability_crash_matrix.rs
  • xtask/src/durability_crash_matrix/child.rs
  • xtask/src/durability_crash_matrix/error.rs
  • xtask/src/durability_crash_matrix/error/display.rs
  • xtask/src/durability_crash_matrix/process.rs
  • xtask/src/durability_crash_matrix/production_protocol.rs
  • xtask/src/durability_crash_matrix/production_protocol/control.rs
  • xtask/src/durability_crash_matrix/production_protocol/fixture.rs
  • xtask/src/durability_crash_matrix/production_protocol/initialization.rs
  • xtask/src/durability_crash_matrix/production_protocol/initialization_storage.rs
  • xtask/src/durability_crash_matrix/production_protocol/publication.rs
  • xtask/src/durability_crash_matrix/production_protocol/publication_storage.rs
  • xtask/src/durability_crash_matrix/production_protocol/recovery.rs
  • xtask/src/durability_crash_matrix/production_protocol/recovery_storage.rs
  • xtask/src/durability_crash_matrix/production_protocol/segment_stage.rs
  • xtask/src/durability_crash_matrix/restart.rs
  • xtask/src/durability_crash_matrix/restart/expectation.rs
  • xtask/src/durability_crash_matrix/restart/expectation/sequence.rs
  • xtask/src/durability_crash_matrix/restart/expectation/steps.rs
  • xtask/src/durability_crash_matrix/restart/semantic.rs
  • xtask/src/durability_crash_occurrence.rs
  • xtask/src/durability_crash_point.rs
  • xtask/src/durability_crash_point_identity.rs
  • xtask/src/durability_crash_position.rs
  • xtask/src/lib.rs
  • xtask/src/main.rs
  • xtask/src/protocol_conformance/workflow_tests.rs
  • xtask/src/task_error.rs
  • xtask/tests/cli_contract.rs
  • xtask/tests/durability_crash_case_contract.rs
  • xtask/tests/durability_crash_documentation.rs
  • xtask/tests/durability_crash_point_contract.rs
  • xtask/tests/durability_crash_process_contract.rs
  • xtask/tests/durability_crash_production_contract.rs
  • xtask/tests/process_policy_contract.rs
  • xtask/tests/segment_store_protocol_contract/recovery_laws.rs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Code Lawyer activity summary

# Severity Source Finding Commit Outcome
1 P2 Self Post-crash oracle failures discarded the violated invariant and expected/observed evidence 55b87c9 Precise typed diagnostics; regression GREEN
2 P2 Full gate The versioned CLI usage oracle omitted durability-crash-matrix c8cdc84 Exact command vocabulary restored; 12/12 CLI contracts GREEN
3 P2 Full gate The bounded-process contract froze obsolete pub(super) visibility after the crash harness acquired the crate-private capability 88d447a Visibility and rustdoc oracle aligned; 15/15 process contracts GREEN
4 P1 Minimal-feature gate New crash integration tests imported repository-tasks APIs without matching feature guards b0ea839 All crash contracts GREEN; no-default-feature Clippy GREEN

Final local gate: debug and optimized workspace suites, all-feature and minimal-feature Clippy, repository verification, documentation integrity, formatting, whole-history whitespace, and pure-Rust source checks are GREEN. Graft reports zero breaking changes.

@codex review please. Confirm the remediation and flag any remaining correctness, recovery, determinism, API, documentation, or maintainability defect.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity summary — hosted Linux regression

Item Priority Source File Resolution Commit Outcome
5 P1 GitHub Actions src/adapters/filesystem_writer_lock.rs Use nonblocking flock(2) for the retained read-only root directory handle; retain the regular-file lock and identity verification for writer.lock. c47a6f6 Local writer-lock laws, debug and optimized 105-case crash matrices, Clippy, full debug/release tests, formatting, and repository policy checks are green. Hosted Linux rerun pending.

The existing platform documentation already specifies process-scoped exclusive advisory locking on both the pinned root and writer file; this repair restores the implementation to that contract without changing format, API, or recovery semantics.

@codex review please

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c47a6f6b45

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/adapters/filesystem_platform_profile.rs Outdated
Comment thread src/adapters/filesystem_recovery_segment_resume_storage.rs
Comment thread xtask/src/durability_crash_matrix/child.rs Outdated
@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity summary — Linux root descriptor correction

Item Priority Source File RED evidence Resolution Commit Outcome
6 P1 GitHub Actions and Linux reproduction src/adapters/filesystem_writer_lock.rs Rust 1.96 Linux: 0/4 writer-lock laws passed; root flock returned EBADF because the capability directory is an O_PATH descriptor. Open . relative to the pinned capability with openat as `O_RDONLY O_DIRECTORY O_CLOEXEC

c47a6f6 correctly selected flock(2) but did not account for Linux O_PATH; 8514705 is a separate follow-up commit per the no-amend policy.

@codex review please

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8514705470

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/adapters/filesystem_recovery_stage_discard_storage.rs
Comment thread src/adapters/recovery_segment_classifier.rs
Comment thread src/adapters/filesystem_initialization_namespace.rs Outdated
@flyingrobots

Copy link
Copy Markdown
Owner Author

Code Lawyer activity summary — review closure

# Priority Source Finding Commit Outcome
1 P1 Self Root synchronization reused a capability descriptor that is not sync-capable on every admitted platform 1f9da85 Reopens the pinned root as a sync-capable directory; regression green
2 P1 Self Immutable-pool synchronization reused capability descriptors instead of dedicated sync-capable handles 090d0b0 Reopens exact child namespaces before durability sync; regression green
3 P1 PR Crash children synthesized filesystem states instead of executing production protocols 1fc1ad0 All 105 cases now drive production initialization, segment, publication, and recovery transitions
4 P1 PR Name-based recovery removal could unlink an unverified replacement inode 3deee9d Final removal is bound to revalidated opened evidence; replacement races refuse
5 P1 PR The only platform-admission producer rejected valid already-published stores ecf4f7e Published stores reopen through verified platform admission
6 P2 PR Existing protocol child directories escaped root filesystem-profile validation 0f7fa3d Every child is checked for filesystem, mount, inode flags, and device equality
7 P2 PR Writable recovery handoff could accept a same-inode, same-length byte substitution 4c26dc5 Exact fingerprint is recomputed before handoff and the append position is restored
8 P2 PR Corrupt short framing was misclassified as an exact truncation 430b4fb Every available fixed byte is validated before truncation admission
9 P2 Full gate Filesystem discard fixtures encoded corruption as truncation 069d7d1 Fixtures now use canonical protocol prefixes
10 P2 Full gate Finalization planner fixture encoded corruption as truncation 4015d8d Canonical next-head prefix preserves the intended refusal law
11 P2 Full gate Completion planner fixture encoded corruption as truncation 19dd003 Canonical catalog prefix preserves the intended refusal law
12 P2 Full gate Shared discard fixtures encoded corruption as truncation 8a26b6c All stage kinds derive exact prefixes from canonical fixtures
13 P1 Full gate fuzz/Cargo.lock omitted Keep's direct rustix dependency edge f88ab38 Offline Cargo regeneration changed one dependency edge; locked fuzz gates pass

All six unresolved inline review threads were resolved only after the corresponding commits were pushed.

Local evidence is green: full debug and optimized workspace suites; debug and optimized 105-case process-death matrices; all-feature and minimal-feature checks and strict Clippy; doctests and MSRV; Golden File Worldline, protocol conformance, pure-Rust source structure, pinned documentation/refusal checks, whole-history whitespace, root/fuzz deny and audit; locked fuzz build/Clippy; and the complete 9-target bounded runtime fuzz smoke with no crash, timeout, swallowed failure, or RSS-limit violation.

CodeRabbit skipped because the 244-path PR exceeds its 100-file limit and review credits are unavailable. @codex review please — confirm the current head and flag any remaining correctness, recovery, determinism, API, documentation, or maintainability defect.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity Summary — Hosted Linux Clippy repair

Issue Priority Source File Commit RED GREEN Outcome
Linux-only test helper unnecessarily owned Result values P2 GitHub Actions src/adapters/filesystem_platform_profile.rs 1c8937d clippy::needless_pass_by_value in hosted Linux quality gates Linux-target strict Clippy passed; Linux Docker tests passed 2/2; macOS strict Clippy, formatting, source-structure, and diff checks passed Fixed and pushed

The helper now borrows the result it inspects; production behavior and public contracts are unchanged.

@codex review please

@flyingrobots
flyingrobots merged commit fa105da into main Jul 30, 2026
5 checks passed
@flyingrobots
flyingrobots deleted the feature/crash-recovery-matrix branch July 30, 2026 00:05

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c8937d3fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

match self.verify_current(request)? {
RecoveryNextHeadFinalizationReadiness::Ready => self
.root()
.rename(NEXT_HEAD, self.root(), HEAD)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind head replacement to the verified candidate inode

If an external filesystem actor replaces head.next after verify_current returns but before this call, rename resolves the name again and publishes the unverified replacement as HEAD; execution then synchronizes the root and returns a receipt without revalidating the published bytes. Bind the atomic replacement to the candidate inode whose evidence was verified so a name-replacement race is refused.

AGENTS.md reference: AGENTS.md:L80-L81

Useful? React with 👍 / 👎.

pool_directory: &Dir,
pool_name: &str,
) -> Result<RecoveryStagePoolOutcome, RecoveryStageCompletionStorageError> {
match stage_directory.hard_link(stage_name, pool_directory, pool_name) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind pool links to the verified stage inode

If current.seg or current.cat is replaced after link_or_admit fingerprints it but before this name-based hard link, the replacement inode is installed under the digest-derived immutable pool name. The subsequent pool verification detects the mismatch but leaves that canonical coordinate poisoned, so retries cannot link the valid stage without manual intervention. Link the verified opened inode, or otherwise prevent an evidence mismatch from creating the pool entry.

AGENTS.md reference: AGENTS.md:L80-L81

Useful? React with 👍 / 👎.

Comment on lines +84 to +85
let inventory = FilesystemRecoveryInventoryReader::from_root(inventory_root)
.map_err(|source| FilesystemRecoveryStageDiscardOpenError::Namespace { source })?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Admit the complete namespace before recovery mutation

When the store contains an unrecoverably ambiguous inventory—for example both current.seg and current.cat, which classify_recovery_names rejects as conflicting stages—this constructor still grants mutation authority because from_root only pins the three directories and never reads or classifies their entries. A caller can therefore discard or complete one stage and destroy evidence while another incompatible history remains; require and bind an ambiguity-free inventory under the writer lock before any filesystem recovery executor can mutate state.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment on lines +31 to +33
state: RecoveryCatalogStage::Complete(catalog),
..
} => RecoveryStageCompletionTarget::Catalog {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require transitive catalog admission before pooling

For a checksum-valid catalog whose entries reference a missing segment or disagree with the named record offsets, classification produces only a ChecksummedCatalog, yet this branch authorizes immutable-pool completion from it. ChecksummedCatalog::decode verifies local framing and integrity but only admit binds entries to admitted segment bytes, so execution can remove current.cat and return a receipt claiming a valid orphan for a catalog that no reader can admit. Require pool-backed transitive catalog admission before producing the completion request.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build the durable crash-injection and recovery matrix

1 participant