@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 — (no submodules)
- crypto-sync — (no submodules)
- engine — (no submodules)
- engine — (no submodules)
- codes —
codes.tsdefines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - vault-sync-error —
VaultSyncErroris the single concrete error class thrown from every production path inside@suaveplan/vault-sync. I… - merge — (no submodules)
- merge — (no submodules)
- otel — (no submodules)
- instruments — (no submodules)
- patch — (no submodules)
- patch — (no submodules)
- queue — (no submodules)
- queue — (no submodules)
- schemas — (no submodules)
- schemas — (no submodules)
- types — (no submodules)
- types — (no submodules)
- vector-clock — (no submodules)
- vector-clock — (no submodules)
- vault-sync-error —
VaultSyncErroris the single concrete error class thrown from every production path inside@suaveplan/vault-sync. I… - merge — (no submodules)- merge — (no submodules)- otel — (no submodules)- instruments — (no submodules)- patch — (no submodules)- patch — (no submodules)- queue — (no submodules)- queue — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- types — (no submodules)- types — (no submodules)- vector-clock — (no submodules)- vector-clock — (no submodules)- crypto-sync — (no submodules)- engine — (no submodules)- engine — (no submodules)- codes —
codes.tsdefines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - vault-sync-error —
VaultSyncErroris the single concrete error class thrown from every production path inside@suaveplan/vault-sync. I… - merge — (no submodules)- merge — (no submodules)- otel — (no submodules)- instruments — (no submodules)- patch — (no submodules)- patch — (no submodules)- queue — (no submodules)- queue — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- types — (no submodules)- types — (no submodules)- vector-clock — (no submodules)- vector-clock — (no submodules)- crypto-sync — (no submodules)- engine — (no submodules)- engine — (no submodules)- codes —
codes.tsdefines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - vault-sync-error —
VaultSyncErroris the single concrete error class thrown from every production path inside@suaveplan/vault-sync. I… - merge — (no submodules)- merge — (no submodules)- otel — (no submodules)- instruments — (no submodules)- patch — (no submodules)- patch — (no submodules)- queue — (no submodules)- queue — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- types — (no submodules)- types — (no submodules)- vector-clock — (no submodules)- vector-clock — (no submodules)- crypto-sync — (no submodules)- engine — (no submodules) - engine — (no submodules)- codes —
codes.tsdefines the canonical, frozen registry of every fully-qualified error code emitted by `@suaveplan/vault-sync… - vault-sync-error —
VaultSyncErroris the single concrete error class thrown from every production path inside@suaveplan/vault-sync. I… - merge — (no submodules) - merge — (no submodules)- otel — (no submodules) - instruments — (no submodules)- patch — (no submodules) - patch — (no submodules)- queue — (no submodules) - queue — (no submodules)- schemas — (no submodules) - schemas — (no submodules)- types — (no submodules) - types — (no submodules)- vector-clock — (no submodules) - vector-clock — (no submodules)
Install
bun add @suaveplan/vault-sync
Quick start
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 —
mergeVaultItemswithlww/append/atomic - patch — RFC 6902 diff and apply for vault items
- engine —
SyncEngineorchestrator (pull/push/sync) - queue —
SyncQueuedurable mutation buffer - crypto-sync — XChaCha20-Poly1305 envelope
- vector-clock — causal-ordering primitives
- errors / codes —
VAULT_SYNC_CODES - errors / VaultSyncError —
VaultSyncError - otel — OTel meter / tracer accessors
- schemas — Zod schemas for every public boundary
- types — 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
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