/** * Sealed blob bytes v1 (#654 design §8.1, E1c). * * A protocol field blob (`instruction.blobRef`, a progress spill, an artifact) * is sealed before its outer content, by the same frame, key and AEAD rule. * Its AAD is the 16 outer AAD members that do not depend on the outer * plaintext, the blob's own `paddedLength`, and `fieldPath`: the RFC 6901 * JSON Pointer from the moved-fields object to its BlobRef. The blob's salt, * nonce and padded length travel next to the BlobRef inside the outer * plaintext, so the outer AEAD and content MAC cover them. * * Internal: the subpath index does not import this module, so it adds no * bytes to the published closure. */ import { z } from 'zod'; import { type SealedBinding, type SealedCategory, type SealedContentHeaderV1, type SealedContentOpenFailure, type SealedContentRandomness } from './sealed-content'; /** What the outer plaintext carries next to a sealed blob's BlobRef. */ export declare const SealedBlobParamsV1Schema: z.ZodObject<{ salt: z.ZodString; nonce: z.ZodString; paddedLength: z.ZodNumber; }, z.core.$strict>; export type SealedBlobParamsV1 = z.infer; /** * The canonical AAD bytes of a blob sealed under an outer header (§8.1). */ export declare function sealedBlobAad(header: SealedContentHeaderV1, binding: SealedBinding, paddedLength: number, fieldPath: string): Uint8Array; /** * The input of one blob seal. Scope, chain head, sender, category and binding * must be the ones of the outer content that will carry the BlobRef. */ export interface SealBlobInput { readonly scopeKey: Uint8Array; readonly scope: { readonly id: string; readonly epoch: number; }; readonly chainHead: { readonly seq: number; readonly hash: string; }; readonly sender: string; readonly category: SealedCategory; readonly binding: SealedBinding; /** The pointer to the BlobRef node in the moved-fields object. */ readonly fieldPath: string; /** The raw blob bytes. */ readonly bytes: Uint8Array; /** The plaintext limit of this field, in bytes. */ readonly maxContentLength: number; } export interface SealedBlob { readonly params: SealedBlobParamsV1; /** AES-256-GCM output: the padded frame followed by the 16-byte tag. Upload these bytes. */ readonly ciphertext: Uint8Array; } /** * Seal one blob once, before the outer content. A retry must reuse the * uploaded blob, never seal again (§8.6). */ export declare function sealBlob(input: SealBlobInput): Promise; /** * {@link sealBlob} with a caller-chosen salt and nonce, for test vectors only. */ export declare function sealBlobWithRandomness(input: SealBlobInput, randomness: SealedContentRandomness): Promise; export interface OpenSealedBlobInput { /** The outer header that `openSealedContent` authenticated. */ readonly header: SealedContentHeaderV1; /** The binding the outer content opened under. */ readonly binding: SealedBinding; readonly scopeKey: Uint8Array; /** The receiver derives it from where it found the BlobRef, never from a table. */ readonly fieldPath: string; /** From the opened outer plaintext. Its shape is still checked here. */ readonly params: unknown; /** The downloaded blob bytes. The caller checks the BlobRef `contentHash` against them (§9.3). */ readonly ciphertext: Uint8Array; readonly maxContentLength: number; } export type SealedBlobOpenResult = { readonly ok: true; readonly bytes: Uint8Array; } | { readonly ok: false; readonly reason: SealedContentOpenFailure; }; /** * Open one blob, fail closed. In order: binding and category * (`sealing_policy_mismatch`); header, field path and params shape * (`sealed_open_failed`); key id (`sealed_key_unavailable`); ciphertext * length, AEAD under the rebuilt blob AAD and the five frame checks (all * `sealed_open_failed`). Nothing here throws for hostile input. */ export declare function openSealedBlob(input: OpenSealedBlobInput): Promise;