/** * Record-scoped CEK sealing — grantor side. * * The **grantor** holds the collection DEK and seals ONE record's CEK to an * `at-*` host so that host — and only that host — can decrypt exactly that * record, with no access to the vault DEK and no ability to read any other * record. This is the counterpart to the host-side `openSealedRecord` * (`@noy-db/hub/sealed-record`), which holds no DEK. * * These functions are the orchestration behind `vault.sealRecordToHost` / * `vault.revokeSealedRecord` / `vault.rotateRecordCek`, lifted off `Vault` * behind a narrow {@link SealingContext} so the kernel file delegates. They * live in `record-keys/` (the vault-side CEK policy layer), NOT in * `sealed-record/`, so the host-side subpath stays DEK-free — the wire * *types* they share are spine-owned (`kernel/types.ts`), not imported from * `sealed-record/` directly. */ import { type EnclaveKey } from '../crypto.js'; import { type NoydbStore, type RecipientSealer } from '../../types.js'; /** The `_sealed_cek` delivery namespace (one envelope per `collection/id/pid`). */ export declare const SEALED_CEK_NS = "_sealed_cek"; /** What the grantor functions need from their `Vault`. */ export interface SealingContext { readonly adapter: NoydbStore; /** Vault id (the adapter's first coordinate). */ readonly vault: string; /** Resolve the DEK a record's CEK is wrapped under. */ getDEK(collection: string): Promise; /** Actor id stamped on `_by` (empty string → omit). */ readonly actor: string; /** Evict the per-record CEK cache + decrypted-record cache after a rotation. */ invalidateRecordCaches(collection: string, id: string): Promise; } /** * Seal a record's CEK to a host. See `vault.sealRecordToHost` for the contract. * Returns `{ pid, envelopeKey }`. */ export declare function sealRecordToHost(ctx: SealingContext, collection: string, id: string, hostSealer: RecipientSealer, opts: { expiresAt: string; }): Promise<{ pid: string; envelopeKey: string; }>; /** * Revoke one sealed-CEK grant. * * **Default (`{ hard: false }`) is SOFT** — it only deletes the delivery * envelope from the store. A host that already fetched (or cached the unsealed * CEK from) that envelope KEEPS decrypt capability for the record; soft revoke * is a "stop new fetches" control, not a cryptographic cutoff. * * **`{ hard: true }`** additionally rotates the record's CEK (via * {@link rotateRecordCek}): the live body is re-encrypted under a fresh CEK and * EVERY sealed-CEK delivery envelope for the record (all pids) is deleted, so * any previously-sealed CEK fails the AES-GCM auth tag on the rotated body — * future opens are cryptographically denied. (PRE-rotation history versions, * which keep their old `_cek`, remain openable — same semantics as * `rotateRecordCek`.) */ export declare function revokeSealedRecord(ctx: SealingContext, collection: string, id: string, pid: string, opts?: { hard?: boolean; }): Promise; /** * HARD-rotate a record's CEK: re-encrypt the live body under a fresh CEK, evict * caches, and delete EVERY sealed-CEK delivery envelope for the record. See * `vault.rotateRecordCek` for why this bypasses `Collection.put` (no guards, no * history bump — a key rotation must not re-encrypt prior history under the new * CEK). */ export declare function rotateRecordCek(ctx: SealingContext, collection: string, id: string): Promise;