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.
onStatereplaces 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,buildStateran withgroups: [], 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