import { type NatsConnection } from "@nats-io/transport-node"; /** The §13.7 artifact bound: a document above it cannot ride one message and is refused. */ export declare const CONTRACT_ARTIFACT_MAX_BYTES: number; /** The §13.7 closure byte bound: the sum of every fetched artifact's canonical bytes. */ export declare const CONTRACT_CLOSURE_MAX_BYTES: number; /** The §13.7 reference-chain bound: the walk's depth from the root. */ export declare const CONTRACT_CLOSURE_MAX_REF_DEPTH = 32; /** The artifact-count ceiling: a walk that would exceed it fails loud, never truncates. */ export declare const CONTRACT_CLOSURE_MAX_ARTIFACTS = 64; /** A trusted, space-bonded contract-store context: an OPAQUE token carrying only the space. Its * JS + JSM resources DERIVE from one binding-layer connection by the constructor and live in a * module-private WeakMap keyed by this token, NEVER as reachable properties (distsys 8dcad72 * MEDIUM): a caller holding the context cannot rebind its broker to validate a lost-CAS "winner" * through a different broker than it published to. Every store seam takes this context. */ export interface ContractStoreContext { readonly space: string; } /** A per-operation artifact read memo: `digest hex -> the in-flight or settled read`. Scoped to ONE * logical operation against ONE store context (e.g. a single {@link resolveService}); it is not a * process cache and holds no bound state. Passed to {@link fetchContractClosure} so the closure * walks of one operation neither re-read nor concurrently duplicate the same artifact. */ export type ArtifactMemo = Map>; /** Bond the resources to one space by CONSTRUCTION (frozen token + WeakMap-private resources, the * shared context discipline): a hand-assembled structural look-alike is rejected at every seam, * and the broker cannot be rebound out from under a live operation. */ export declare function contractStoreContext(nc: NatsConnection, space: string): Promise; /** The artifact's subject token: SHA-256 hex over the artifact's CANONICAL bytes (§13.7: the * `sha256:` prefix is not a subject token). The bytes handed here MUST already be canonical — * publication and verify-on-read enforce that ({@link assertCanonicalArtifactBytes}). */ export declare function contractArtifactDigestHex(bytes: Uint8Array): string; /** Normalize a digest reference (`` or `sha256:`) to the bare subject token; a * malformed reference fails loud (a garbled ref never fetches an unintended subject). */ export declare function contractRefToHex(ref: string): string; /** A value's canonical artifact bytes (strict RFC 8785 over I-JSON): what publication stores * and what the digest identifies. Non-interchangeable values refuse. */ export declare function contractArtifactCanonicalBytes(value: unknown): Uint8Array; /** Prove presented bytes ARE their own parse's strict RFC 8785 canonical serialization and * return the parsed value (§13.7 content identity): invalid UTF-8, non-JSON, and every * noncanonical encoding (reordered keys, whitespace, duplicate keys, noncanonical numbers) * refuse — an equivalent value in a different encoding never gets its own identity, so two * implementations can never disagree on an artifact's digest. */ export declare function assertCanonicalArtifactBytes(bytes: Uint8Array, what: string): unknown; /** Publish one artifact at its content address, create-only. The bytes are DETACHED at entry * (a caller mutating the buffer across the publish await changes nothing), PROVEN canonical * ({@link assertCanonicalArtifactBytes}), and the digest is computed FROM that snapshot; a * lost CAS fetches the recorded artifact and — because the subject IS the digest and the * fetch verifies — the loss is an idempotent no-op ({won: false}). Oversize refuses. */ export declare function publishContractArtifact(ctx: ContractStoreContext, bytes: Uint8Array): Promise<{ digestHex: string; won: boolean; }>; /** Fetch one artifact by digest (`undefined` = not published). VERIFY-ON-READ is unconditional * and TWO-PROOF: the fetched bytes must recompute the digest AND be strict canonical JSON — * content addressing is the tamper boundary (§13.7). * * APPEND-SHADOW DEFENSE (critic, live-confirmed): the `epc.*` publish grant is a raw JS publish; * the create-only fence is a publisher-SET header (`Nats-Expected-Last-Subject-Sequence: 0`) the * grant cannot compel, so a non-cooperative grant-holder can APPEND garbage at an * already-published digest subject. `last_by_subj` would then return that shadow and a fail-closed * read would make the honest artifact permanently unfetchable (a total, operator-recovery-only * DoS once ep is the sole contract path). The subject IS the content digest and honest * publication is create-only, so the FIRST message at the subject is the unique verifying * artifact and every shadow is a strictly later append. The read therefore verifies `last_by_subj` * (the O(1) fast path, correct whenever nobody shadowed) and, on a verify-miss, FALLS BACK to the * create-only winner (`next_by_subj` from the stream start) and verifies THAT — so a shadow-append * is defeated by the reader, never relying on publisher cooperation. Only when NEITHER the last nor * the first message verifies is the store genuinely corrupt (fail loud). Pre-emptive garbage * BEFORE the honest publish is the already-loud case: the honest create-only publish then loses at * registration, so there is no honest artifact to recover. * * GRANT NOTE (critic completeness item): the fallback issues `next_by_subj`, which rides the bare * `$JS.API.DIRECT.GET.` form — the executor publisher holds it, the ordinary agent baseline * does NOT (it holds only the subject-scoped `last_by_subj`, per the D32 read-grant bound). Sound * because {@link ensureContractStore} fails loud unless the store is config-B immutable, so the * manager never serves a store where an agent's `last_by_subj` could return a shadow — the fallback * never triggers on the agent path. Widening the agent grant to the bare form is unnecessary (and * would relax the D32 bound for no gain). */ export declare function fetchContractArtifact(ctx: ContractStoreContext, digestHex: string): Promise; /** The §13.7 closure MANIFEST artifact: contract identity is THIS artifact's digest (the * closure digest), never the root document digest alone. Digest fields carry the one scalar * shape `sha256:`. */ export interface ContractClosureManifest { v: 1; root: string; /** Every artifact transitively reachable through by-digest references from `root` (the root * appears only if a reference re-reaches it), sorted lexicographically, deduplicated. */ members: string[]; } /** Build the canonical manifest for a walked closure: refs normalize, members sort + dedup. * The ROOT is named by its own field and belongs in `members` only when a reference * re-reaches it (the §13.7 "reachable THROUGH references" rule, pinned here so two * implementations always mint the identical manifest). */ export declare function buildContractClosureManifest(rootRef: string, memberRefs: readonly string[]): ContractClosureManifest; /** Publish a closure's manifest as an ordinary canonical artifact; the returned digest IS the * closure digest (§13.7). */ export declare function publishContractClosureManifest(ctx: ContractStoreContext, manifest: ContractClosureManifest): Promise<{ closureDigestHex: string; won: boolean; }>; /** Fetch and VERIFY a closure by its CLOSURE digest (§13.7): fetch the manifest artifact at * that digest (its identity is proven by the fetch), then walk the by-digest references from * `root` through the `extractRefs` resolution seam and PROVE the walked set equals * `manifest.members` exactly — an under-naming manifest (the walk reaches an unlisted * artifact) and an over-naming one (a listed member is never reached) both refuse; a missing * artifact anywhere is all-or-nothing loud. The walk is BOUNDED: the frozen closure byte * bound, the reference-chain depth, the artifact-count ceiling (non-raiseable; a caller may * narrow), a per-artifact reference cap, and ONE total monotonic time budget. `extractRefs` * receives a DETACHED copy of each artifact's bytes (a mutating seam cannot poison the * returned map) and its answer is size-capped. Returns digest → bytes (manifest excluded; * root first, then first-visit order) plus the parsed manifest. */ export declare function fetchContractClosure(ctx: ContractStoreContext, closureDigestRef: string, extractRefs: (bytes: Uint8Array, digestHex: string) => string[], opts?: { maxArtifacts?: number; walkBudgetMs?: number; artifactMemo?: ArtifactMemo; }): Promise<{ manifest: ContractClosureManifest; artifacts: Map; }>; //# sourceMappingURL=endpoint-contract-store.d.ts.map