Skip to content

feat: FUSE and WinFsp Rust integration with grant-root awareness and SDK-owned read chain#594

Merged
FSM1 merged 163 commits into
mainfrom
feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness
Jul 7, 2026
Merged

feat: FUSE and WinFsp Rust integration with grant-root awareness and SDK-owned read chain#594
FSM1 merged 163 commits into
mainfrom
feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness

Conversation

@FSM1

@FSM1 FSM1 commented Jul 7, 2026

Copy link
Copy Markdown
Owner

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

  • Symmetric unwrap throughout — every node unseal in crates/fuse/src/inode.rs and replay.rs uses aes::unseal_aes_gcm_aad with AAD bound via build_node_aad; no ecies::unwrap_key remains on the node path (SC#1).
  • spawn_file_meta_reencrypt deleted — cross-folder move requires zero re-encrypt; enforced by a CI grep gate (SC#2). The lone residual Windows caller is 69-14's deletion target (winfsp-gated).
  • Grant-root awarenesscrates/fuse/src/write_ops/grant_scope.rs gates 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).
  • Node is a real Rust enumenum Node { Folder{children}, File{content}, Root{children} } in crates/core/src/node/; durable generation + sequence high-water persisted in a JSON sidecar adjacent to the write journal, surviving daemon restart (SC#4).
  • SDK-owned read chaincrates/fuse consumes list_folder_owned / fetch_node_gated; a CI grep gate forbids any inline raw IPNS resolve/unseal in crates/fuse/src (SC#6).
  • Root-key recovery — vault-blob-v3 codec ported to Rust (byte-exact cross-language KAT), two-key root (root_read_key / root_write_key) minted at vault init and unwrapped on recovery, mounted directly (drops the ^0xA5 bridge).

Gates

  • cargo test --workspace: 476 passed, 0 failed (macOS, default fuse feature).
  • Verification 69-VERIFICATION.md: PASS — 5/5 locally-verifiable success criteria.
  • Security 69-SECURITY.md: SECURED — threats_open: 0 across the 109-threat plan-time register (2 critical / 79 high verified in code or CI-gated; 4 low/medium accepted risks documented).
  • Validation 69-VALIDATION.md: compliant, 0 local gaps.
  • Required-green CI gates before merge:
    • cargo-windows job — cargo check/test --workspace --no-default-features --features winfsp.
    • Full Desktop E2E Tests matrix (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:

  • CRITICAL read_ops: a read immediately after a write returned EIO — the unresolved-FilePointer poll matched the same empty-CID predicate as its guard, so the buffered-content fallback was unreachable. Now serves pending_content first.
  • inode: redacting Debug for InodeKind so key material can't reach logs/panic output; file-attr update moved into the File arm.
  • 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 in Zeroizing.
  • metadata: best-effort unpin of the uploaded CID on every publish-failure path.
  • content_ops: symmetric TEE-pairing rejection. core/decode: deny_unknown_fields on 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_floor args misread as size/mtime; apply_owned_children write-generation reset — the in-flight-write protection lives one level up in fs.rs).

Deferred (tracked todos)

  • Shared-scope-exit read-key rotation is fail-closed, not live-wired — the grant-root gate is present and wired, but a covered scope-exit returns EIO (no production RotationDeps implementor 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.
  • SDK anti-rollback floor-store atomicity — non-atomic read-modify-write under concurrency + blocking I/O on the async executor; safe under the single-daemon model and mirrors the shipped TS twin. .planning/todos/pending/2026-07-07-sdk-floor-store-concurrency-atomicity.md.
  • FUSE publish/concurrency hardening — CAS-retry consolidation (5→2 attempt regression risk), FP-resolve global concurrency cap, Windows write-plane keying (69-14, CI-gated), and a lower-value crypto-hygiene zeroization pass. .planning/todos/pending/2026-07-07-fuse-publish-and-concurrency-hardening-deferred.md.

The crates/core bin-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

  • Plan 69-14 (WinFsp platform layer) is autonomous:false / CI-only on macOS — crates/fuse/src/platform/windows/* never compiles under local mac cargo (macFUSE-only linking); it is verified by the cargo-windows + Desktop E2E CI gates above.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Improved desktop vault initialization and recovery with distinct read/write root keys for stronger key separation.
    • Updated mounting to use the recovered vault keys directly for more consistent behavior across sessions.
  • Bug Fixes

    • Improved fail-closed handling for tampered or mismatched vault settings during startup and recovery.
    • Reduced edge-case failures during file operations by tightening vault state usage.
  • Documentation

    • Updated project phase/roadmap and execution status materials to reflect the latest progress.

FSM1 added 30 commits July 6, 2026 02:41
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)
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (3)
  • tests/desktop-e2e/package.json
  • tests/desktop-e2e/scripts/bump-ipns-sequence.ts
  • tsconfig.scripts.json
⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/pnpm-lock.yaml
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 21f7f4cc-c3d1-4230-86cc-b51fc4010461

📥 Commits

Reviewing files that changed from the base of the PR and between 4a5e6a8 and 0f90665.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • tests/desktop-e2e/package.json
  • tests/desktop-e2e/scripts/bump-ipns-sequence.ts
  • tsconfig.scripts.json

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

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

This 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.

Changes

Desktop vault and CI gating

Layer / File(s) Summary
Desktop vault root-key flow
apps/desktop/src-tauri/src/commands/vault.rs, apps/desktop/src-tauri/src/commands/auth.rs
initialize_vault and fetch_and_decrypt_vault now use v3 root key blobs and empty ROOT node publishing, and post_auth_finalize passes recovered root keys into mount_filesystem.
CI grep gates
.github/workflows/ci.yml
Adds SC#6 resolve-call-site gating and SC#2 spawn_file_meta_reencrypt absence checks for crates/fuse/src.

Phase 69 planning and execution tracking

Layer / File(s) Summary
Roadmap, state, and deferred work
.planning/ROADMAP.md, .planning/STATE.md, .planning/todos/pending/*
Updates Phase 69 completion/state tracking and adds deferred work notes for publish/concurrency hardening and shared-scope-exit rotation wiring.
Plans 69-01 through 69-08
.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-01-*69-08-*
Documents the node codec, anti-rollback floor gate, sent-shares API, AAD seal/unseal, grant-scope predicate, gated listing, cache wiring, and rotation-engine workstreams.
Plans 69-09 through 69-14
.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-09-*69-14-*
Covers the Unix FUSE cutover runbook, journal reshape, recycle-bin and vault-root migrations, the Windows split, and the WinFsp integration/gating plan.
Plans 69-15 through 69-20
.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-15-*69-20-*
Documents the write-body codec, SDK emit/adapter, owned listing, journal reshape, recycle-bin restore data, and vault root publication changes.
Plans 69-21 through 69-25
.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/69-21-*69-25-*
Documents the vault-blob-v3 codec, KeyState root slots, desktop root-key lifecycle, mount wiring, and desktop-e2e helper migration.
Phase context, research, security, validation, verification
.planning/phases/69-fuse-and-winfsp-rust-integration-and-grant-root-awareness/*, .planning/debug/d07-write-plane-pairing.md
Captures the phase context, research, patterns, security, validation, verification, and debug notes used to track the rollout.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • FSM1/cipher-box#127: Also changes vault initialization and root-key/IPNS derivation flow.
  • FSM1/cipher-box#538: Shares the spawn_file_meta_reencrypt call-chain and related FUSE write-path cleanup.
  • FSM1/cipher-box#555: Introduces the verified IPNS resolve chokepoint now enforced by the SC#6 CI gate.

Suggested labels: release:desktop:feat, release:cipherbox-fuse:feat, release:cipherbox-core:feat, release:cipherbox-sdk:feat

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main theme: FUSE/WinFsp Rust integration with grant-root awareness and an SDK-owned read chain.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness

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.

@github-actions github-actions Bot added release:cipherbox-core:feat Minor version bump (new feature) for cipherbox-core release:cipherbox-sdk:feat Minor version bump (new feature) for cipherbox-sdk release:api:feat Minor version bump (new feature) for api release:cipherbox-fuse:feat Minor version bump (new feature) for cipherbox-fuse release:desktop:feat Minor version bump (new feature) for desktop release:sdk-core:feat Minor version bump (new feature) for sdk-core release:sdk:fix Patch version bump (bug fix) for sdk release:web:fix Patch version bump (bug fix) for web release:tee-worker:fix Patch version bump (bug fix) for tee-worker labels Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Release Preview

Package Bump Label Source
api minor release:api:feat Direct (feat commit)
cipherbox-core minor release:cipherbox-core:feat Direct (feat commit)
cipherbox-fuse minor release:cipherbox-fuse:feat Direct (feat commit)
cipherbox-sdk minor release:cipherbox-sdk:feat Direct (feat commit)
desktop minor release:desktop:feat Direct (feat commit)
sdk patch release:sdk:fix Cascade (sdk-core minor)
sdk-core minor release:sdk-core:feat Direct (feat commit)
tee-worker patch release:tee-worker:fix Cascade (sdk-core minor)
web minor release:web:fix Cascade (sdk-core minor)

Cascade Details

  • sdk-core minor -> sdk patch (direct dependency)
  • sdk-core minor -> web patch (direct dependency)
  • sdk-core minor -> tee-worker patch (direct dependency)

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR moves the desktop FUSE and WinFsp paths onto the shared Rust node read chain. The main changes are:

  • Shared node/v3 encode, decode, seal, and listing support in crates/core and crates/sdk.
  • Desktop FUSE reads routed through SDK-owned gated resolve helpers.
  • Grant-root-aware delete and rename gating for shared-scope exits.
  • Root-key recovery using v3 vault blobs with separate read and write keys.
  • CI grep gates for raw resolve calls and removed re-encrypt-on-move code.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The reviewed follow-up areas either keep intentional cutover behavior or document deferred hardening work.
  • No accepted issue required a new inline comment.

Important Files Changed

Filename Overview
apps/desktop/src-tauri/src/commands/vault.rs Uses the v3 vault blob recovery path with separate root read and write keys.
crates/core/src/bin.rs Updates recycle-bin metadata to the node/v3 child reference shape.
crates/sdk/src/listing.rs Adds SDK-owned gated node fetch and owned-folder listing behavior.
crates/sdk/src/floor_store.rs Persists rotation high-water state in a JSON sidecar for daemon restarts.
crates/fuse/src/write_ops/grant_scope.rs Adds grant-root-aware scope-exit gating for delete and rename operations.

Reviews (6): Last reviewed commit: "docs(69): retire bump-ipns-sequence defe..." | Re-trigger Greptile

Comment thread apps/desktop/src-tauri/src/commands/vault.rs
Comment thread crates/core/src/bin.rs
Comment thread crates/sdk/src/listing.rs
Comment thread crates/sdk/src/floor_store.rs
Comment thread crates/sdk/src/floor_store.rs
Comment thread crates/fuse/src/write_ops/grant_scope.rs
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.74%. Comparing base (0c23dcb) to head (0f90665).

Additional details and impacted files

Impacted file tree graph

@@            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              
Flag Coverage Δ
api 79.96% <ø> (ø)
api-client 79.96% <ø> (ø)
core 79.96% <ø> (ø)
crypto 79.96% <ø> (ø)
desktop 21.82% <ø> (-9.62%) ⬇️
rust 76.02% <ø> (?)
sdk 79.96% <ø> (ø)
sdk-core 79.96% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
apps/desktop/src-tauri/src/commands/auth.rs 0.00% <ø> (ø)
apps/desktop/src-tauri/src/commands/vault.rs 39.15% <ø> (+39.15%) ⬆️
apps/desktop/src-tauri/src/fuse/mod.rs 7.31% <ø> (+7.31%) ⬆️
apps/desktop/src-tauri/src/fuse/prepopulate.rs 0.00% <ø> (ø)
crates/api-client/src/shares.rs 77.14% <ø> (ø)
crates/core/src/bin.rs 97.57% <ø> (ø)
crates/core/src/node/decode.rs 93.75% <ø> (ø)
crates/core/src/node/encode.rs 100.00% <ø> (ø)
crates/core/src/node/seal.rs 97.08% <ø> (ø)
crates/core/src/node/types.rs 100.00% <ø> (ø)
... and 31 more

... and 55 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

FSM1 added 2 commits July 7, 2026 15:44
…areness' of https://github.com/FSM1/cipher-box into feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness

@coderabbitai coderabbitai 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.

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 lift

Partial vault initialization can strand retries on the same IPNS names.

initialize_vault is called for new users and again when an existing user hits a 404 in apps/desktop/src-tauri/src/commands/auth.rs, so a failure after the two deterministic IPNS publishes but before /vault/init leaves later attempts stuck on the same PublishResult::Conflict path. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0c23dcb and 84eade0.

📒 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.md
  • apps/desktop/src-tauri/src/commands/auth.rs
  • apps/desktop/src-tauri/src/commands/vault.rs
  • apps/desktop/src-tauri/src/fuse/mod.rs
  • apps/desktop/src-tauri/src/fuse/prepopulate.rs
  • apps/desktop/src-tauri/src/fuse/windows/mod.rs
  • crates/api-client/src/shares.rs
  • crates/core/src/bin.rs
  • crates/core/src/decrypt.rs
  • crates/core/src/file.rs
  • crates/core/src/folder.rs
  • crates/core/src/lib.rs
  • crates/core/src/node/decode.rs
  • crates/core/src/node/encode.rs
  • crates/core/src/node/mod.rs
  • crates/core/src/node/seal.rs
  • crates/core/src/node/types.rs
  • crates/core/src/vault_blob.rs
  • crates/core/tests/node_codec_vectors.rs
  • crates/core/tests/node_seal_vectors.rs
  • crates/core/tests/node_write_body_vectors.rs
  • crates/fuse/src/cache.rs
  • crates/fuse/src/content_ops.rs
  • crates/fuse/src/dir_ops.rs
  • crates/fuse/src/events.rs
  • crates/fuse/src/fs.rs
  • crates/fuse/src/inode.rs
  • crates/fuse/src/journal_helpers.rs
  • crates/fuse/src/lib.rs
  • crates/fuse/src/metadata.rs
  • crates/fuse/src/operations.rs
  • crates/fuse/src/platform/windows/write_ops.rs
  • crates/fuse/src/poll.rs
  • crates/fuse/src/publish.rs
  • crates/fuse/src/read_ops.rs
  • crates/fuse/src/replay.rs
  • crates/fuse/src/test_support.rs
  • crates/fuse/src/write_ops/grant_scope.rs
  • crates/fuse/src/write_ops/implementation/delete.rs
  • crates/fuse/src/write_ops/implementation/file_data.rs
  • crates/fuse/src/write_ops/implementation/mkdir.rs
  • crates/fuse/src/write_ops/implementation/rename.rs
  • crates/fuse/src/write_ops/mod.rs
  • crates/sdk/src/adapter.rs
  • crates/sdk/src/emit.rs
  • crates/sdk/src/error.rs
  • crates/sdk/src/floor_store.rs
  • crates/sdk/src/lib.rs
  • crates/sdk/src/listing.rs
  • crates/sdk/src/queue.rs
  • crates/sdk/src/rotation/engine.rs
  • crates/sdk/src/rotation/high_water.rs
  • crates/sdk/src/rotation/mod.rs
  • crates/sdk/src/rotation/scope.rs
  • crates/sdk/src/state.rs
  • packages/sdk-core/scripts/edit-filepointer.mts
  • packages/sdk-core/scripts/rename-folder.mts
  • packages/sdk-core/scripts/verify-filepointer.mts
  • release-please-config.json
  • tsconfig.scripts.json

FSM1 added 3 commits July 7, 2026 16:07
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
@FSM1

FSM1 commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai please perform a full review of this PR

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

@FSM1 Understood — I'll perform a full review of all changes in this PR.

✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 59 minutes.

FSM1 added 3 commits July 7, 2026 17:25
…-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
@FSM1 FSM1 merged commit 4b96aa9 into main Jul 7, 2026
33 checks passed
@FSM1 FSM1 deleted the feat/fuse-and-winfsp-rust-integration-and-grant-root-awareness branch July 7, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:api:feat Minor version bump (new feature) for api release:cipherbox-core:feat Minor version bump (new feature) for cipherbox-core release:cipherbox-fuse:feat Minor version bump (new feature) for cipherbox-fuse release:cipherbox-sdk:feat Minor version bump (new feature) for cipherbox-sdk release:desktop:feat Minor version bump (new feature) for desktop release:sdk:fix Patch version bump (bug fix) for sdk release:sdk-core:feat Minor version bump (new feature) for sdk-core release:tee-worker:fix Patch version bump (bug fix) for tee-worker release:web:fix Patch version bump (bug fix) for web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant