Initial Commit
This commit is contained in:
126
packages/security-stack/security/vault-sync/README.md
Normal file
126
packages/security-stack/security/vault-sync/README.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# @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.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [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) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [merge](./src/merge/merge.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [otel](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [instruments](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
<!-- end:auto-docs --> - [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(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) — <!-- begin:auto-docs --> _(no submodules)_- [merge](./src/merge/merge.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(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) — <!-- begin:auto-docs --> _(no submodules)_- [merge](./src/merge/merge.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(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) — <!-- begin:auto-docs --> _(no submodules)_- [merge](./src/merge/merge.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_- [crypto-sync](./src/crypto-sync/crypto-sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_ - [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(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) — <!-- begin:auto-docs --> _(no submodules)_ - [merge](./src/merge/merge.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ - [instruments](./src/otel/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_ - [patch](./src/patch/patch.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_ - [queue](./src/queue/queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ - [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(no submodules)_ - [vector-clock](./src/vector-clock/vector-clock.md) — <!-- begin:auto-docs --> _(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
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user