/** * Shadow vaults — `vault.frame()` returns a read-only view of the * CURRENT vault state. * * Companion to {@link VaultInstant} from `history/time-machine.ts`: * * | Type | Reads from | Use case | * |------|------------|----------| * | `VaultInstant` | past snapshots (ledger + history) | "books on date X" | * | `VaultFrame` | live vault state | screen-share / demo / audit | * * ```ts * const readonly = vault.frame() * const invoices = await readonly.collection('invoices').list() * await readonly.collection('invoices').put(...) * // → throws ReadOnlyFrameError * ``` * * ## Contract * * Every write method on {@link CollectionFrame} throws * {@link ReadOnlyFrameError}. Reads delegate to the underlying * collection, so validation, locale handling, and caching all work * exactly as they do on the live collection. * * ## Security note: behaviour-enforced, not cryptographically-enforced * * A VaultFrame rejects writes by contract in the JavaScript layer. * It does NOT strip the DEKs from the underlying keyring — the same * in-memory keys that decrypt records could, in principle, encrypt * new writes via a hand-crafted adapter call. Cryptographic * enforcement (keyring variants with the write half of each DEK * removed) is hierarchical-access work. Use a VaultFrame to * prevent *accidental* writes in a read-scoped flow — do not rely on * it as a security boundary against a hostile caller sharing the * same process. * * @module */ import type { Collection } from '../../kernel/collection.js'; import type { Query } from '../../kernel/query/builder.js'; import type { Vault } from '../../kernel/vault.js'; import type { LocaleReadOptions } from '../../kernel/types.js'; /** * A read-only view of a vault's current state. Produced by * `vault.frame()`. Cheap to construct; safe to throw away. */ export declare class VaultFrame { private readonly vault; constructor(vault: Vault); /** * Get a read-only view of one collection. The returned * {@link CollectionFrame} delegates all reads to the underlying * live collection — cache, locale handling, and validation all * work identically to the live collection. */ collection(name: string): CollectionFrame; /** List all collection names visible in the underlying vault. */ collections(): Promise; } /** * Read-only collection view. All write methods throw * {@link ReadOnlyFrameError}; all read methods delegate to the * underlying live {@link Collection}. */ export declare class CollectionFrame { private readonly inner; /** The underlying collection name. Captured at construction so * we don't need to peek into the private Collection state. */ readonly name: string; constructor(inner: Collection, /** The underlying collection name. Captured at construction so * we don't need to peek into the private Collection state. */ name: string); get(id: string, locale?: LocaleReadOptions): Promise; list(locale?: LocaleReadOptions): Promise; /** * Return the chainable query builder. Terminals like `.toArray()`, * `.first()`, `.count()`, `.aggregate()` all work; the builder has * no write surface of its own, so exposing it directly is safe. */ query(): Query; query(predicate: (record: T) => boolean): T[]; /** History reads — allowed (history is read-only by nature). */ history(...args: Parameters['history']>): ReturnType['history']>; getVersion(id: string, version: number): Promise; put(_id: string, _record: T): Promise; delete(_id: string): Promise; update(_id: string, _patch: Partial): Promise; revert(_id: string, _version: number): Promise; putMany(_entries: ReadonlyArray): Promise; deleteMany(_ids: readonly string[]): Promise; }