Skip to content

Work / Aakalan / Wiki / Concepts

sync-gates

Conceptverified 2026-10-30

sync-gates

src/services/sync.ts is what moved the store onto live data. Two rules are load-bearing:

  • Nothing is emitted until the groups listener has reported. onState replaces the remote-owned slice wholesale, groups included. The three top-level listeners resolve in any order, so without the gate the personal-expenses listener routinely reported first, buildState ran with groups: [], and the reducer deleted every group the user had, including one created seconds earlier. On screen it reads as a group that flickers and vanishes.
  • A groups query that ERRORS does not open that gate. An unreadable group list must never read as "this user has none".

src/services/subscribe.test.ts is the regression test for both.

Snapshot and write failures both surface through syncProblem on the store and the banner in src/components/ui/sync-banner.tsx. Nothing here may go back to being silent: a denied read looks exactly like an empty account, and a refused write looks like a row that saved and then vanished.

Related: data-seam, local-first-ledger