Skip to content

Feature: Sync Relay (Cloudflare Worker)

Feature: Sync Relay (Cloudflare Worker)

Status: Delivered
CAS: CAS-748
Delivered: 2026-04-26
Parent epic: CAS-171 Multi-Device Sync with E2E Encryption


What shipped

A Cloudflare Worker edge service that relays encrypted changesets between Casaconomy desktop clients. The relay is zero-knowledge by design: it stores and forwards opaque ciphertext blobs and cannot read payload content. All decryption happens on-device.

Architecture

Client A ──(push)──► Worker (edge, Cloudflare network)
D1 SQLite (weur) ── R2 (weur)
Client B ──(pull)──► Worker

Storage:

  • D1changesets, devices, vaults, snapshots metadata tables
  • R2 — full snapshot blobs (large uploads, content-addressed)

Entry point: workers/sync-relay/src/index.ts

Zero-knowledge property

The relay enforces ZK at the server layer:

  • ciphertext fields are stored and forwarded verbatim — no decode, parse, or inspect
  • D1 text columns contain only opaque bytes (verified by ZK audit test suite)
  • Nonces are treated as opaque identifiers, never inspected
  • Static audit script (scripts/check-zk-static.sh, npm run lint:zk) fails the build if ciphertext appears in console calls, decode paths, conditionals, or error strings

API

MethodPathPurpose
POST/vaults/:id/changesetsPush a changeset
GET/vaults/:id/changesetsPull changesets (since cursor)
POST/devicesRegister a device keypair
GET/devices/:idFetch device public key
POST/vaults/:id/snapshotsUpload a full snapshot to R2
GET/vaults/:id/snapshots/latestFetch latest snapshot metadata

Rate limiting is enforced per vault per IP. Devices authenticate via Ed25519 keypairs registered at pairing time.

Test suite (sub-task S6 / CAS-754)

  • ZK audit tests: 4 ciphertext-canary probes (push response, D1 columns, pull response cross-field, nonce opacity) — prove ciphertext never escapes the relay
  • E2E smoke: two-device cross-vault push/pull with sequence integrity and round-trip ciphertext fidelity
  • Concurrent burst load: 20 parallel pushes + 20 parallel pulls across distinct vaults — all must return 2xx, no 5xx
  • Static ZK grep audit: integrated into npm run lint:zk

52 tests across 6 files pass. ZK static audit: PASSED.

Tauri client side

transport_http.rs was updated to align the PushRequest struct with the relay API: added id, origin_device, origin_user, timestamp, operation_type, entity, entity_id, schema_version, key_id, and nonce fields. Renamed entity_typeentity to match the relay schema.


Sub-tasks delivered

IdentifierTitle
CAS-749S1 — D1 schema + wrangler config
CAS-750S2 — changeset push/pull handlers
CAS-751S3 — device registration + auth
CAS-752S4 — snapshot upload/fetch (R2)
CAS-753S5 — rate limiting + retention
CAS-754S6 — ZK audit test + E2E smoke + README