Same-User Multi-Device Sync (My Phone = My Vault)
Runa the Artificer — Backend Engineer
By the end of this chapter you’ll understand:
- What infrastructure was missing before this epic (the relay Worker, the API contract mismatch, the wrong pairing UI)
- How the per-field conflict resolution in the replay engine works
- What remains unfinished and why (QR scan, UI indicators, Android)
Same-User Multi-Device Sync (My Phone = My Vault)
Status: Delivered
CAS: CAS-3073
Delivered: 2026-05-17
PRs: #842, #850, #851, #853, #855, #866, #868, #869, #870, #871, #872, #873, #874
What’s new
You can now add your iPhone as a second device that carries your same vault — not a partner’s profile, not a new account, but your own data on your phone. Once paired, both devices stay in sync: every transaction, rule, and tag you add on desktop appears on mobile and vice versa. Conflicts are resolved automatically using per-field merge rules, so neither device’s work is silently discarded.
How to use it
- On desktop, open Settings → Devices and generate a pairing code or QR.
- On iPhone, open Casaconomy → tap the “Add this device” option and scan the QR (or enter the code manually — camera scan is currently manual-entry only).
- Once paired, sync is automatic. Every change on either device is pushed to the relay and replayed on the other within seconds.
You don’t need to do anything ongoing — sync runs in the background on every DB write.
What changed under the hood
casaconomy-sync-relayCloudflare Worker deployed — new D1 database, R2 bucket, HMAC-auth, rate-limit bindings, retention cron, and/vaults/{id}/changesetsroutes. This was the missing infrastructure layer; sync had no backend to write to before this.- API contract aligned — desktop and iOS clients reconciled to the relay’s
/vaults/{id}/changesetsURL scheme; the old/v1/snapshotsmismatch is gone. - Per-field conflict resolution in the replay engine (
replay_engine.rs) — overlapping writes are merged field-by-field with a deterministic rule set and an audit log; convergence proved across 8 scenarios. - Client-side changeset push — every local SQLite write now serialises a changeset and pushes it to the relay; iOS receives inbound changesets via the
vault-sync://changeset-receivedURL-scheme event.
Why we built it
The regent’s intent for Casaconomy has always been “my phone is just another window onto my vault.” The pairing relay existed (CAS-583/CAS-2877) but the data-sync backend was never deployed, the client–relay contract never matched, and the device-pair UI invited a “partner” rather than cloning the same user. This epic closes all three gaps and makes the “add my phone” flow functional end-to-end for the first time.
Known limitations / follow-on work
- iPhone camera QR scanning does not work — manual code entry is required (CAS-3070, tracked separately).
- iOS sync-received events are wired but not yet surfaced as UI indicators (loading states, “synced N seconds ago” banners).
- Android is not yet supported.
- Sync is changeset-based (not snapshot-based); the older encrypted-snapshot path (CAS-1093) remains for cold restore and is not replaced by this epic.
Recap
- Three gaps closed in one epic: the sync relay Cloudflare Worker was deployed (it never existed before), the client–relay API contract was aligned, and the pairing UI was corrected from “add a partner” to “add my phone.”
- Per-field conflict resolution in
replay_engine.rsmerges overlapping writes deterministically using last-writer-wins on timestamps; convergence is proved across 8 scenarios. - iPhone QR scanning, sync UI indicators, and Android support remain as tracked follow-on items.