feat: FUSE and WinFsp Rust integration with grant-root awareness and SDK-owned read chain#594
Conversation
Entire-Checkpoint: ce707f2e5696
Entire-Checkpoint: 60948f3771cf
Entire-Checkpoint: 5cea888ff254
Entire-Checkpoint: 5ea0a6ce1d31
Entire-Checkpoint: 5ab720b56e40
Entire-Checkpoint: 449f632ec08b
- Add crates/core/tests/node_codec_vectors.rs referencing cipherbox_core::node::* - Loads tests/vectors/node-codec.json body_vectors, asserts non-vacuous count guard - RED: fails to compile since crates/core/src/node/ does not yet exist
…json - Add crates/core/src/node/ module: Node/NodeKind/NodeContent/VersionEntry enum + types mirroring packages/core/src/node/types.ts - SealedChildRef frozen NODE-03 five-field set, deny_unknown_fields, no write field; WriteChildRef/NodeWriteBody write-plane types for wave-6 D-07 - encode_node/decode_node produce fixed-field-order JSON byte-identical to tests/vectors/node-codec.json body_vectors (D-04 cross-language KAT) - encode_published_node/decode_published_node for the PublishedNode envelope (opaque readSealed/writeSealed strings; AEAD sealing wired in a later plan) - Additive: crates/core/src/folder.rs untouched, cargo check --workspace green
- Add 69-01-SUMMARY.md documenting the Node/SealedChildRef/PublishedNode codec implementation and KAT verification
Entire-Checkpoint: ad7454c489b8
…aterStore - Port packages/sdk/src/state/rotation-high-water.ts to crates/sdk/src/rotation/high_water.rs - HighWaterStore trait with async get/put; RotationHighWater generic over two injected stores - enforce_resolved: validate-live-input then generation-floor then cold-device-or-seq-floor then bump both, exact TS ordering - RotationError enum (thiserror): GenerationRegression, SequenceRegression, InvalidFloorValue - 10 unit tests over an in-memory HashMap-backed store mirroring client-rotation.test.ts scenarios
- Add SentShareResponse/SentSharesPage DTOs mirroring the server's SentShareResponseDto/PaginatedSentSharesDto field-for-field - Add list_sent_shares (single page) and collect_sent_shares (pages until total is reached) mirroring revoke_shares_for_items's authenticated-GET/error-handling shape - Extract should_fetch_next_page as a pure, unit-testable termination check so pagination cannot spin on an empty/misreported page - This is the client-side source of activeGrantRootIpnsNames for the grant-root awareness work
… (D-03) - JsonSidecarFloorStore implements HighWaterStore over a single JSON sidecar file - Atomic write path: temp file + rename, 0600 perms via OpenOptionsExt (mirrors queue.rs) - for_generation/for_seq constructors give each floor its own independent sidecar file - floor_store_restart test proves the floor survives struct drop + recreate over the same path - No new storage dependency (D-03: sled/redb/rusqlite rejected)
- Add 69-02-SUMMARY.md documenting the RotationHighWater gate and JsonSidecarFloorStore port
Entire-Checkpoint: 8bb67b1ad83b
- Load tests/vectors/crypto/node-aad.json seal_vectors + aad_vectors - RED: references cipherbox_core::node::seal which does not yet exist - Covers round-trip, AAD KAT conformance, transplant resistance, fail-closed malformed node_id, and fresh-IV-per-seal
- seal_node/unseal_node (role 0x01 read-body) and
seal_child_read_key/unseal_child_read_key (role 0x02 child-readkey)
wrap cipherbox_crypto::aes::{seal_aes_gcm_aad,unseal_aes_gcm_aad,
build_node_aad} directly
- seal_child_write_key/unseal_child_write_key (role 0x04) added for
D-07 dual-keying prep, mirroring packages/core/src/node/seal.ts
- add NodeError::SealFailed(#[from] CryptoError); pub mod seal in
node/mod.rs
- terminal-owner rule: no caller-supplied or returned buffer is zeroed
…cate - add crates/sdk/src/rotation/scope.rs with RED-phase stubs (todo!()) for has_covering_grant + maybe_rotate_on_scope_exit - add spy-based #[test]/#[tokio::test] cases mirroring packages/sdk-core/src/__tests__/rotation/scope.test.ts (private -> 0 rotate calls, covered -> exactly 1, T-63-17 anti-malicious-relay cross-check) - wire pub mod scope into rotation/mod.rs and re-export from lib.rs - add RotationError::RotateFailed variant for fail-closed rotate() error propagation
- has_covering_grant: leaf-first scan; true if any ancestor is in active_grant_root_ipns_names OR equals local_grant_record.root_ipns_name (anti-malicious-relay cross-check, T-63-17) - maybe_rotate_on_scope_exit: invokes the injected rotate closure exactly once for a covered scope exit, zero times for a private mutation (ROT-02 short-circuit); rotate errors propagate as Err, never swallowed - all 16 spy-based unit tests pass (cargo test -p cipherbox-sdk rotation::scope) - cargo check --workspace green
- add 69-05-SUMMARY.md documenting has_covering_grant + maybe_rotate_on_scope_exit RED/GREEN TDD execution, 16 passing tests, cargo check --workspace green
Entire-Checkpoint: 0adbc7a285c3
- Add crates/fuse/src/write_ops/grant_scope.rs: ancestor_ipns_chain walks parent_ino from a mutated inode up to ROOT_INO over the already-mounted InodeTable, leaf-first, zero network calls - build_coverage_params + grant_root_for wrap cipherbox_sdk::rotation::scope::has_covering_grant (69-05) rather than reimplementing the predicate - Declare grant_scope as any(fuse, winfsp) in write_ops/mod.rs and widen lib.rs's write_ops module gate to the same cfg so the Windows write handlers (69-14) can reach the same module (Pitfall 1)
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. 💤 Files selected but had no reviewable changes (3)
⛔ Files ignored due to path filters (1)
⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR advances Phase 69 to 25/25 plans completed. It adds desktop vault root-key wiring, CI grep gates, and a large set of Phase 69 planning, research, validation, security, and verification documents covering the node/v3, grant-root, rotation, and WinFsp migration work. ChangesDesktop vault and CI gating
Phase 69 planning and execution tracking
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Release Preview
Cascade Details
|
Greptile SummaryThis PR moves the desktop FUSE and WinFsp paths onto the shared Rust node read chain. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (6): Last reviewed commit: "docs(69): retire bump-ipns-sequence defe..." | Re-trigger Greptile |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #594 +/- ##
==========================================
+ Coverage 65.89% 73.74% +7.84%
==========================================
Files 153 192 +39
Lines 14551 28119 +13568
Branches 1700 1700
==========================================
+ Hits 9589 20736 +11147
- Misses 4717 7138 +2421
Partials 245 245
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…areness' of https://github.com/FSM1/cipher-box into feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness
Entire-Checkpoint: 4340dd7e937a
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/desktop/src-tauri/src/commands/vault.rs (1)
115-278: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy liftPartial vault initialization can strand retries on the same IPNS names.
initialize_vaultis called for new users and again when an existing user hits a 404 inapps/desktop/src-tauri/src/commands/auth.rs, so a failure after the two deterministic IPNS publishes but before/vault/initleaves later attempts stuck on the samePublishResult::Conflictpath. Handle self-conflicts as idempotent recovery instead of aborting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/desktop/src-tauri/src/commands/vault.rs` around lines 115 - 278, initialize_vault can fail after successfully publishing the deterministic IPNS records, causing retries to hit PublishResult::Conflict and abort even though the vault was already partially created. Update initialize_vault to treat self-conflicts on the vault key and root folder publishes as idempotent recovery: when publish_ipns returns Conflict in these branches, verify the existing record matches the expected content/sequence and continue instead of returning an error. Use the existing publish_ipns, create_ipns_record, and the two publish branches in initialize_vault to locate the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
@.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-21-PLAN.md:
- Around line 143-144: The threat model table has a malformed row that is
breaking Markdown table parsing, so update the row in the planning document to
match the exact pipe-separated column structure used by the surrounding table.
Check the table entry containing T-69-21-SC and align its cells and separators
with the other rows so markdownlint recognizes it as a valid table row, keeping
the formatting consistent with the table header and neighboring entries.
In
@.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-22-PLAN.md:
- Line 116: The markdown table row is malformed because the closing tag is
interrupting the table syntax, causing markdownlint to treat it as plain text.
Fix the row in the PLAN document by moving the closing tag so it does not sit
inside the table row and ensuring the table formatting around the threat model
section remains valid and parsable.
In
@.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-24-PLAN.md:
- Line 160: The markdown table row is malformed and is being treated as plain
text, so fix the table markup in the plan document where the closing tag appears
by itself. Update the surrounding table structure so the row is valid Markdown
table syntax and continues parsing cleanly, checking the nearby table section
around the threat model entry for the correct row delimiter and alignment.
---
Outside diff comments:
In `@apps/desktop/src-tauri/src/commands/vault.rs`:
- Around line 115-278: initialize_vault can fail after successfully publishing
the deterministic IPNS records, causing retries to hit PublishResult::Conflict
and abort even though the vault was already partially created. Update
initialize_vault to treat self-conflicts on the vault key and root folder
publishes as idempotent recovery: when publish_ipns returns Conflict in these
branches, verify the existing record matches the expected content/sequence and
continue instead of returning an error. Use the existing publish_ipns,
create_ipns_record, and the two publish branches in initialize_vault to locate
the fix.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dba5daab-685b-4478-9778-672cca45fc2e
📒 Files selected for processing (128)
.github/workflows/ci.yml.planning/ROADMAP.md.planning/STATE.md.planning/debug/d07-write-plane-pairing.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-01-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-01-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-02-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-02-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-03-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-03-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-04-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-04-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-05-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-05-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-06-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-06-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-07-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-07-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-08-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-08-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-09-GRIND-RUNBOOK.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-09-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-09-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-10-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-10-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-11-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-11-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-12-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-12-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-13-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-13-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-14-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-15-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-15-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-16-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-16-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-17-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-17-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-18-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-18-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-19-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-19-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-20-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-20-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-21-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-21-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-22-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-22-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-23-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-23-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-24-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-24-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-25-PLAN.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-25-SUMMARY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-CONTEXT.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-DISCUSSION-LOG.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-FUSE-CUTOVER-RESEARCH.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-LEGACY-RETIREMENT-RESEARCH.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-PATTERNS.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-RESEARCH.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-ROOT-KEY-RECOVERY-RESEARCH.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-SECURITY.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-VALIDATION.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-VERIFICATION.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-WRITE-OWNER-RESEARCH.md.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-WRITE-PLANE-RESEARCH.md.planning/todos/pending/2026-07-07-fuse-publish-and-concurrency-hardening-deferred.md.planning/todos/pending/2026-07-07-fuse-shared-scope-exit-rotation-live-wiring.md.planning/todos/pending/2026-07-07-sdk-floor-store-concurrency-atomicity.mdapps/desktop/src-tauri/src/commands/auth.rsapps/desktop/src-tauri/src/commands/vault.rsapps/desktop/src-tauri/src/fuse/mod.rsapps/desktop/src-tauri/src/fuse/prepopulate.rsapps/desktop/src-tauri/src/fuse/windows/mod.rscrates/api-client/src/shares.rscrates/core/src/bin.rscrates/core/src/decrypt.rscrates/core/src/file.rscrates/core/src/folder.rscrates/core/src/lib.rscrates/core/src/node/decode.rscrates/core/src/node/encode.rscrates/core/src/node/mod.rscrates/core/src/node/seal.rscrates/core/src/node/types.rscrates/core/src/vault_blob.rscrates/core/tests/node_codec_vectors.rscrates/core/tests/node_seal_vectors.rscrates/core/tests/node_write_body_vectors.rscrates/fuse/src/cache.rscrates/fuse/src/content_ops.rscrates/fuse/src/dir_ops.rscrates/fuse/src/events.rscrates/fuse/src/fs.rscrates/fuse/src/inode.rscrates/fuse/src/journal_helpers.rscrates/fuse/src/lib.rscrates/fuse/src/metadata.rscrates/fuse/src/operations.rscrates/fuse/src/platform/windows/write_ops.rscrates/fuse/src/poll.rscrates/fuse/src/publish.rscrates/fuse/src/read_ops.rscrates/fuse/src/replay.rscrates/fuse/src/test_support.rscrates/fuse/src/write_ops/grant_scope.rscrates/fuse/src/write_ops/implementation/delete.rscrates/fuse/src/write_ops/implementation/file_data.rscrates/fuse/src/write_ops/implementation/mkdir.rscrates/fuse/src/write_ops/implementation/rename.rscrates/fuse/src/write_ops/mod.rscrates/sdk/src/adapter.rscrates/sdk/src/emit.rscrates/sdk/src/error.rscrates/sdk/src/floor_store.rscrates/sdk/src/lib.rscrates/sdk/src/listing.rscrates/sdk/src/queue.rscrates/sdk/src/rotation/engine.rscrates/sdk/src/rotation/high_water.rscrates/sdk/src/rotation/mod.rscrates/sdk/src/rotation/scope.rscrates/sdk/src/state.rspackages/sdk-core/scripts/edit-filepointer.mtspackages/sdk-core/scripts/rename-folder.mtspackages/sdk-core/scripts/verify-filepointer.mtsrelease-please-config.jsontsconfig.scripts.json
Entire-Checkpoint: 68d54a8eeea4
…hain The Rust FUSE mount published file_iv as hex while the shipped TS/web node/v3 read chain (sdk-core downloadFileContent) decodes it as base64. The mount hex-decoded its own IV so local reads worked, but any cross-client / SDK reader decoded the 24-char hex IV as base64 -> wrong bytes -> AES-GCM tag failure -> "Decryption failed" on every cross-language content read (desktop-e2e Step 3 round-trip, cross-client sync, and move-content all failed on all platforms). The cross-language node-codec KAT never caught it: its sample IV is coincidentally valid as both hex and base64, and docs/METADATA_SCHEMAS.md wrongly said "hex". Fix: publish_file_node emits base64(iv) and the read paths base64-decode content.file_iv (GCM + CTR); the journaled placeholder is base64 so replay publishes base64 too. Internal iv_hex threading and the display-only inode.iv are unchanged. Also fixes the reverse latent bug of the mount reading web-uploaded (base64) files. No migration concern — node/v3 FUSE is unreleased. Entire-Checkpoint: 583f2f877f72
Entire-Checkpoint: d472b999e1e9
|
@coderabbitai please perform a full review of this PR |
|
✅ Action performedFull review finished. Your plan includes PR reviews subject to rate limits. More reviews will be available in 59 minutes. |
…-detection e2e) Entire-Checkpoint: 1cd9a5b51e69
…hain The conflict-detection desktop-e2e helper still read the legacy folder model (loadVaultKeyBlob().rootFolderKey, loadFolderMetadata().metadata.children, updateFolderMetadataAndPublish with folderKey) — 69-25 migrated the sibling verify/edit/rename helpers to node/v3 but missed this one. Under node/v3 the root is a Node, so folder.metadata.children was undefined and the helper crashed with "Cannot read properties of undefined (reading 'length')", failing the Windows conflict-detection leg. Migrate to node/v3: load the two-key root (rootReadKey/rootWriteKey) from the v3 vault blob, resolve + unsealNode the current root PublishedNode, then republish it UNCHANGED at sequence+1 via updateFolderMetadataAndPublish (children === base, no-op merge; writeChildren + ipnsPrivateKey preserved from the sealed write-body; signed by the root write-body IPNS key). CLI/env contract unchanged. Declares the previously-phantom @cipherbox/core devDependency and re-admits the file to the scripts typecheck gate (tsconfig.scripts.json exclude now empty). Entire-Checkpoint: e872ad906ae8
Entire-Checkpoint: f2130a6b556b
Phase 69 — FUSE and WinFsp: Rust Integration and Grant-Root Awareness
Makes the desktop FUSE/WinFsp client a thin adapter over an owning Rust SDK, mirroring the Phase 68.2 SDK-owned read chain on the TypeScript side. The Rust read chain (IPNS resolve + durable anti-rollback floor gate + node unseal + child-metadata resolution) now lives once in the shared
crates/core+crates/sdk, not reimplemented inline per client.What changed
crates/fuse/src/inode.rsandreplay.rsusesaes::unseal_aes_gcm_aadwith AAD bound viabuild_node_aad; noecies::unwrap_keyremains on the node path (SC#1).spawn_file_meta_reencryptdeleted — cross-folder move requires zero re-encrypt; enforced by a CI grep gate (SC#2). The lone residual Windows caller is69-14's deletion target (winfsp-gated).crates/fuse/src/write_ops/grant_scope.rsgates scope-exit mutations: a private delete with no covering grant is a pure relink (zero rotation publishes); a shared-scope exit rotates exactly once at the grant root (SC#3).Nodeis a real Rust enum —enum Node { Folder{children}, File{content}, Root{children} }incrates/core/src/node/; durable generation + sequence high-water persisted in a JSON sidecar adjacent to the write journal, surviving daemon restart (SC#4).crates/fuseconsumeslist_folder_owned/fetch_node_gated; a CI grep gate forbids any inline raw IPNS resolve/unseal incrates/fuse/src(SC#6).root_read_key/root_write_key) minted at vault init and unwrapped on recovery, mounted directly (drops the^0xA5bridge).Gates
cargo test --workspace: 476 passed, 0 failed (macOS, defaultfusefeature).69-VERIFICATION.md: PASS — 5/5 locally-verifiable success criteria.69-SECURITY.md: SECURED —threats_open: 0across the 109-threat plan-time register (2 critical / 79 high verified in code or CI-gated; 4 low/medium accepted risks documented).69-VALIDATION.md: compliant, 0 local gaps.cargo-windowsjob —cargo check/test --workspace --no-default-features --features winfsp.Desktop E2E Testsmatrix (macOS / Windows / Linux) — dispatched against this branch's head SHA (SC#5 sign-off authority).Ship-review hardening (this branch)
CodeRabbit (scoped per-crate) + four adversarial-verification passes over the net-new code produced 10 verified-safe fixes applied here, incl. one CRITICAL:
read_ops: a read immediately after a write returnedEIO— the unresolved-FilePointer poll matched the same empty-CID predicate as its guard, so the buffered-content fallback was unreachable. Now servespending_contentfirst.inode: redactingDebugforInodeKindso key material can't reach logs/panic output; file-attr update moved into theFilearm.replay: both-plane idempotency guard; TEE-enrollment check hoisted above the content upload (no pinned-blob leak on a missing key epoch); unsealed child keys wrapped inZeroizing.metadata: best-effort unpin of the uploaded CID on every publish-failure path.content_ops: symmetric TEE-pairing rejection.core/decode:deny_unknown_fieldson the node wire structs (fail-closed decode).operations: dropped an extra un-zeroized read-key copy.FALSE positives were refuted with evidence (e.g.
generation/version_floorargs misread as size/mtime;apply_owned_childrenwrite-generation reset — the in-flight-write protection lives one level up infs.rs).Deferred (tracked todos)
EIO(no productionRotationDepsimplementor yet — the known ROT-07 live-wiring gap). Fail-closed is security-safe: it refuses to complete a covered delete/move without rotating. Private deletes are fully functional. The todo also enumerates the grant-scope gate fail-closed-correctness findings (empty-cache authoritativeness, ancestor-walk, poisoned-lock, rename dest gating) to resolve together when rotation goes live..planning/todos/pending/2026-07-07-fuse-shared-scope-exit-rotation-live-wiring.md..planning/todos/pending/2026-07-07-sdk-floor-store-concurrency-atomicity.md..planning/todos/pending/2026-07-07-fuse-publish-and-concurrency-hardening-deferred.md.The
crates/corebin-metadata "v1" backward-compat finding was verified a non-issue: plan 69-19 mandates a clean flag-day cutover (no legacy bin blobs), and the suggested#[serde(default)]shim would weaken the fail-closed decode it prohibits.Notes
69-14(WinFsp platform layer) isautonomous:false/ CI-only on macOS —crates/fuse/src/platform/windows/*never compiles under local mac cargo (macFUSE-only linking); it is verified by thecargo-windows+ Desktop E2E CI gates above.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation