# @suaveplan/vault-sync - Domain-specific sync and conflict-resolution engine for the Vaulted password-manager ecosystem: vector-clock causal ordering, CRDT merge strategies (LWW / append / atomic), RFC 6902 JSON Patch incremental sync, durable offline queue with operation collapsing, and end-to-end-encrypted sync payloads via XChaCha20-Poly1305. ## Summary Domain-specific sync and conflict-resolution engine for the Vaulted password-manager ecosystem. Builds on `@suaveplan/crdt` and `@suaveplan/diff` (RFC 6902 JSON Patch) to provide offline-first, end-to-end-encrypted vault synchronisation. Implements vault-item merge strategies (last-write-wins for passwords, append-only for audit history, atomic for folder moves), durable queues with operation collapsing, vector-clock causal ordering, and XChaCha20-Poly1305 sync payloads. ## Documentation tree - [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_ - [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_ - [engine](./src/engine/engine.md) — _(no submodules)_ - [engine](./src/engine/engine.md) — _(no submodules)_ - [codes](./src/errors/codes.md) — `codes.ts` defines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - [vault-sync-error](./src/errors/vault-sync-error.md) — `VaultSyncError` is the single concrete error class thrown from every production path inside `@suaveplan/vault-sync`. I… - [merge](./src/merge/merge.md) — _(no submodules)_ - [merge](./src/merge/merge.md) — _(no submodules)_ - [otel](./src/otel/instruments.md) — _(no submodules)_ - [instruments](./src/otel/instruments.md) — _(no submodules)_ - [patch](./src/patch/patch.md) — _(no submodules)_ - [patch](./src/patch/patch.md) — _(no submodules)_ - [queue](./src/queue/queue.md) — _(no submodules)_ - [queue](./src/queue/queue.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_ - [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_ - [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - [vault-sync-error](./src/errors/vault-sync-error.md) — `VaultSyncError` is the single concrete error class thrown from every production path inside `@suaveplan/vault-sync`. I… - [merge](./src/merge/merge.md) — _(no submodules)_- [merge](./src/merge/merge.md) — _(no submodules)_- [otel](./src/otel/instruments.md) — _(no submodules)_- [instruments](./src/otel/instruments.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - [vault-sync-error](./src/errors/vault-sync-error.md) — `VaultSyncError` is the single concrete error class thrown from every production path inside `@suaveplan/vault-sync`. I… - [merge](./src/merge/merge.md) — _(no submodules)_- [merge](./src/merge/merge.md) — _(no submodules)_- [otel](./src/otel/instruments.md) — _(no submodules)_- [instruments](./src/otel/instruments.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - [vault-sync-error](./src/errors/vault-sync-error.md) — `VaultSyncError` is the single concrete error class thrown from every production path inside `@suaveplan/vault-sync`. I… - [merge](./src/merge/merge.md) — _(no submodules)_- [merge](./src/merge/merge.md) — _(no submodules)_- [otel](./src/otel/instruments.md) — _(no submodules)_- [instruments](./src/otel/instruments.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_ - [engine](./src/engine/engine.md) — _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - [vault-sync-error](./src/errors/vault-sync-error.md) — `VaultSyncError` is the single concrete error class thrown from every production path inside `@suaveplan/vault-sync`. I… - [merge](./src/merge/merge.md) — _(no submodules)_ - [merge](./src/merge/merge.md) — _(no submodules)_- [otel](./src/otel/instruments.md) — _(no submodules)_ - [instruments](./src/otel/instruments.md) — _(no submodules)_- [patch](./src/patch/patch.md) — _(no submodules)_ - [patch](./src/patch/patch.md) — _(no submodules)_- [queue](./src/queue/queue.md) — _(no submodules)_ - [queue](./src/queue/queue.md) — _(no submodules)_- [schemas](./src/schemas/schemas.md) — _(no submodules)_ - [schemas](./src/schemas/schemas.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_ - [vector-clock](./src/vector-clock/vector-clock.md) — _(no submodules)_ ## Install ```bash bun add @suaveplan/vault-sync ``` ## Quick start ```ts import { applyPatch, decryptSyncPayload, diffVaultItems, encryptSyncPayload, mergeVaultItems, SyncEngine, SyncQueue, VaultSyncError, } from "@suaveplan/vault-sync"; const local = { id: "i1", title: "Email", password: "old", folderId: null, history: [], nodeId: "device-a", updatedAt: 1, clock: { "device-a": 1 }, }; const remote = { ...local, password: "new", updatedAt: 2 }; const merged = mergeVaultItems(local, remote, "lww"); const patch = diffVaultItems(local, merged); const restored = applyPatch(local, patch); const queue = new SyncQueue({ nodeId: "device-a" }); queue.enqueue({ kind: "update", itemId: "i1", fields: { password: "new" } }); const drained = queue.flush(); const key = crypto.getRandomValues(new Uint8Array(32)); const envelope = encryptSyncPayload(new TextEncoder().encode("snap"), key); const plaintext = decryptSyncPayload(envelope, key); ``` ## Modules - [merge](./src/merge/merge.md) — `mergeVaultItems` with `lww` / `append` / `atomic` - [patch](./src/patch/patch.md) — RFC 6902 diff and apply for vault items - [engine](./src/engine/engine.md) — `SyncEngine` orchestrator (`pull` / `push` / `sync`) - [queue](./src/queue/queue.md) — `SyncQueue` durable mutation buffer - [crypto-sync](./src/crypto-sync/crypto-sync.md) — XChaCha20-Poly1305 envelope - [vector-clock](./src/vector-clock/vector-clock.md) — causal-ordering primitives - [errors / codes](./src/errors/codes.md) — `VAULT_SYNC_CODES` - [errors / VaultSyncError](./src/errors/vault-sync-error.md) — `VaultSyncError` - [otel](./src/otel/instruments.md) — OTel meter / tracer accessors - [schemas](./src/schemas/schemas.md) — Zod schemas for every public boundary - [types](./src/types/types.md) — types-only contracts ## Error codes | Code | Thrown by | |---|---| | `VAULTSYNC.MERGE.STRATEGY_UNKNOWN` | `mergeVaultItems` / `assertMergeStrategy` | | `VAULTSYNC.MERGE.CONFLICT_UNRESOLVED` | `mergeVaultItems` (atomic) / id mismatch | | `VAULTSYNC.PATCH.INVALID` | `applyPatch` | | `VAULTSYNC.SYNC.PAYLOAD_TAMPERED` | `decryptSyncPayload` | | `VAULTSYNC.SYNC.PAYLOAD_INVALID_VERSION` | `decryptSyncPayload` | | `VAULTSYNC.SYNC.PAYLOAD_TOO_LARGE` | `encryptSyncPayload` | | `VAULTSYNC.SYNC.TRANSPORT_FAILED` | `SyncEngine.pull` / `SyncEngine.push` | | `VAULTSYNC.QUEUE.DEPTH_EXCEEDED` | `SyncQueue.enqueue` | | `VAULTSYNC.QUEUE.SERIALIZATION_FAILED` | `SyncQueue.serialize` / `SyncQueue.deserialize` | | `VAULTSYNC.VECTOR_CLOCK.REGRESSION` | `increment` (saturation guard) | ## Testing & coverage ```bash bunx turbo test --filter=@suaveplan/vault-sync bunx turbo test:coverage --filter=@suaveplan/vault-sync # 100/100/100/100 bunx turbo lint typecheck --filter=@suaveplan/vault-sync ```