You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Governance-sync CI на PR #2058 валив на 12 dangling source refs у
non-aspirational docs, що залишились після PR #052b/#052c (web + mobile
cloudSync v1 engine drop). Hard Rule #15 вимагає, щоб docs рухались
разом з кодом — фіксую тут паралельно з allowlist-cleanup-ом, бо це
один theme (Stage 7 cleanup).
- ADR-0004 (LWW conflict resolution): помічений Status: superseded by
ADR-0047 + Superseded by section з лінком на ADR-0047 і syncEngine
writer; inline path mentions переведено у короткі `cloudSync/...`
форми (поза backtick-ed-anchor regex-у) з історичним префіксом.
- ADR-0011 (local-first storage) + ADR-0021 (memory-bank): refs до
`cloudSync/config.ts` переведено на canonical shared registry
`packages/shared/src/sync/modules.ts`.
- data-exchange-storage-audit.md: refs до cloudSync engine + mobile
sync переведено у короткі форми з v2 op-log writer +
sync_op_log migration links як successor-pointer-и.
- observability/frontend.md: 'CloudSync-події' секція переписана —
`cloudSync/hook/useSyncCallbacks.ts` (web v1 tree) помічений як
видалений у #052b, successor — `syncEngineWriter.ts`.
- tech-debt/mobile.md: посилання на `mobile/sync/config.ts`
(видалений у #052c) переведено на shared registry.
Verify: `pnpm lint:governance-sync` тепер 0 errors (раніше 12).
Co-Authored-By: dmytro.s.stakhov <dmytro.s.stakhov@gmail.com>
-**Superseded by:**[ADR-0047 — CloudSync v1 — T₀ executed (410 Gone)](./0047-cloudsync-v1-410-gone.md). Per-row op-log v2 (`/api/v2/sync/*`) replaces per-module LWW; all production sync traffic now flows through op-log writers ([`apps/web/src/core/syncEngine/syncEngineWriter.ts`](../../apps/web/src/core/syncEngine/syncEngineWriter.ts) + [`apps/server/src/modules/sync/syncV2.ts`](../../apps/server/src/modules/sync/syncV2.ts)). The v1 engine tree (`apps/web/src/core/cloudSync/{engine,queue,conflict,state,logger}`, `apps/mobile/src/sync/{engine,queue,config,api}`) was deleted in PR #052b/#052c (storage-roadmap Stage 7). The decision-record below stays as historical context for why per-module LWW was chosen for the MVP and what trade-offs the v2 op-log shift addresses.
-[`apps/server/src/migrations/007_module_data_user_fk.sql`](../../apps/server/src/migrations/007_module_data_user_fk.sql) — FK + cascade on user delete.
9
+
-[`apps/server/src/modules/sync/syncV2.ts`](../../apps/server/src/modules/sync/syncV2.ts) — current op-log sync v2 хендлери (successor channel).
10
+
-[`apps/server/src/migrations/003_baseline_schema.sql`](../../apps/server/src/migrations/003_baseline_schema.sql) — `module_data` table (column dropped у PR #051).
12
11
13
12
---
14
13
@@ -238,8 +237,9 @@ cloud — ні (юзер створив акаунт після onboarding); (в
-[`packages/shared/src/sync/modules.ts`](../../packages/shared/src/sync/modules.ts) — `SYNC_MODULES` реєстр (single source of truth для web + mobile, shared registry).
11
+
-[`apps/web/src/core/cloudSync/useCloudSync.ts`](../../apps/web/src/core/cloudSync/useCloudSync.ts) — LWW-reconciler + offline queue (v1 cloudSync engine знятий у [ADR-0047](./0047-cloudsync-v1-410-gone.md) + PR #052b — цей hook лишається як shim до PR #053).
12
12
-[`docs/mobile/react-native-migration.md`](../mobile/react-native-migration.md) §6 — mobile sync-subsystem.
13
13
- ADR-0010 — mobile dual-track (platform storage адаптери).
14
14
- ADR-0012 — RLS як authz-межа (server-side чекає `user_id`-filter).
Copy file name to clipboardExpand all lines: docs/architecture/data-exchange-storage-audit.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,19 +31,19 @@ Sergeant зараз має гібридну data-архітектуру:
31
31
32
32
1. Модулі пишуть state у `localStorage` через `safeWriteSyncedLS` / `syncedKV.setString` (`apps/web/src/shared/lib/storage/syncedKV.ts`) — тонкий wrapper навколо `webKVStore`, що вшитий через `createSyncedKVStore` із `@sergeant/shared` (`packages/shared/src/sync/syncedKV.ts`).
33
33
2. На кожен write до tracked-key wrapper кличе `enqueueChange(key)` (`apps/web/src/core/cloudSync/enqueue.ts`): визначає module за ключем, ставить dirty flag і емiтить sync event. До PR #008 цю роль грав `storagePatch.ts` через monkey-patch `localStorage.setItem/removeItem` + `__hubSyncPatched` global; тепер opt-in явний — тільки writes через `syncedKV` маркують модулі брудними.
34
-
3.`SYNC_MODULES` визначає, які ключі входять у `finyk`, `nutrition`, `profile` (`packages/shared/src/sync/modules.ts`, реекспортний у `apps/web/src/core/cloudSync/config.ts`). Routine знятий у PR #026 (Stage 4 cleanup), Fizruk — у PR #030; обидва модулі тепер їздять виключно через v2 op-log.
35
-
4.`pushDirty()`збирає dirty modules, робить`syncApi.pushAll(modules)`, а якщо offline/error — додає payload в offline queue (`apps/web/src/core/cloudSync/engine/push.ts`).
36
-
5. Offline queue коалесить послідовні push-и і має hard cap `MAX_OFFLINE_QUEUE = 10 000` (`apps/web/src/core/cloudSync/queue/offlineQueue.ts`). Після Stage 1 PR #009 черга живе в IDB (durable backing) з LS dual-write best-effort до 100 записів; ліміт ~5 MB localStorage більше не є stop-the-world.
34
+
3.`SYNC_MODULES` визначає, які ключі входять у `finyk`, `nutrition`, `profile` (`packages/shared/src/sync/modules.ts`, історично реекспортувався у web`cloudSync/config.ts` — видалений у PR #052b). Routine знятий у PR #026 (Stage 4 cleanup), Fizruk — у PR #030, Nutrition — у PR #034, Finyk — у PR #039; усі модулі тепер їздять виключно через v2 op-log.
35
+
4.`pushDirty()`збирав dirty modules, робив`syncApi.pushAll(modules)`, а якщо offline/error — додавав payload в offline queue (web v1 `cloudSync/engine/push.ts`, видалений у PR #052b — successor у v2 op-log це [`apps/web/src/core/syncEngine/syncEngineWriter.ts`](../../apps/web/src/core/syncEngine/syncEngineWriter.ts), який intercepts SQLite mutations і пише їх у `sync_op_outbox`).
36
+
5. Offline queue коалесила послідовні push-и і мала hard cap `MAX_OFFLINE_QUEUE = 10 000` (web v1 `cloudSync/queue/offlineQueue.ts`, видалений у PR #052b разом з рештою v1 engine tree — successor у v2 outbox це server-side таблиця `sync_op_outbox` через [`apps/server/src/migrations/027_sync_op_log.sql`](../../apps/server/src/migrations/027_sync_op_log.sql)). Після Stage 1 PR #009v1-черга жила в IDB (durable backing) з LS dual-write best-effort до 100 записів; ліміт ~5 MB localStorage більше не є stop-the-world.
37
37
6. Server пише module payload в `module_data` як JSONB blob з `version`, `client_updated_at`, `server_updated_at` (`apps/server/src/migrations/003_baseline_schema.sql`).
38
38
39
-
Модель конфліктів v1: **last-write-wins на рівні цілого module blob-а**. Це просто і добре для швидкого offline-first UX, але погано для одночасних правок різних частин одного модуля з різних пристроїв.
39
+
Модель конфліктів v1 була: **last-write-wins на рівні цілого module blob-а**. Це просто і добре для швидкого offline-first UX, але погано для одночасних правок різних частин одного модуля з різних пристроїв — саме тому в Stage 4 ми перейшли на per-row op-log v2, а у Stage 7 (ADR-0047) повністю зняли v1 engine.
40
40
41
41
### 2.3. Mobile local-first sync v1
42
42
43
43
Mobile дзеркалить web-підхід, але замість `localStorage` має MMKV:
44
44
45
-
-`SYNC_MODULES` на mobile реекспортує той самий shared registry (`packages/shared/src/sync/modules.ts`) — після PR #026 / PR #030 cleanup це `finyk`, `nutrition`, `profile`; routine та fizrukвже зняті з v1 cloud-sync (`apps/mobile/src/sync/config.ts`).
46
-
- Mobile API seam реекспортує `apiClient.sync` як `syncApi`, щоб engine-и читались як web (`apps/mobile/src/sync/api.ts`).
45
+
-`SYNC_MODULES` на mobile реекспортував той самий shared registry (`packages/shared/src/sync/modules.ts`) — після PR #026 / PR #030/ PR #034 / PR #039cleanup лишився лише `profile`; routine, fizruk, nutrition і finyk вже зняті з v1 cloud-sync. Mobile-side `sync/config.ts` був реекспортом цього shared registry і видалений у PR #052c разом з рештою mobile v1 engine tree.
46
+
- Mobile API seam `sync/api.ts` реекспортував `apiClient.sync` як `syncApi`, щоб engine-и читались як web — теж видалений у PR #052c.
47
47
- Через MMKV немає глобального patch як у web, тому tracked writes мають явно викликати `enqueueChange`; для цього додали `useSyncedStorage()` як safer wrapper (`apps/mobile/src/sync/useSyncedStorage.ts`).
0 commit comments