Skip to content

Executive Summary

Modern applications increasingly adopt local-first architecture—data lives on the device, works offline, and syncs opportunistically. This approach delivers superior user experience: instant responsiveness, offline capability, and data ownership.

However, sync is hard. Developers face a painful choice:

OptionProblem
Firebase/SupabaseVendor lock-in, data leaves device unencrypted, recurring costs
Build customMonths of networking, encryption, conflict resolution work
Skip syncUsers stuck on single device, competitive disadvantage

Local-first frameworks (Tauri, Electron, React Native, Flutter) have matured for building desktop and mobile applications. Developers can build, package, and distribute apps easily.

Missing piece: Sync. Local-first developers have no turnkey, zero-knowledge solution for multi-device synchronization that doesn’t require trusting a third party with their users’ data.


A zero-knowledge relay that passes encrypted blobs between devices. The relay never sees plaintext data—it’s a dumb pipe.

Zero-knowledge relay flow: Device A sends encrypted blob to relay, relay forwards to Device B, Device B ACKs and blob is deleted

Multi-relay fan-out (Phase 6.5): Clients push to multiple relays simultaneously. Primary relay is awaited; secondaries are fire-and-forget. On connect, the client tries each relay in order until one succeeds (automatic failover). Each relay tracks cursors independently.

Key insight: The client library stays constant. Only the relay tier changes.

ComponentPurpose
sync-clientRust library for E2E encryption, pairing, cursor tracking, multi-relay failover
sync-contentLarge file transfer via iroh-blobs (encrypt-then-hash)
sync-relayStateless message router with temporary buffering (runs independently per region)
sync-bridgeFFI bridge — resolves generic SyncClient<T> into concrete SyncHandle for bindings
sync-nodenapi-rs bindings — @0k-sync/native npm package for Bun/Node.js/Deno
sync-pythonPyO3 bindings — zerok-sync pip package for Python 3.10+
  • Data storage — Relay is pass-through only, not a database
  • Conflict resolution — CRDTs are app responsibility (we transport blobs)
  • User accounts — Zero-knowledge pairing via QR/codes
  • Proprietary dependencies — 100% open source stack

Three gates must be addressed before GA release:

GateStatusAction Required
Security Audit✅ CompleteTwo audits complete (2026-02-05). 35 findings, 0 critical/high remaining. Noise Protocol (clatter) implemented.
Enterprise Compliance⚠️ Blocked”FIPS Mode” fallback using AES-GCM/PBKDF2 for regulated markets
Infrastructure✅ ReadyCloudflare Tunnel validated; self-hosted iroh-relay option
ComponentChoiceVersionValidation
P2P networkingiroh0.96200K+ connections, stable API
Transport encryptioniroh QUIC (TLS 1.3)0.96Wire encryption via iroh
Noise Protocolclatter2.2Hybrid ML-KEM-768 + X25519
Large contentiroh-blobs0.98BLAKE3/Bao verified streaming
Blob encryptionXChaCha20-Poly1305RustCrypto192-bit nonces, no coordination needed
Key derivationArgon2idRustCryptoDevice-adaptive parameters
Transportiroh0.96QUIC P2P + relay fallback
StorageSQLite + WALvia sqlx70K+ writes/sec

iroh Version Strategy:

  • Production: iroh 0.96 (requires cargo patch for curve25519-dalek)
  • Content transfer: iroh-blobs 0.98 for large files
  • Discovery: mDNS (LAN), DNS, optional DHT

⚠️ Dependency Note: iroh 0.96 requires a cargo patch for curve25519-dalek 5.0.0-pre.1. See workspace Cargo.toml [patch.crates-io] section. PR #878 submitted upstream.


Protocol stack: Layer 0 (Transport) through Layer 4 (Application Sync Logic)

FunctionAlgorithmNotes
CipherXChaCha20-Poly1305192-bit nonce (not 96-bit)
Transportiroh QUIC (TLS 1.3)Wire encryption
KDFArgon2idDevice-adaptive: 19-64 MiB based on RAM (OWASP minimum: 19 MiB)

Why XChaCha20 (not standard ChaCha20)?

  • 192-bit nonces eliminate collision risk (safe threshold: 2^80 vs 2^32)
  • Random nonce generation safe without cross-device coordination
  • Negligible performance overhead (one HChaCha20 block)
PropertyHow Achieved
Zero-knowledge relayE2E encryption with Group Key; relay sees only ciphertext
No accountsDevices pair via QR code or short code; no email/password
Forward secrecyiroh QUIC TLS (transport level). Noise Protocol XX planned for application-level forward secrecy.
Replay protectionMonotonic cursors + nonces
Relay redundancyMulti-relay fan-out with automatic connect failover (Phase 6.5)

Mobile platforms kill background network connections within ~30 seconds of backgrounding. Solution:

Mobile architecture modes: Foreground (active sync), Background (sockets closed), Wake events

Key principle: Never block on app close. Fire-and-forget flush with 500ms timeout. Stranded commits sync on next launch.


Six tiers serve the full market:

TierInfrastructureTarget User
1. Vibe Coderiroh public networkHobbyist, zero setup
2. Home DeveloperSelf-hosted DockerPrivacy-focused
3. Vercel-styleContainer on PaaSStartup on budget
4. Community SyncManaged Cloud sharedIndie developer
5. CloudManaged Cloud dedicatedFunded startup
6. EnterpriseCustomer infrastructureRegulated industry

Developer Experience (All Tiers):

// One line to add sync
use sync_client::SyncClient;
let client = SyncClient::new(SyncConfig::default()).await?;
client.push(encrypted_blob).await?;

Changing tiers = changing one config value. No code changes.


Crate dependency structure: sync-types → sync-core → sync-client → bindings and sync-relay

CrateTest Strategy
sync-typesSerialization round-trip
sync-corePure logic, instant tests (no I/O)
sync-clientCrypto verification, mock transport
sync-cliE2E headless scripts
integrationsFramework-specific tests

From research validation:

  1. Thundering Herd Mitigation — Client-side exponential backoff with jitter on reconnect
  2. Device-Adaptive Argon2 — 12 MiB (low-end) to 64 MiB (desktop) based on available RAM
  3. XChaCha20 Nonces — 192-bit random nonces, never 96-bit
  4. Noise Protocol — Hybrid clatter with ML-KEM-768 + X25519 implemented
  5. iroh 0.96 — Pre-1.0 but stable, requires cargo patch (see Cargo.toml)

RiskSeverityMitigation
Post-quantum transitionLowHybrid Noise (clatter ML-KEM-768) implemented
FIPS compliance gapCritical (for Gov/Finance)Feature flag for AES-GCM/PBKDF2 build
iroh ecosystem maturityLowUsing stable 0.96; self-hosted option; multi-relay failover implemented
Mobile battery impactMediumWake-on-Push architecture; quantify in beta
Thundering herdMediumClient-side jitter required

QuestionAnswer
What is it?Zero-knowledge sync protocol for local-first apps
Who is it for?Local-first developers (any framework)
Why build it?Fills the sync gap in local-first ecosystem
How does it scale?Client constant, relay tier changes
What’s validated?iroh 0.96 (E2E tested), XChaCha20-Poly1305, Argon2id, multi-relay fan-out. Multi-language bindings implemented (napi-rs, PyO3). Hybrid Noise Protocol (clatter ML-KEM-768 + X25519) implemented. 750+ tests across the workspace + 63 chaos scenarios.
What’s blocked?FIPS compliance (enterprise only)

0k-Sync completes local-first apps: Build → Store Locally → Sync Securely.