Skip to content

fix(desktop): align file upload IPNS sequence and verify file pointers#446

Merged
FSM1 merged 3 commits into
mainfrom
fix/desktop-new-file-upload-ipns-sequence
Apr 2, 2026
Merged

fix(desktop): align file upload IPNS sequence and verify file pointers#446
FSM1 merged 3 commits into
mainfrom
fix/desktop-new-file-upload-ipns-sequence

Conversation

@FSM1

@FSM1 FSM1 commented Apr 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • add next_file_publish_sequence handling in the FUSE desktop upload flow
  • update platform operation handling to use the corrected IPNS sequence behavior
  • add file pointer verification to the desktop round-trip test scripts
  • add a verification script for file pointer validation

Testing

  • Updated tests to confirm the failure before applying the fix
  • Implemented the fix and validated it manually
  • Verified desktop E2E tests pass locally after the fix

Changed areas

  • crates/fuse
  • packages/sdk-core/scripts/verify-filepointer.mjs
  • tests/desktop-e2e/scripts

Summary by CodeRabbit

Release Notes

  • New Features

    • Added file pointer verification capability for vault contents.
  • Bug Fixes

    • Optimized file publishing sequence handling to improve efficiency on initial publishes.
  • Tests

    • Enhanced end-to-end testing with file pointer verification tests and randomized test files for improved reliability.

Copilot AI review requested due to automatic review settings April 2, 2026 12:46
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b9545b13-07bd-4909-8633-41064d71fdac

📥 Commits

Reviewing files that changed from the base of the PR and between 719ddef and 0432540.

📒 Files selected for processing (6)
  • crates/fuse/src/lib.rs
  • crates/fuse/src/operations.rs
  • crates/fuse/src/platform/windows/operations.rs
  • packages/sdk-core/scripts/verify-filepointer.mjs
  • tests/desktop-e2e/scripts/test-round-trip.ps1
  • tests/desktop-e2e/scripts/test-round-trip.sh

Walkthrough

Adds a helper to compute per-file IPNS publish sequences and integrates it into FUSE publish flows to skip resolving sequence on first publish. Adds a file-pointer verifier script and updates desktop e2e tests to use randomized files and poll the verifier.

Changes

Cohort / File(s) Summary
IPNS Sequence Management
crates/fuse/src/lib.rs, crates/fuse/src/operations.rs, crates/fuse/src/platform/windows/operations.rs
Adds next_file_publish_sequence(is_first_publish, current_sequence) and updates publish logic to avoid resolving current sequence on first publish; delegates sequence computation to the new helper and uses its result for IPNS record creation and coordinator recording.
File Pointer Verification Script
packages/sdk-core/scripts/verify-filepointer.mjs
New Node.js CLI script to authenticate, load vault/root metadata, resolve per-file metadata by name, optionally download & decrypt content, and emit a JSON verification report; exits nonzero on failure.
End-to-End Test Updates
tests/desktop-e2e/scripts/test-round-trip.ps1, tests/desktop-e2e/scripts/test-round-trip.sh
Tests now generate randomized file names/content, ensure verifier runtime (build dist artifacts if missing), run the file-pointer verifier with polling and retries, and adjust cleanup; adds an extra verification step after client reload.

Sequence Diagram(s)

sequenceDiagram
    participant TestClient as Test Client
    participant Verifier as verify-filepointer
    participant AuthAPI as Auth API
    participant VaultSvc as Vault Service
    participant IPFS as IPFS/IPNS

    TestClient->>Verifier: run(file-name, expected-content, api-url, email, secret)
    Verifier->>AuthAPI: POST /auth/test-login {email, secret}
    AuthAPI-->>Verifier: {accessToken, privateKeyHex}
    Verifier->>VaultSvc: GET /vault (Authorization: Bearer token)
    VaultSvc-->>Verifier: {rootIpnsName}
    Verifier->>IPFS: resolve(rootIpnsName) -> root folder metadata
    Verifier->>IPFS: loadVaultKeyBlob(root) / loadFolderMetadata(root)
    Verifier->>IPFS: find child by name -> fileMetaIpnsName
    Verifier->>IPFS: resolve(fileMetaIpnsName) -> file CID/metadata
    alt expected-content provided
        Verifier->>IPFS: download(file CID)
        IPFS-->>Verifier: encrypted content
        Verifier->>Verifier: decrypt using privateKeyHex
        Verifier->>Verifier: compare plaintext == expected-content
    end
    Verifier-->>TestClient: JSON report {rootIpns, fileCid, contentVerified}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

release:sdk-core:fix

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: fixing IPNS sequence alignment for file uploads and adding file pointer verification, which are the central themes across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/desktop-new-file-upload-ipns-sequence

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 and usage tips.

@github-actions

github-actions Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Release Preview

Package Bump Label Source
cipherbox-fuse patch release:cipherbox-fuse:fix Direct (fix commit)
desktop minor release:desktop:fix Cascade (cipherbox-fuse patch)

Cascade Details

  • cipherbox-fuse patch -> desktop patch (direct dependency)

github-actions Bot added a commit that referenced this pull request Apr 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the desktop FUSE upload flow to handle “first publish” IPNS sequence behavior explicitly and extends the desktop round-trip E2E scripts with a FilePointer/per-file IPNS verification step (via a new sdk-core verifier script).

Changes:

  • Add next_file_publish_sequence() helper and use it to compute per-file IPNS publish sequence numbers without resolving IPNS on first publish.
  • Enhance desktop E2E round-trip scripts (bash + PowerShell) to verify FilePointer presence and per-file IPNS metadata resolution/content round-trip.
  • Add a Node verifier script (packages/sdk-core/scripts/verify-filepointer.mjs) that authenticates via test-login, loads folder metadata, resolves per-file metadata, and optionally verifies decrypted content.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/desktop-e2e/scripts/test-round-trip.sh Adds repo-root detection, builds verifier runtime if needed, writes randomized test file, and verifies FilePointer + per-file metadata/content.
tests/desktop-e2e/scripts/test-round-trip.ps1 Windows equivalent of the round-trip enhancements, including verifier runtime build and repeated verification attempts.
packages/sdk-core/scripts/verify-filepointer.mjs New script to authenticate, load root folder metadata, find a FilePointer by name, resolve per-file metadata from IPNS, and optionally verify content.
crates/fuse/src/platform/windows/operations.rs Uses the new sequence helper and skips sequence resolution on first per-file publish.
crates/fuse/src/operations.rs Same per-file publish sequence change for the non-Windows implementation.
crates/fuse/src/lib.rs Introduces next_file_publish_sequence() and adds unit tests for it.

Comment thread crates/fuse/src/lib.rs
@codecov

codecov Bot commented Apr 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.92%. Comparing base (cd82248) to head (0432540).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #446      +/-   ##
==========================================
+ Coverage   62.35%   71.92%   +9.57%     
==========================================
  Files         135      114      -21     
  Lines       10088     7171    -2917     
  Branches     1053     1055       +2     
==========================================
- Hits         6290     5158    -1132     
+ Misses       3580     1795    -1785     
  Partials      218      218              
Flag Coverage Δ
api 85.06% <ø> (+0.05%) ⬆️
api-client 85.06% <ø> (+0.05%) ⬆️
core 85.06% <ø> (+0.05%) ⬆️
crypto 85.06% <ø> (+0.05%) ⬆️
desktop 14.40% <ø> (-16.82%) ⬇️
sdk 85.06% <ø> (+0.05%) ⬆️
sdk-core 85.06% <ø> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 35 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.

Copilot finished work on behalf of FSM1 April 2, 2026 12:59
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/desktop-new-file-upload-ipns-sequence

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 and usage tips.

@FSM1

FSM1 commented Apr 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai please review

@FSM1
FSM1 force-pushed the fix/desktop-new-file-upload-ipns-sequence branch from 719ddef to 0432540 Compare April 2, 2026 13:13
@FSM1
FSM1 enabled auto-merge (squash) April 2, 2026 13:14

@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: 2

🧹 Nitpick comments (1)
crates/fuse/src/lib.rs (1)

124-135: Narrow this helper to crate visibility.

next_file_publish_sequence is only used from internal modules, so keeping it pub unnecessarily expands the crate's public API surface.

♻️ Proposed fix
-pub fn next_file_publish_sequence(
+pub(crate) fn next_file_publish_sequence(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fuse/src/lib.rs` around lines 124 - 135, The function
next_file_publish_sequence is unnecessarily public; change its visibility to
crate-level (e.g., make it pub(crate) or remove pub if used only within the
crate) so it no longer expands the public API surface, leaving the
implementation and return type intact and ensuring internal modules can still
call next_file_publish_sequence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/sdk-core/scripts/verify-filepointer.mjs`:
- Around line 28-45: The script currently requires --secret; change logic in the
argument-parsing block that returns { apiUrl, secret, email, fileName,
expectedContent } so that secret is optional and falls back to
process.env.TEST_SECRET (i.e., set secret = values.get('secret') ||
process.env.TEST_SECRET), remove --secret from the required-arguments check and
from the usage error string, and keep the CLI flag as an override; then update
callers (tests/e2e-desktop/scripts/* wrappers) to stop passing --secret and rely
on TEST_SECRET in the environment instead.

In `@tests/desktop-e2e/scripts/test-round-trip.ps1`:
- Around line 45-64: The early-return guard in Ensure-VerifierRuntime only
checks $sdkCoreDist and $apiClientDist but must verify all four build outputs;
update Ensure-VerifierRuntime to define and test paths for the missing dist
files (packages/crypto/dist/index.mjs and packages/core/dist/index.mjs) and
change the if condition to require all four Test-Path results before returning
early, and make the equivalent change in the shell counterpart
test-round-trip.sh so both scripts check the same four prerequisites.

---

Nitpick comments:
In `@crates/fuse/src/lib.rs`:
- Around line 124-135: The function next_file_publish_sequence is unnecessarily
public; change its visibility to crate-level (e.g., make it pub(crate) or remove
pub if used only within the crate) so it no longer expands the public API
surface, leaving the implementation and return type intact and ensuring internal
modules can still call next_file_publish_sequence.
🪄 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: 7961481b-5cdd-4bc3-a17e-98e2bd11e5c8

📥 Commits

Reviewing files that changed from the base of the PR and between cd82248 and 719ddef.

📒 Files selected for processing (7)
  • crates/fuse/src/lib.rs
  • crates/fuse/src/operations.rs
  • crates/fuse/src/platform/windows/operations.rs
  • packages/sdk-core/scripts/verify-filepointer.mjs
  • release-please-config.json
  • tests/desktop-e2e/scripts/test-round-trip.ps1
  • tests/desktop-e2e/scripts/test-round-trip.sh

Comment on lines +28 to +45
const apiUrl = values.get('api-url');
const secret = values.get('secret');
const email = values.get('email');
const fileName = values.get('file-name');

if (!apiUrl || !secret || !email || !fileName) {
throw new Error(
'Usage: verify-filepointer.mjs --api-url <url> --secret <secret> --email <email> --file-name <name> [--expected-content <text>]'
);
}

return {
apiUrl,
secret,
email,
fileName,
expectedContent: values.get('expected-content'),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don’t make the test-login secret mandatory on argv.

Requiring --secret here forces both round-trip wrappers to put TEST_SECRET in process arguments. Fall back to process.env.TEST_SECRET, keep the flag as an optional override, and then drop --secret from the shell/PowerShell callers.

🔐 Proposed fix
-  const secret = values.get('secret');
+  const secret = values.get('secret') ?? process.env.TEST_SECRET;
   const email = values.get('email');
   const fileName = values.get('file-name');
 
-  if (!apiUrl || !secret || !email || !fileName) {
+  if (!apiUrl || !email || !fileName || !secret) {
     throw new Error(
-      'Usage: verify-filepointer.mjs --api-url <url> --secret <secret> --email <email> --file-name <name> [--expected-content <text>]'
+      'Usage: verify-filepointer.mjs --api-url <url> --email <email> --file-name <name> [--secret <secret>] [--expected-content <text>] (or set TEST_SECRET)'
     );
   }

Based on learnings In PowerShell and Bash test scripts for tests/e2e-desktop/scripts/, secrets (like TEST_SECRET) should be passed via environment variables, NOT as command-line parameters, to avoid exposure in process listings and shell history.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sdk-core/scripts/verify-filepointer.mjs` around lines 28 - 45, The
script currently requires --secret; change logic in the argument-parsing block
that returns { apiUrl, secret, email, fileName, expectedContent } so that secret
is optional and falls back to process.env.TEST_SECRET (i.e., set secret =
values.get('secret') || process.env.TEST_SECRET), remove --secret from the
required-arguments check and from the usage error string, and keep the CLI flag
as an override; then update callers (tests/e2e-desktop/scripts/* wrappers) to
stop passing --secret and rely on TEST_SECRET in the environment instead.

Comment on lines +45 to +64
function Ensure-VerifierRuntime {
$sdkCoreDist = Join-Path $RepoRoot "packages/sdk-core/dist/index.mjs"
$apiClientDist = Join-Path $RepoRoot "packages/api-client/dist/index.mjs"

if ((Test-Path $sdkCoreDist) -and (Test-Path $apiClientDist)) {
return
}

& pnpm --dir $RepoRoot --filter @cipherbox/crypto build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/crypto" }

& pnpm --dir $RepoRoot --filter @cipherbox/core build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/core" }

& pnpm --dir $RepoRoot --filter @cipherbox/api-client build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/api-client" }

& pnpm --dir $RepoRoot --filter @cipherbox/sdk-core build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/sdk-core" }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Check all verifier prerequisites before returning early.

This guard only proves two of the four dist outputs you treat as prerequisites are present. A partially-built workspace can skip the fallback and then fail later when the verifier runs. The same guard in tests/desktop-e2e/scripts/test-round-trip.sh needs the same change.

🧱 Proposed fix
 function Ensure-VerifierRuntime {
     $sdkCoreDist = Join-Path $RepoRoot "packages/sdk-core/dist/index.mjs"
     $apiClientDist = Join-Path $RepoRoot "packages/api-client/dist/index.mjs"
+    $coreDist = Join-Path $RepoRoot "packages/core/dist/index.mjs"
+    $cryptoDist = Join-Path $RepoRoot "packages/crypto/dist/index.mjs"
 
-    if ((Test-Path $sdkCoreDist) -and (Test-Path $apiClientDist)) {
+    if ((Test-Path $sdkCoreDist) -and (Test-Path $apiClientDist) -and (Test-Path $coreDist) -and (Test-Path $cryptoDist)) {
         return
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function Ensure-VerifierRuntime {
$sdkCoreDist = Join-Path $RepoRoot "packages/sdk-core/dist/index.mjs"
$apiClientDist = Join-Path $RepoRoot "packages/api-client/dist/index.mjs"
if ((Test-Path $sdkCoreDist) -and (Test-Path $apiClientDist)) {
return
}
& pnpm --dir $RepoRoot --filter @cipherbox/crypto build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/crypto" }
& pnpm --dir $RepoRoot --filter @cipherbox/core build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/core" }
& pnpm --dir $RepoRoot --filter @cipherbox/api-client build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/api-client" }
& pnpm --dir $RepoRoot --filter @cipherbox/sdk-core build
if ($LASTEXITCODE -ne 0) { throw "Failed to build @cipherbox/sdk-core" }
}
function Ensure-VerifierRuntime {
$sdkCoreDist = Join-Path $RepoRoot "packages/sdk-core/dist/index.mjs"
$apiClientDist = Join-Path $RepoRoot "packages/api-client/dist/index.mjs"
$coreDist = Join-Path $RepoRoot "packages/core/dist/index.mjs"
$cryptoDist = Join-Path $RepoRoot "packages/crypto/dist/index.mjs"
if ((Test-Path $sdkCoreDist) -and (Test-Path $apiClientDist) -and (Test-Path $coreDist) -and (Test-Path $cryptoDist)) {
return
}
& pnpm --dir $RepoRoot --filter `@cipherbox/crypto` build
if ($LASTEXITCODE -ne 0) { throw "Failed to build `@cipherbox/crypto`" }
& pnpm --dir $RepoRoot --filter `@cipherbox/core` build
if ($LASTEXITCODE -ne 0) { throw "Failed to build `@cipherbox/core`" }
& pnpm --dir $RepoRoot --filter `@cipherbox/api-client` build
if ($LASTEXITCODE -ne 0) { throw "Failed to build `@cipherbox/api-client`" }
& pnpm --dir $RepoRoot --filter `@cipherbox/sdk-core` build
if ($LASTEXITCODE -ne 0) { throw "Failed to build `@cipherbox/sdk-core`" }
}
🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)

[warning] 45-45: The cmdlet 'Ensure-VerifierRuntime' uses an unapproved verb.

(PSUseApprovedVerbs)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/desktop-e2e/scripts/test-round-trip.ps1` around lines 45 - 64, The
early-return guard in Ensure-VerifierRuntime only checks $sdkCoreDist and
$apiClientDist but must verify all four build outputs; update
Ensure-VerifierRuntime to define and test paths for the missing dist files
(packages/crypto/dist/index.mjs and packages/core/dist/index.mjs) and change the
if condition to require all four Test-Path results before returning early, and
make the equivalent change in the shell counterpart test-round-trip.sh so both
scripts check the same four prerequisites.

@FSM1
FSM1 merged commit 741f226 into main Apr 2, 2026
25 of 26 checks passed
@FSM1
FSM1 deleted the fix/desktop-new-file-upload-ipns-sequence branch April 14, 2026 00:03
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.

3 participants