stable

Vault

The Vault object reference: open collections, encrypted tamper-evident backup/restore, metadata and locale, session identity, and export authorization.

A Vault is the handle db.openVault(name) returns — one isolated, encrypted namespace, conventionally bound to vault. It has its own keyring, so the DEKs that decrypt its collections are unwrapped from this vault's key material and say nothing about any other vault. It sits in the middle of the Noydb → Vault → Collection<T> hierarchy: the session opens it and owns the crypto, the vault opens collections and holds vault-scoped metadata, and the collections hold the records.

Every method on this page is on that instance and works when you pass zero strategies to createNoydb() — the strategy-free kernel surface. The session-level primitives that produced this handle (opening, locking, policy) live on Noydb; anything a vault gains from an opt-in strategy is gathered at the end under Unlocked by services.

The reference is organized into groups — opening collections, encrypted backup and restore, metadata and locale, session identity, and export authorization — each opening with a short note on what unites its methods, then the individual methods. The owner-curated public envelope is a passive read documented on its own service page, linked below.

Opening collections

These methods turn a collection name into a live, typed Collection<T> handle and let you discover the collections a vault holds. Reach for collection() first — it is the doorway to every read and write.

collection()

collection<T>(
  collectionName: string,
  options?: {
    schema?: StandardSchemaV1<unknown, T>
    indexes?: readonly IndexDef[]
    prefetch?: boolean
    cache?: CacheOptions
    sensitive?: SensitiveOpt<T>
    perRecordKeys?: boolean
    deterministicFields?: readonly string[]
    acknowledgeDeterministicRisk?: boolean
    provenance?: boolean
    meta?: CollectionMeta
    fieldMeta?: Record<string, FieldMeta>
    // service options (refs, i18nFields, computed, classifiedFields, tiers,
    // blobFields, …) documented on their service pages
  }
): Collection<T>

Open (or reconstruct) a typed collection within this vault and cache the handle; the generic T threads through get / put / query / scan so records come back typed. Throws ReservedCollectionNameError for names starting with _dict_ or equal to _sequences (use vault.dictionary(name) / vault.sequence(name) for those). Lazy mode combined with indexes is rejected at construction time.

  • collectionName — the collection to open; created on first write.
  • options — collection configuration. The kernel members below work strategy-free:
    • options.schema — a Standard Schema v1 validator (Zod, Valibot, ArkType, …). Every put() is validated before encryption; every read is validated after decryption; failing records throw SchemaValidationError. See Schema.
    • options.indexes — secondary indexes for the query DSL, computed in memory after decryption (the adapter never sees index data).
    • options.prefetch — hydration mode. Default true (eager: load everything on first access); false is lazy mode — records load on demand, bounded by the LRU cache.
    • options.cache — LRU bounds ({ maxRecords, maxBytes: '50MB' | 1024 }). Required in lazy mode.
    • options.sensitive — structural group-encryption: the named fields are sealed into their own _sealed[field] envelope slot under a per-field key, kept out of the open _data blob. Default-off; byte-identical output when absent.
    • options.perRecordKeys — when true, each record body is encrypted under a fresh per-record CEK wrapped under the collection DEK (_cek), stable across versions — the foundation for per-record erasure and record-scoped sealing. Off by default.
    • options.deterministicFields — declare deterministic-encryption fields for blind equality search (see findByDet()). Requires acknowledgeDeterministicRisk: true.
    • options.acknowledgeDeterministicRisk — explicit acknowledgement that deterministic encryption leaks equality; required whenever deterministicFields is set.
    • options.provenance — when true, put() calls that supply a source option stamp _source / _sourceTs onto the unencrypted envelope metadata. Off by default (zero cost otherwise).
    • options.meta — the collection's descriptive metadata (label / description / icon); surfaced by collection.describe().
    • options.fieldMeta — per-field consumer-neutral descriptors (label / unit / semanticType / sensitivity …); surfaced by collection.describe().
    • Service options — refs, i18nFields, dictKeyFields, lookupFields, moneyFields, computed, classifiedFields, embeddings / textIndexes, crdt, tiers / tierMode, blobFields, archive, persistJsonSchema / schemaUpdate, attestation, historyConfig take effect only when the matching strategy is wired into createNoydb; each is documented on its service page.

collections()

collections(): Promise<string[]>

List every collection name held in this vault.

Backup and restore

These methods produce and consume a verifiable, encrypted JSON backup of the whole vault — ciphertext end to end, tamper-evident via the embedded ledger head. Reach for them to snapshot a vault or move it between noy-db instances without ever exposing plaintext.

dump()

dump(): Promise<string>

Dump the vault as a verifiable, encrypted JSON backup string. The backup embeds the current ledger head and the full _ledger internal collections, so the receiver can run verifyBackupIntegrity() after load() and detect tampering between dump and restore. Backups produced without a ledger (older formats, or hubs built without the history strategy) skip that integrity check with a warning — both modes round-trip cleanly.

Note: dump() is the encrypted-backup path; record bodies stay under the vault's DEKs. For a plaintext export, use the as-* exporters — gated by export authorization.

load()

load(backupJson: string): Promise<void>

Restore a vault from a string produced by dump(). After loading, it runs verifyBackupIntegrity() and, on failure, throws BackupLedgerError (chain or head mismatch) or BackupCorruptedError (a data envelope no longer matches its ledger entry). The adapter state is already written by the time it throws, so the caller decides whether to accept the suspect state or wipe and retry. Legacy backups with no ledger load with a console warning and skip the check.

  • backupJson — the JSON string returned by dump().

verifyBackupIntegrity()

verifyBackupIntegrity(): Promise<VerifyBackupResult>

Run an end-to-end integrity check: walk the ledger hash chain, then cross-check every current data envelope's payloadHash against its ledger entry. Returns a discriminated union — { ok: true, head, length } on success, or { ok: false, kind: 'chain' | 'data', … } identifying whether the chain itself broke or a specific envelope diverged. Exposed for scheduled tamper detection on an in-place vault, not just during load().

Metadata and locale

These read the vault's descriptive metadata and manage its default locale — the fallback used for i18n / dictKey field resolution when a per-call { locale } is omitted.

getMeta()

getMeta(): VaultMeta | undefined

Return the vault-level descriptive metadata (label / description), set once at construction via openVault(name, { meta }) and first-wins thereafter. undefined when none was supplied.

setLocale()

setLocale(locale: string | undefined): void

Set or update the vault-default locale at runtime — useful when the user switches their preferred language after opening the vault.

  • locale — the new default locale; pass undefined to clear it.

getLocale()

getLocale(): string | undefined

Return the current vault-default locale, or undefined if none is set.

Session identity

These read-only getters identify the principal backing this vault session. Reach for them to drive UI affordance gates, stamp audit trails, or confirm a caller's role before attempting a privileged action.

userId

get userId(): string

The user id of the keyring backing this vault session — for UI affordances ("you are alice"), audit trails, and stamping records with the current actor.

role

get role(): Role

The role of the keyring backing this session — one of owner | admin | operator | viewer | client. Use it to gate UI affordances and approval workflows before attempting an action.

Export authorization

These pre-flight the current keyring's authorization to export or import data. Every @noy-db/as-* package calls the assert* variant before it runs; the non-throwing can* variants are for UI affordances (grey out a button) without catching an exception. The plaintext export primitives themselves — exportStream() / exportJSON() and the as-* exporters — run only after these checks pass.

assertCanExport()

assertCanExport(tier: 'plaintext', format: ExportFormat): void
assertCanExport(tier: 'bundle'): void

Authorize an export against the current keyring's exportCapability; throws ExportCapabilityError when the keyring is not authorized. The plaintext tier defaults closed for every role (the owner must positively grant it per format); the bundle tier defaults on for owner / admin, off for others.

  • tier — 'plaintext' (a decrypted per-format export) or 'bundle' (the encrypted .noydb container).
  • format — for the plaintext tier, the specific ExportFormat being authorized (e.g. 'xlsx', 'csv').

canExport()

canExport(tier: 'plaintext', format: ExportFormat): boolean
canExport(tier: 'bundle'): boolean

Non-throwing read of the invoking keyring's export capability, with role-based defaults resolved — the UI-affordance companion to assertCanExport().

  • tier — 'plaintext' or 'bundle', as above.
  • format — for the plaintext tier, the ExportFormat to check.

assertCanImport()

assertCanImport(tier: 'plaintext', format: ExportFormat): void
assertCanImport(tier: 'bundle'): void

Authorize an import against the keyring's importCapability; throws ImportCapabilityError otherwise. Reader entry points (fromString / fromBytes) must call this before parsing. Default-closed for every role — including the owner for bundle import, because import is more dangerous than export (it corrupts rather than merely leaks).

  • tier — 'plaintext' (a per-format import) or 'bundle' (a .noydb bundle import).
  • format — for the plaintext tier, the specific ExportFormat being authorized.

canImport()

canImport(tier: 'plaintext', format: ExportFormat): boolean
canImport(tier: 'bundle'): boolean

Non-throwing read of the keyring's import capability — returns false in every default-closed case.

  • tier — 'plaintext' or 'bundle', as above.
  • format — for the plaintext tier, the ExportFormat to check.

Public envelope

getCover — the owner-curated, deliberately-plaintext vault descriptor, readable before unlock so a bundle writer can label a vault — is documented on the cover service page, alongside the cover config opt-in.

Unlocked by services

Further methods appear on a Vault once you opt into the matching service — a tree-shakeable with*() capability wired into createNoydb. Each stays gated (throwing a *NotEnabledError or the strategy's equivalent) until its strategy is present. Browse the Services catalog; grouped by capability: