feat: desktop auto-updater, TEE file enrollment, and CI build workflow#360
Conversation
Entire-Checkpoint: 7c629a55631e
Entire-Checkpoint: 056a27a75ce0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: bb40396efd18
Entire-Checkpoint: d1c754a0f5d3
- Plan 02: acknowledge Windows force-restart as acceptable (unmount/restart/mount cycle) - VALIDATION.md: align verification commands with actual plan commands (cargo check + grep, not cargo test) - Set nyquist_compliant: true and wave_0_complete: true Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 312d160bebe0
- Add tauri-plugin-updater = "2" to desktop Cargo.toml - Configure updater plugin in tauri.conf.json with Ed25519 pubkey placeholder and GitHub Releases endpoint - Enable createUpdaterArtifacts in bundle config for updater bundle generation - Add updater:default capability permission Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: dae386fc0f67
- Add tee_public_key, tee_key_epoch, is_first_publish params to publish_file_metadata - Wrap file IPNS private key with TEE public key on first publish using ECIES - Thread TEE keys from CipherBoxFS into background upload spawn in release() handler - Use existing is_new_file flag (CID empty) as first-publish signal Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: d4af47332cb3
…mation - GitHub Actions workflow triggered on Release Please publish events - Build matrix: macOS (aarch64 + x86_64), Ubuntu 22.04, Windows - Ed25519 signing via TAURI_SIGNING_PRIVATE_KEY GitHub secret - tauri-action@v1 uploads bundles + latest.json to GitHub Release - FUSE-T install for macOS, WinFsp install for Windows, libfuse3 for Linux - Windows uses --no-default-features --features winfsp Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 2d82311f6fc9
- Create updater.rs with check_on_launch (5s delay) and manual_check functions - Register tauri_plugin_updater plugin in main.rs Builder chain - Call updater::check_on_launch in setup closure after tray initialization - Add "Check for Updates..." tray menu item with event handler - System notification on update ready or manual check result Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: fd2792f27a7d
- Mirror Unix TEE enrollment pattern for Windows WinFSP codepath - Add tee_public_key, tee_key_epoch, is_first_publish params to Windows publish_file_metadata - Wrap file IPNS private key with TEE public key on first publish - Compute is_new_file from empty CID check before cleanup handler - Thread TEE keys from fs into background upload spawn Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 18ff0103adcc
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 8f276ea1d92b
- Create 25-02-SUMMARY.md with execution results - Update STATE.md with plan progress and metrics - Update ROADMAP.md with phase 25 plan progress - Mark DESKTOP-01 requirement as complete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: fff06dbc5c58
- Add 25-01-SUMMARY.md with execution results - Mark DESKTOP-02 requirement as complete in REQUIREMENTS.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: a010022aba08
Generated Ed25519 signing keypair and set GitHub secrets (TAURI_SIGNING_PRIVATE_KEY, TAURI_SIGNING_PRIVATE_KEY_PASSWORD). Public key now embedded in updater config for signature verification. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: f352abfe8301
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 50c2e9405893
9/9 must-haves verified. DESKTOP-01 (auto-updater) and DESKTOP-02 (TEE file enrollment) both fully implemented and wired. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 8f8cb082a144
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 3ac1dc079750
- Replace nested if/let TEE wrapping with match destructuring, eliminating the intermediate has_tee_enrollment boolean - Remove explicit `pnpm vite build` step from CI workflow — Tauri's beforeBuildCommand already handles this, saving ~90s per platform Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 33ec003d123a
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
WalkthroughThis PR implements Phase 25 "Desktop Enhancements" by adding Tauri auto-update functionality (launch-delayed checks, background downloads, tray menu integration) and TEE key enrollment for per-file IPNS publishes in the FUSE mount on Unix and Windows platforms. It includes a new GitHub Actions workflow for cross-platform signed desktop builds, supporting changes to desktop Tauri configuration and tray integration, and modifications to FUSE publish operations to conditionally wrap file IPNS private keys on first publish. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User/Desktop App
participant Tauri as Tauri Updater Plugin
participant GitHub as GitHub Releases
participant Notify as System Notifications
rect rgba(100, 150, 200, 0.5)
Note over User,Notify: Launch-Time Check (5s delay)
User->>User: App starts, setup runs
User->>Tauri: check_on_launch() spawned async
Tauri->>Tauri: Wait 5 seconds
Tauri->>GitHub: GET latest.json (check())
GitHub-->>Tauri: Version & download URL
alt Update Available
Tauri->>Tauri: download_and_install()
Tauri->>GitHub: Download binary
GitHub-->>Tauri: Binary received
Tauri->>Notify: Emit "Update Ready" notification
Tauri->>User: Staged for next restart
else No Update
Tauri->>Tauri: Log & return
end
end
rect rgba(150, 200, 100, 0.5)
Note over User,Notify: Manual Check (Tray Menu)
User->>User: Click "Check for Updates..."
User->>Tauri: manual_check()
Tauri->>GitHub: GET latest.json (check())
GitHub-->>Tauri: Version info
alt Update Found
Tauri->>Tauri: download_and_install()
Tauri->>GitHub: Download binary
Tauri->>Notify: Emit "Update Ready" notification
else No Update
Tauri->>Notify: Emit "Already on latest version" notification
end
end
sequenceDiagram
participant App as Desktop App/FUSE
participant Coordinator as Publish Coordinator
participant Crypto as Cipherbox Crypto
participant API as IPNS API Client
rect rgba(200, 100, 150, 0.5)
Note over App,API: First File Publish (new file, empty CID)
App->>App: release_handle() called on new file
App->>Coordinator: Compute is_new_file = true
App->>Coordinator: Clone tee_public_key & epoch from FS context
App->>Coordinator: publish_file_metadata(is_first_publish=true, tee_public_key, tee_key_epoch)
Coordinator->>Crypto: wrap_key(ipns_private_key, tee_public_key)
Crypto-->>Coordinator: encrypted_key (hex-encoded)
Coordinator->>API: IpnsPublishRequest with encrypted_ipns_private_key & key_epoch
API-->>Coordinator: Publish success
end
rect rgba(100, 200, 150, 0.5)
Note over App,API: Subsequent File Publish (existing file)
App->>App: release_handle() called on modified file
App->>Coordinator: Compute is_new_file = false (CID present)
App->>Coordinator: Clone tee_public_key & epoch (but not used)
App->>Coordinator: publish_file_metadata(is_first_publish=false, ...)
Coordinator->>Crypto: Skip TEE wrapping
Coordinator->>API: IpnsPublishRequest with encrypted_ipns_private_key=None, key_epoch=None
API-->>Coordinator: Publish success (no re-enrollment)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #360 +/- ##
===========================================
+ Coverage 59.31% 69.40% +10.09%
===========================================
Files 126 105 -21
Lines 9180 6210 -2970
Branches 892 892
===========================================
- Hits 5445 4310 -1135
+ Misses 3531 1696 -1835
Partials 204 204
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR adds three desktop-focused capabilities: (1) enrolling newly created per-file IPNS keys with the TEE on first publish (to enable periodic republishing), (2) integrating the Tauri v2 updater with launch + manual checks, and (3) adding a GitHub Actions workflow to build/signed desktop release artifacts for the updater pipeline.
Changes:
- Thread TEE public key + epoch into per-file
publish_file_metadataon both Unix (FUSE) and Windows (WinFsp), wrapping the per-file IPNS private key on first publish. - Add a new desktop updater module, wire it into app startup, and expose a “Check for Updates…” tray menu action; enable updater capability + config.
- Add a release-triggered CI workflow to build/signed desktop bundles (macOS arm64+x86_64, Linux, Windows) and upload updater artifacts to GitHub Releases.
Reviewed changes
Copilot reviewed 25 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/fuse/src/read_ops.rs | Passes tee_public_key/tee_key_epoch + first-publish flag into per-file publish during release() uploads (Unix). |
| crates/fuse/src/operations.rs | Adds TEE enrollment fields to per-file IPNS publish request (Unix). |
| crates/fuse/src/platform/windows/write_ops.rs | Computes first-publish flag and passes TEE params into per-file publish path (Windows). |
| crates/fuse/src/platform/windows/operations.rs | Adds TEE enrollment fields to per-file IPNS publish request (Windows). |
| apps/desktop/src-tauri/src/updater.rs | New module implementing launch-delayed and manual update checks + notifications. |
| apps/desktop/src-tauri/src/main.rs | Registers updater plugin and triggers update check on launch. |
| apps/desktop/src-tauri/src/tray/mod.rs | Adds tray menu item + handler for manual update checks. |
| apps/desktop/src-tauri/tauri.conf.json | Enables updater artifact generation and configures updater endpoints + Ed25519 pubkey. |
| apps/desktop/src-tauri/capabilities/default.json | Grants updater capability permission. |
| apps/desktop/src-tauri/Cargo.toml | Adds tauri-plugin-updater dependency. |
| .github/workflows/build-desktop.yml | Builds signed desktop artifacts on release publish and uploads updater assets to the release. |
| Cargo.lock | Locks new/updated Rust dependencies (including updater plugin and related transitive deps). |
| .planning/phases/25-desktop-enhancements/25-CONTEXT.md | Phase context for desktop enhancements work. |
| .planning/phases/25-desktop-enhancements/25-RESEARCH.md | Research notes and integration patterns for updater + TEE enrollment. |
| .planning/phases/25-desktop-enhancements/25-VALIDATION.md | Validation strategy for Phase 25. |
| .planning/phases/25-desktop-enhancements/25-VERIFICATION.md | Verification report for Phase 25 deliverables. |
| .planning/phases/25-desktop-enhancements/25-01-PLAN.md | Execution plan for TEE per-file enrollment. |
| .planning/phases/25-desktop-enhancements/25-01-SUMMARY.md | Summary of the TEE enrollment plan execution. |
| .planning/phases/25-desktop-enhancements/25-02-PLAN.md | Execution plan for updater integration. |
| .planning/phases/25-desktop-enhancements/25-02-SUMMARY.md | Summary of the updater integration execution. |
| .planning/phases/25-desktop-enhancements/25-03-PLAN.md | Execution plan for desktop CI build workflow. |
| .planning/phases/25-desktop-enhancements/25-03-SUMMARY.md | Summary of the CI workflow execution. |
| .planning/config.json | Fixes JSON formatting/structure. |
| .planning/STATE.md | Updates planning state and progress counters. |
| .planning/ROADMAP.md | Marks Phase 25 as completed and updates roadmap progress section. |
| .planning/REQUIREMENTS.md | Marks DESKTOP-01 / DESKTOP-02 as complete. |
| .planning/PROJECT.md | Updates project “Last updated” marker for Phase 25 completion. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/build-desktop.yml:
- Around line 80-88: In the "Install WinFsp (Windows)" step add SHA256 integrity
verification before running msiexec: after downloading to $winfspMsi compute the
file hash (e.g., use PowerShell Get-FileHash -Algorithm SHA256) and compare it
against the expected SHA256 for winfsp-2.0.23075; if the hash does not match,
fail the job and do not call Start-Process msiexec.exe; update the step to store
the expected checksum in a variable or literal and ensure comparison uses a
case-insensitive string match so the installer only runs on a verified MSI.
In `@crates/fuse/src/operations.rs`:
- Around line 165-181: The current match on (is_first_publish, tee_public_key)
can set encrypted_ipns_private_key while leaving key_epoch as None, producing a
half-configured TEE enrollment; modify the construction so that when
encrypted_ipns_private_key is Some(...) you always set key_epoch to
Some(tee_key_epoch) and when you choose None for encrypted_ipns_private_key you
also pass None for key_epoch; update the match handling around is_first_publish,
tee_public_key and tee_key_epoch that builds encrypted_ipns_for_tee and
tee_epoch to guarantee both fields are set or both are None before creating the
cipherbox_api_client::IpnsPublishRequest (fields encrypted_ipns_private_key and
key_epoch).
In `@crates/fuse/src/platform/windows/operations.rs`:
- Around line 360-379: The current TEE enrollment branch can set
encrypted_ipns_private_key while leaving key_epoch None; update the logic around
is_first_publish/tee_public_key so you only produce encrypted_ipns_for_tee and
tee_epoch together or neither: when (true, Some(tee_key)) is matched, verify
tee_key_epoch is Some and error out if it is None (reject half-configured TEE),
otherwise wrap file_ipns_private_key and set both encrypted_ipns_for_tee and
tee_epoch from tee_key_epoch; ensure the IpnsPublishRequest
(cipherbox_api_client::IpnsPublishRequest) is populated with either both
encrypted_ipns_private_key and key_epoch Some or both None so no partial
enrollment is sent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4f16522f-1db8-46a1-ac02-4e85b7c4a382
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (26)
.github/workflows/build-desktop.yml.planning/PROJECT.md.planning/REQUIREMENTS.md.planning/ROADMAP.md.planning/STATE.md.planning/config.json.planning/phases/25-desktop-enhancements/25-01-PLAN.md.planning/phases/25-desktop-enhancements/25-01-SUMMARY.md.planning/phases/25-desktop-enhancements/25-02-PLAN.md.planning/phases/25-desktop-enhancements/25-02-SUMMARY.md.planning/phases/25-desktop-enhancements/25-03-PLAN.md.planning/phases/25-desktop-enhancements/25-03-SUMMARY.md.planning/phases/25-desktop-enhancements/25-CONTEXT.md.planning/phases/25-desktop-enhancements/25-RESEARCH.md.planning/phases/25-desktop-enhancements/25-VALIDATION.md.planning/phases/25-desktop-enhancements/25-VERIFICATION.mdapps/desktop/src-tauri/Cargo.tomlapps/desktop/src-tauri/capabilities/default.jsonapps/desktop/src-tauri/src/main.rsapps/desktop/src-tauri/src/tray/mod.rsapps/desktop/src-tauri/src/updater.rsapps/desktop/src-tauri/tauri.conf.jsoncrates/fuse/src/operations.rscrates/fuse/src/platform/windows/operations.rscrates/fuse/src/platform/windows/write_ops.rscrates/fuse/src/read_ops.rs
- Fix ROADMAP.md: check plan boxes, add missing v1.1 milestone column - Fix STATE.md: update position to COMPLETE 3/3 - Add SHA256 checksum verification for WinFsp MSI download (matches ci.yml, deploy-staging.yml, desktop-e2e.yml pattern) - Guard against half-configured TEE enrollment: error if tee_public_key is present but tee_key_epoch is missing (both Unix and Windows) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 7227dc8b9ee1
Summary
Key files
crates/fuse/src/operations.rspublish_file_metadata(Unix)crates/fuse/src/platform/windows/operations.rsapps/desktop/src-tauri/src/updater.rsapps/desktop/src-tauri/src/tray/mod.rs.github/workflows/build-desktop.ymlapps/desktop/src-tauri/tauri.conf.jsonTest plan
cargo check -p cipherbox-fuse --features fusecompiles cleanlyupdater.rshascheck_on_launchandmanual_checkfunctionstauri.conf.jsonhas real Ed25519 public key (not placeholder)build-desktop.ymltriggers onrelease: [published]with 4-platform matrixTAURI_SIGNING_PRIVATE_KEYandTAURI_SIGNING_PRIVATE_KEY_PASSWORDare set🤖 Generated with Claude Code