Files
2026-05-27 23:47:53 +01:00

157 lines
22 KiB
Markdown

# @suaveplan/vault - Vault orchestration layer for the Vaulted password-manager ecosystem: drive-backed encrypted SQLite container, lifecycle state machine (open → unlock → lock), per-item field encryption, attachments / shares / sync delegation, and OpaqueKeyHandle boundary enforcement.
## Summary
Vault orchestration layer for the Vaulted password-manager ecosystem. Provides a drive-backed encrypted SQLite-style container, a strict `locked` ↔ `unlocked` lifecycle state machine, per-item field encryption for concealed values, attachment / share / sync delegation behind injectable adapter interfaces, and `OpaqueKeyHandle` boundary enforcement so raw key bytes never leave `@suaveplan/crypto-vault`.
<!-- begin:auto-docs -->
## Documentation tree
- [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [field-encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [codes](./src/errors/codes.md) — `codes.ts` defines the stable error-code registry for `@suaveplan/vault`. Every failure raised by the orchestration lay…
- [vault-error](./src/errors/vault-error.md) — `vault-error.ts` defines `VaultError`, the concrete `SuaveplanError` subclass thrown by every public path in `@suavepla…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->- migrations — <!-- begin:auto-docs --> _(no submodule…
- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [helpers](./src/items/helpers.md) — `items-helpers.ts` extracts the pure transformation helpers used by the items repository: row-to-item projection (with…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->- migrations — <!-- begin:auto-docs --> _(no submodule…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [manifest](./src/manifest/manifest.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 -->
- [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 -->
- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [adapters](./src/types/adapters.md) — `adapters.ts` defines the Phase-1 adapter contracts the vault orchestration layer uses to talk to blob storage, share-l…
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - wiring — `wiring.ts` extracts the per-unlock module…
- [lifecycle](./src/vault/lifecycle.md) — `lifecycle.ts` extracts the two side-effecting helpers that drive the unlock path: `deriveVaultKeyBuffer` (running 2SKD…
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - wiring — `wiring.ts` extracts the per-unlock module…
- [wiring](./src/vault/wiring.md) — `wiring.ts` extracts the per-unlock module factories used by `Vault`: `buildItems`, `buildSearch`, `buildAttachments`,…
<!-- end:auto-docs --> - [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [field-encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the stable error-code registry for `@suaveplan/vault`. Every failure raised by the orchestration lay…
- [vault-error](./src/errors/vault-error.md) — `vault-error.ts` defines `VaultError`, the concrete `SuaveplanError` subclass thrown by every public path in `@suavepla…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/items/helpers.md) — `items-helpers.ts` extracts the pure transformation helpers used by the items repository: row-to-item projection (with…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [manifest](./src/manifest/manifest.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)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [adapters](./src/types/adapters.md) — `adapters.ts` defines the Phase-1 adapter contracts the vault orchestration layer uses to talk to blob storage, share-l…
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [lifecycle](./src/vault/lifecycle.md) — `lifecycle.ts` extracts the two side-effecting helpers that drive the unlock path: `deriveVaultKeyBuffer` (running 2SKD…
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [wiring](./src/vault/wiring.md) — `wiring.ts` extracts the per-unlock module factories used by `Vault`: `buildItems`, `buildSearch`, `buildAttachments`,…
- [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [field-encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the stable error-code registry for `@suaveplan/vault`. Every failure raised by the orchestration lay…
- [vault-error](./src/errors/vault-error.md) — `vault-error.ts` defines `VaultError`, the concrete `SuaveplanError` subclass thrown by every public path in `@suavepla…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- migrations — <!-- begin:auto…
- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/items/helpers.md) — `items-helpers.ts` extracts the pure transformation helpers used by the items repository: row-to-item projection (with…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- migrations — <!-- begin:auto…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [manifest](./src/manifest/manifest.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)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [adapters](./src/types/adapters.md) — `adapters.ts` defines the Phase-1 adapter contracts the vault orchestration layer uses to talk to blob storage, share-l…
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [lifecycle](./src/vault/lifecycle.md) — `lifecycle.ts` extracts the two side-effecting helpers that drive the unlock path: `deriveVaultKeyBuffer` (running 2SKD…
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [wiring](./src/vault/wiring.md) — `wiring.ts` extracts the per-unlock module factories used by `Vault`: `buildItems`, `buildSearch`, `buildAttachments`,…
- [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [field-encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the stable error-code registry for `@suaveplan/vault`. Every failure raised by the orchestration lay…
- [vault-error](./src/errors/vault-error.md) — `vault-error.ts` defines `VaultError`, the concrete `SuaveplanError` subclass thrown by every public path in `@suavepla…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- migrations — <!-- begin:auto-docs --> _(no submodul…
- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_- [helpers](./src/items/helpers.md) — `items-helpers.ts` extracts the pure transformation helpers used by the items repository: row-to-item projection (with…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- migrations — <!-- begin:auto-docs --> _(no submodul…
- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_- [manifest](./src/manifest/manifest.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)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [adapters](./src/types/adapters.md) — `adapters.ts` defines the Phase-1 adapter contracts the vault orchestration layer uses to talk to blob storage, share-l…
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [lifecycle](./src/vault/lifecycle.md) — `lifecycle.ts` extracts the two side-effecting helpers that drive the unlock path: `deriveVaultKeyBuffer` (running 2SKD…
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_- wiring — `wiring.ts` extracts the per-unlock module…
- [wiring](./src/vault/wiring.md) — `wiring.ts` extracts the per-unlock module factories used by `Vault`: `buildItems`, `buildSearch`, `buildAttachments`,…
- [attachments](./src/attachments/attachments.md) — <!-- begin:auto-docs --> _(no submodules)_- [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_ - [container](./src/container/container.md) — <!-- begin:auto-docs --> _(no submodules)_- [encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_ - [field-encryption](./src/encryption/field-encryption.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — `codes.ts` defines the stable error-code registry for `@suaveplan/vault`. Every failure raised by the orchestration lay…
- [vault-error](./src/errors/vault-error.md) — `vault-error.ts` defines `VaultError`, the concrete `SuaveplanError` subclass thrown by every public path in `@suavepla…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_ - [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_ - [migrations](./src/items/migrations/migrations.md) — <!-- begin:auto-docs --> _(no submodules)_ - [helpers](./src/items/helpers.md) — `items-helpers.ts` extracts the pure transformation helpers used by the items repository: row-to-item projection (with…
- [items](./src/items/items.md) — <!-- begin:auto-docs --> _(no submodules)_- [manifest](./src/manifest/manifest.md) — <!-- begin:auto-docs --> _(no submodules)_ - [manifest](./src/manifest/manifest.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)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ - [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_ - [search](./src/search/search.md) — <!-- begin:auto-docs --> _(no submodules)_- [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_ - [shares](./src/shares/shares.md) — <!-- begin:auto-docs --> _(no submodules)_- [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_ - [sync](./src/sync/sync.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [adapters](./src/types/adapters.md) — `adapters.ts` defines the Phase-1 adapter contracts the vault orchestration layer uses to talk to blob storage, share-l…
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_ - [lifecycle](./src/vault/lifecycle.md) — `lifecycle.ts` extracts the two side-effecting helpers that drive the unlock path: `deriveVaultKeyBuffer` (running 2SKD…
- [vault](./src/vault/vault.md) — <!-- begin:auto-docs --> _(no submodules)_ - [wiring](./src/vault/wiring.md) — `wiring.ts` extracts the per-unlock module factories used by `Vault`: `buildItems`, `buildSearch`, `buildAttachments`,…
## Install
```bash
bun add @suaveplan/vault
```
## Quick start
```ts
import { Vault } from "@suaveplan/vault";
const vault = Vault.open({
vaultId: "personal",
email: "user@example.com",
containerPath: "/personal.vault",
attachmentsPrefix: "/personal/attachments",
argon2id: { memoryKB: 65536, iterations: 3, parallelism: 4, outputLength: 32 },
argon2idSalt: argon2idSaltBytes,
drive,
driveSharing,
sync,
});
await vault.unlock(password, secretKey);
const item = vault.items.create({
title: "GitHub",
category: "login",
fields: { username: "alice", url: "https://github.com" },
concealedFields: { password: "p@ssw0rd" },
tags: ["work"],
favorite: true,
});
const fetched = vault.items.get(item.id);
const matches = vault.search.search({ query: "github", category: "login" });
await vault.lock(); // zeroizes all key material
```
## Modules
- [`vault/vault`](./src/vault/vault.md) — orchestration entry point, lifecycle state machine.
- [`vault/lifecycle`](./src/vault/lifecycle.md) — 2SKD + key-hierarchy + drive load/create helpers.
- [`vault/wiring`](./src/vault/wiring.md) — module factory helpers.
- [`manifest/manifest`](./src/manifest/manifest.md) — bitpacker-packed container manifest header.
- [`container/container`](./src/container/container.md) — drive-backed encrypted blob layer.
- [`items/items`](./src/items/items.md) — in-memory items repository.
- [`items/helpers`](./src/items/helpers.md) — pure row projection / patch helpers.
- [`items/migrations/migrations`](./src/items/migrations/migrations.md) — forward-only schema migrations.
- [`encryption/field-encryption`](./src/encryption/field-encryption.md) — per-item field encryption.
- [`search/search`](./src/search/search.md) — concealed-field-safe search.
- [`attachments/attachments`](./src/attachments/attachments.md) — drive-backed attachment storage.
- [`shares/shares`](./src/shares/shares.md) — share-link orchestration.
- [`sync/sync`](./src/sync/sync.md) — sync delegation orchestrator.
- [`errors/codes`](./src/errors/codes.md) — stable `VAULT.*` error code registry.
- [`errors/vault-error`](./src/errors/vault-error.md) — `VaultError` class.
- [`otel/instruments`](./src/otel/instruments.md) — OTel histogram + counter instruments.
- [`schemas/schemas`](./src/schemas/schemas.md) — Zod schemas for every public boundary.
- [`types/types`](./src/types/types.md) — orchestration-level types.
- [`types/adapters`](./src/types/adapters.md) — Phase-1 adapter interfaces (DriveLike / DriveSharingLike / VaultSyncLike).
## Security model
- **2SKD**: `Argon2id(HMAC-SHA256(secretKey, password ‖ 0x00 ‖ email), salt, params)` produces the AUK, which is HKDF-derived through `personal-keyset → vault-key → item-key`. Intermediate buffers are zeroized eagerly.
- **OpaqueKeyHandle boundary**: the vault key is wrapped in a `SecureBuffer` and accessed only through `@suaveplan/crypto-vault`'s `unwrap` — never as raw bytes across module boundaries.
- **Defence in depth**: even if the drive-level AEAD is compromised, concealed fields (passwords, PINs, secure notes) remain encrypted with per-item keys inside the SQLite-style container.
- **Manifest binding**: the bitpacker-packed manifest header is bound as AAD to the container's AEAD, so any tampering invalidates the authentication tag.
- **`zeroizeAll()` on lock**: every live `SecureBuffer` is overwritten with zeros and the references released.
## Performance
- Unlock is dominated by Argon2id (≥ 64 MiB / 3 iterations / parallelism configurable). Default parameters ship at OWASP minimums.
- Items, search, attachments, and share operations are all in-memory after unlock; flushes are debounced (default 500 ms; configurable via `flushDebounceMs`).
- Drive I/O happens twice per unlock at most: once on read, once for the freshly-encrypted blob if creating a new vault. Ongoing operations only touch drive on flush + lock.
## Phased delivery
This is the Phase-1 landing. Adapter interfaces (`DriveLike`, `DriveSharingLike`, `VaultSyncLike`) are defined inline; production wiring binds the real `@suaveplan/drive`, `@suaveplan/drive-sharing`, and `@suaveplan/vault-sync` packages without changes to this surface.