packages/super-sync-server/docs/architecture.md
SuperSync is an authenticated PostgreSQL-backed relay, ordering service, and upload-conflict gate for the operation-log protocol. It validates operation metadata, detects vector-clock conflicts, assigns a per-user server sequence, persists accepted operations, and notifies peer clients. Clients own application-state semantics, encryption keys and decryption, and resolution of rejected conflicts.
For the client and whole-system context, start with the Sync Architecture Field Guide.
@sp/shared-schema owns
the HTTP wire contracts. @sp/sync-core owns the
vector-clock algorithms shared by client and server.token query parameter;
it sends only lightweight “new operations available” notifications, while
payloads still move over HTTP.Production deployments must expose HTTP and WebSocket traffic only over HTTPS
and WSS. Every reverse-proxy logging setup must omit sensitive query values and
token-bearing Referer headers from access logs and request failure/error logs,
and token-bearing login/recovery pages must emit
Referrer-Policy: no-referrer. The
bundled Caddy configuration replaces the complete logged query
suffix, drops Referer from both Caddy log paths, and sets that response policy;
the application error logger also replaces its complete query suffix. See the
authentication architecture for the token lifecycle and
risk.
JWT verification consults a bounded, 30-second process-local cache of account verification and token-version state. Auth mutations invalidate the cache in the process performing the write, but independent replicas receive no invalidation signal. A multi-instance deployment therefore needs shared auth invalidation (or must explicitly accept the bounded revocation lag); WebAuthn ceremonies additionally need shared challenge storage or sticky routing. The bundled Helm chart remains single-replica.
Request and response fields belong to the shared wire contract; do not duplicate them here.
| Method and path | Stable purpose |
|---|---|
POST /api/sync/ops | Validate and upload regular operations; the response may piggyback newer remote operations |
GET /api/sync/ops | Download retained operations in per-user sequence order with pagination, gap, and full-state metadata |
POST /api/sync/snapshot | Upload a full-state SYNC_IMPORT, BACKUP_IMPORT, or REPAIR operation |
GET /api/sync/status | Return diagnostic sequence, device, snapshot-age, and quota information; not used by the production client |
DELETE /api/sync/data | Erase the user's sync dataset and reset its sequence state |
GET /api/sync/restore-points | List causal full-state replay boundaries |
GET /api/sync/restore/:serverSeq | Reconstruct plaintext state at a retained sequence |
GET /api/sync/ws | Notify other clients that operations are available; never stream operation payloads |
There is no GET /api/sync/snapshot endpoint. The executable route authority
is sync.routes.ts and
websocket.routes.ts.
serverSeq is a total order within one user's current sync dataset. Accepted
uploads commit inside a PostgreSQL RepeatableRead transaction. In the batch
path, one atomic update of user_sync_state.lastSeq reserves a contiguous
sequence range and serializes accepted writers for that user. A concurrent
transaction that read the same earlier snapshot must fail and retry rather than
commit conflicting operations. A causal REPAIR additionally locks that row
and must prove repairBaseServerSeq === lastSeq. Incoming vector clocks are
compared before being pruned for storage.
A clean-slate full-state upload deletes the prior dataset but preserves
lastSeq, preventing sequence reuse visible to existing clients. Only explicit
DELETE /api/sync/data erases the entire dataset and resets the sequence to
zero.
This serialization mechanism is a load-bearing decision; see
ADR #4,
sync.service.ts, and
operation-upload.service.ts.
operations is append-on-write, not retained forever. Rows are immutable
while retained; cleanup, quota recovery, clean-slate replacement, and explicit
data deletion can remove them.user_sync_state owns lastSeq, the optional compressed snapshot cache, and
the latest causal full-state marker. sync_devices is used only for per-device
identity/metadata and last-seen tracking. Its lastAckedSeq field is dormant
legacy schema state: current sync and retention code neither advances nor
reads it.GET /ops can fast-forward to the
latest causal full-state operation; clients do not download the server's
cached snapshot blob.SYNC_IMPORT, BACKUP_IMPORT, and causal REPAIR
operations. Markerless legacy repairs cannot authorize fast-forward, restore,
or history pruning.The persistence authority is
schema.prisma. Retention and replay live in
cleanup.ts,
storage-quota.service.ts,
snapshot.service.ts, and
op-replay.ts.
When SuperSync E2EE is enabled, only operation.payload is encrypted
client-side. The server has no key and stores that payload as an opaque value.
Routing and causality metadata—including operation and client IDs, action and
operation types, entity IDs, vector clock, timestamps, schema version, import
reason, and the encryption flag—remains plaintext and is used by validation,
ordering, and conflict detection.
The payload's AES-GCM tag does not authenticate the plaintext metadata. E2EE therefore provides payload confidentiality and integrity, not metadata confidentiality or end-to-end authenticity of the complete operation. See the encryption architecture.
| Concern | Owner |
|---|---|
| Authentication | api.ts, auth.ts, passkey.ts, auth-cache.ts |
| Wire protocol | supersync-http-contract.ts |
| HTTP and WebSocket routes | sync.routes.ts, websocket.routes.ts |
| Upload transaction and order | sync.service.ts, operation-upload.service.ts |
| Conflict lookup | conflict.ts |
| Download, gap, fast-forward | operation-download.service.ts |
| Snapshot and restore | snapshot.service.ts, op-replay.ts |
| Retention and quota | cleanup.ts, storage-quota.service.ts |
| Persistence | schema.prisma |
The load-bearing PostgreSQL race coverage is in
tests/integration/, especially the repair-causality,
clean-slate atomicity, conflict-detection, and snapshot-vector-clock suites.