Skip to content

Sync - #149

Merged
ChristianChiarulli merged 6 commits into
masterfrom
sync
Mar 14, 2026
Merged

Sync#149
ChristianChiarulli merged 6 commits into
masterfrom
sync

Conversation

@ChristianChiarulli

@ChristianChiarulli ChristianChiarulli commented Mar 14, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Introduced note synchronization system enabling real-time sync across devices via relay support.
    • Added sync status indicator in the sidebar displaying current connection state (connected, syncing, disconnected, error).
    • Automated macOS build releases with DMG artifact generation.
  • Dependencies

    • Updated and added dependencies for synchronization and WebSocket support.
  • Documentation

    • Updated contribution guidelines regarding commit message formats.

ChristianChiarulli and others added 6 commits March 14, 2026 15:42
Sync engine (sync.rs) connects to a configured relay via WebSocket,
authenticates with NIP-42, and subscribes to NIP-CF CHANGES feed for
gift-wrapped (NIP-59) events. Notes are encrypted end-to-end — the
relay only sees opaque kind:1059 blobs.

- SyncManager as Tauri managed state with auto-start on app launch
- Note-to-event mapping: notes become kind:30023 rumors, sealed and
  gift-wrapped to self with NIP-44 encryption
- Bidirectional sync: local mutations push to relay with 2s debounce,
  remote changes upsert locally with last-write-wins resolution
- Echo prevention via recently-pushed event ID tracking
- Exponential backoff reconnection on disconnect
- Sync state reset on relay or identity change
- DB migration adds sync_event_id column for deletion targeting
- Sync status indicator in sidebar (cloud icons for connected/syncing/error/disconnected)
- Seed script updated with stable test keypair and sync_event_id column
The sync_event_id must be read before delete_note_permanently destroys
the row, and the deletion push should only fire after the local delete
succeeds. Pass the pre-fetched ID through the SyncCommand to avoid a
redundant query against a now-missing row.
After the build matrix completes, a release job collects the aarch64
and x86_64 DMGs and publishes them as a GitHub release tagged by
commit SHA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 02f0b952-8526-4d65-9237-19d8c5fb624c

📥 Commits

Reviewing files that changed from the base of the PR and between 48a2902 and e3f0448.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • CLAUDE.md
  • package.json
  • scripts/seed-db.sh
  • src-tauri/Cargo.toml
  • src-tauri/src/db.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/sync.rs
  • src/features/shell/sidebar-pane.tsx

📝 Walkthrough

Walkthrough

This PR introduces a WebSocket-based synchronization subsystem using the Nostr protocol. It adds database schema migrations for sync event tracking, new Rust dependencies for WebSocket communication, a comprehensive SyncManager implementation with state management, and integrates sync status display into the sidebar UI.

Changes

Cohort / File(s) Summary
CI/CD Workflow
.github/workflows/ci.yml
Adds architecture hints to macOS build matrix, uploads DMG artifacts on push, creates GitHub releases with DMG files, and passes Apple signing credentials as environment variables during builds.
Documentation
CLAUDE.md
Documents commit message style guidance prohibiting Co-Authored-By lines.
Dependencies
package.json, src-tauri/Cargo.toml
Adds @types/react-highlight-words package; updates nostr-sdk with nip59 feature flag; introduces tokio-tungstenite, futures-util, and log dependencies for async WebSocket and logging.
Database Schema & Migrations
scripts/seed-db.sh, src-tauri/src/db.rs
Adds nostr_identity table with test seed data; introduces sync_event_id TEXT column to notes table; splits migration into two sequential steps for schema progression.
Core Sync Implementation
src-tauri/src/sync.rs
Introduces comprehensive SyncManager subsystem with state machine (Disconnected, Connecting, Authenticating, Syncing, Connected, Error); implements WebSocket relay communication, Nostr AUTH handshake, CHANGES event subscription, checkpoint tracking, and bidirectional sync with debouncing and deletion handling.
Application Integration
src-tauri/src/lib.rs
Wires SyncManager into app lifecycle; adds get_sync_status and restart_sync Tauri commands; injects sync pushes after note operations (save, archive, restore, assign); resets sync state on identity import; manages relay configuration changes.
Frontend UI
src/features/shell/sidebar-pane.tsx
Replaces static Profile button with dynamic Sync indicator; fetches sync status via get_sync_status command; subscribes to sync-status events; renders context-aware icons (connected, syncing, error, disconnected) and labels.

Sequence Diagram(s)

sequenceDiagram
    participant Frontend as Frontend (Sidebar)
    participant App as Tauri App
    participant SyncMgr as SyncManager
    participant DB as Database
    participant Relay as WebSocket Relay

    rect rgba(200, 150, 255, 0.5)
    Note over Frontend,Relay: Initialization & Auth
    Frontend->>App: get_sync_status()
    App->>SyncMgr: state()
    SyncMgr-->>App: SyncState::Connecting
    App-->>Frontend: Display connecting icon

    SyncMgr->>DB: Fetch relay URL & identity
    SyncMgr->>Relay: WebSocket connect
    Relay-->>SyncMgr: Connected
    SyncMgr->>Relay: AUTH handshake
    Relay-->>SyncMgr: AUTH success
    SyncMgr->>SyncMgr: Update state to Syncing
    end

    rect rgba(150, 200, 255, 0.5)
    Note over SyncMgr,Relay: Sync Loop & Event Processing
    SyncMgr->>Relay: Subscribe CHANGES
    Relay-->>SyncMgr: EVENT (remote note)
    SyncMgr->>DB: Upsert note with sync_event_id
    SyncMgr->>App: Emit sync-remote-change
    App-->>Frontend: Update remote changes
    end

    rect rgba(255, 200, 150, 0.5)
    Note over Frontend,SyncMgr: Local Mutation & Push
    Frontend->>App: save_note()
    App->>SyncMgr: push(PushNote)
    SyncMgr->>SyncMgr: Debounce & construct event
    SyncMgr->>Relay: Send note event
    Relay-->>SyncMgr: ACK
    SyncMgr->>DB: Update checkpoint
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hop, sync, relay and bound,
Events flowing all around,
Nostr whispers through the wire,
SyncManager climbs ever higher—
No more islands, notes now float,
On WebSocket's swift, connected boat! 🚀

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sync
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@ChristianChiarulli
ChristianChiarulli merged commit 63e5fcb into master Mar 14, 2026
1 of 2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Mar 15, 2026
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.

1 participant