Closes 9.3 in full: migration 016 + pgTAP test 010 + queue.ts conflict-detection path + /settings debug panel + integration test. - Migration 016 adds public.sync_conflicts (append-only audit log of last-write-wins conflicts surfaced by the offline mutation queue). RLS allows owners to SELECT + INSERT their own rows only; UPDATE and DELETE have no policy and are silently denied. collective_id is intentionally nullable so user-level conflicts (theme, language in future) also fit. Indexed on (user_id, created_at desc) for the "show me my last 20 conflicts" query. - queue.ts gains a `QueueContext` (currentUserId + collectiveId) and an optional `preImage` field on UpdateOp. Before sending an UPDATE the queue fetches the remote row (limited to the patched fields), proceeds with the UPDATE (last-write-wins), then fires a best-effort INSERT into sync_conflicts when the remote diverged. Failure to log never blocks the UPDATE or pollutes the pending_ops queue. Three unit specs (SC-01..SC-03) lock the contract in. - sync/index.ts exposes setSyncContext(), called from (app)/+layout's $effect whenever currentUser / currentCollective change. - New SyncConflictsPanel.svelte renders the last 20 conflict rows for the current user with an "Export JSON" button. Gated on import.meta.env.DEV (or a forceShow prop for a future secret unlock) — never ships in the production bundle. Slotted into /settings just above the Account section. - Integration tests (packages/test-utils/tests/sync-conflicts.test.ts, 4 SC-INT specs) exercise the real PostgREST + RLS contract end-to-end with the existing seed users (Ana, Borja). Requires fake-indexeddb in the test-utils dev deps (queue's IDB shim). - pgTAP test 010 covers structure, RLS reads/writes, ownership rejection, and the append-only invariant (UPDATE/DELETE return 0 rows). - packages/types/src/database.ts adds the sync_conflicts table type. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
28 lines
517 B
JSON
28 lines
517 B
JSON
{
|
|
"name": "@colectivo/test-utils",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"type": "module",
|
|
"main": "./src/index.ts",
|
|
"exports": {
|
|
".": "./src/index.ts"
|
|
},
|
|
"scripts": {
|
|
"test": "vitest run",
|
|
"test:watch": "vitest"
|
|
},
|
|
"dependencies": {
|
|
"@colectivo/types": "workspace:*",
|
|
"@supabase/supabase-js": "^2.46.2",
|
|
"jose": "^5.9.6",
|
|
"pg": "^8.13.3"
|
|
},
|
|
"devDependencies": {
|
|
"@types/pg": "^8.11.10",
|
|
"fake-indexeddb": "^6.2.5",
|
|
"typescript": "^5.7.3",
|
|
"vite": "^6.0.7",
|
|
"vitest": "^2.1.8"
|
|
}
|
|
}
|