Sync Contract
:::info Source
Sourced from services/sync-service/SYNC_CONTRACT.md in the documentation repo.
:::
1. Self-Reference
This IS the sync service. This document describes the platform-wide sync protocol that all replicable services conform to.
2. Protocol Summary (Frozen F07)
| Endpoint | Method | Purpose |
|---|---|---|
/sync/v1/pull | POST | Server → client delta since cursor |
/sync/v1/push | POST | Client → server mutations |
/sync/v1/ack | POST | Client acknowledges applied deltas |
/sync/v1/resolve-conflict | POST | Resolve detected conflict |
/sync/v1/registrations | GET | List replicable entity types |
/sync/v1/status | GET | Per-device sync health |
3. Registered Entity Types (at platform launch)
| Service | Entity | Policy | Sync Direction |
|---|---|---|---|
| progress | Statement | append_only | push + pull |
| progress | Attempt | server_authoritative | pull |
| progress | CompletionRecord | server_authoritative | pull |
| assessment | QuizBank | server_authoritative | pull |
| assessment | BranchingScenario | server_authoritative | pull |
| assessment | AttemptResult | append_only | push + pull |
| certification | Certificate | server_authoritative | pull |
| certification | OfflineIssuanceClaim | append_only | push |
| enrollment | Enrollment | server_authoritative | pull |
| content | PlayPackageBundle | server_authoritative | pull |
| marketplace | Listing | server_authoritative | pull |
| marketplace | License | server_authoritative | pull |
| marketplace | Order | server_authoritative | pull |
| notification | Notification (in-app) | append_only | pull |
| authoring | CourseDraft (M5) | crdt_yjs | push + pull |
| identity | Device | server_authoritative | pull |
| tenant | Role + Permission | server_authoritative | pull |
| ai_gateway | Prompt (offline subset) | server_authoritative | pull |
| billing | Invoice + Subscription (view-only) | server_authoritative | pull |
4. Client-Side Responsibilities
- Maintain
statements_outbox,mutationsqueue in IndexedDB/SQLite. - Push on: app foreground, reconnect, 15-min timer.
- Pull after push completes.
- Ack after applying pulled deltas.
- Display pending conflicts in UI for manual resolution.
- Encrypt sensitive payloads in local store.
- 7-day offline max before read-only mode + forced sync prompt.
- 14-day max before local data purge.
5. Cursor Rules
- Opaque from client perspective.
- Server-generated; client stores + returns on next pull.
- Cursor includes:
{ lamport, v (format version) }. - Cursor format change via
vfield — server produces compatible cursors.
6. Delta Window
- Server retains 30 days of deltas.
- Cursor older than 30 days →
sync.cursor.out_of_range(410) → client must full-resync. - Full resync: client purges local entities + re-pulls entire scope.
7. VectorClock Semantics (F06)
- Each device tracks its own counter.
- On push: client sends its VectorClock.
- Server merges:
max(server[d], client[d])per device. - LWW comparison: total order via VectorClock comparison (lexicographic on
max(values)tie-broken bydeviceId).
8. Conflict Resolution UX
append_only: never conflicts.server_authoritative: auto-resolved (server wins); client notified.lww: auto-resolved; most recent writer wins.crdt_yjs: Yjs auto-merges; on rare merge failure → manual conflict UI with side-by-side diff.- AI-assisted merge suggestion (M5): AI proposes merge; author accepts/rejects.
9. Background Sync Behavior
- App foreground → push pending mutations.
- Push completes → pull deltas (all scopes).
- Pull completes → ack cursors.
- Prioritize: revocations > license changes > new content > statements.
- Low-bandwidth mode: pull metadata first; defer large payloads.
- Online steady-state: push/pull every 15 min.
- Connectivity change: immediate sync.
10. Tamper Resistance
- Mutations include HMAC (per device key) for integrity.
- Server verifies HMAC; tamper → reject +
content.bundle.tamper_detected.v1. - Client-side IndexedDB/SQLite encrypted with per-tenant key.
11. Multi-Device
- Each device has independent cursor per scope.
- Deltas scoped per (tenant, user) — all devices for a user see same deltas.
- Device-specific deltas (e.g., bundle for specific device): scope includes deviceId.