import type { KeyObject } from "node:crypto"; import type { Receipt } from "./attestation.js"; import { type ToolProxyExport } from "./toolproxy.js"; /** Thrown when a caged tool call violates policy (and is blocked). */ export declare class CageDenied extends Error { readonly tool: string; constructor(tool: string, message: string); } export interface CageOptions { /** Cryptographic principal the receipt is keyed on — a stable id (SPIFFE id, * key fingerprint, anything), NOT a mutable display name. */ principal: string; /** The tools this agent is permitted to call — its capability boundary. A call * to anything else is denied and recorded. */ allowedTools: string[]; } export interface ToolOptions { /** A per-call predicate to deny an in-boundary tool on specific arguments * (e.g. only allow `pay` below a cap). Returning false → blocked at runtime + * recorded as a deny. NOTE: the receipt attests the TOOL boundary (tool ∈ * allowedTools); a guard is finer RUNTIME hardening — a guard-denied call to * an allowed tool is still "in bounds" in the receipt (the tool was permitted). * Argument-level *proof* (e.g. "amount < cap over all inputs") is the * bytecode prover's job, not this receipt's. */ guard?: (...args: A) => boolean; /** Bind the call to its target (a URL, path, counterparty…) — recorded as a * digest in the receipt, so the receipt is specific to what was acted on. */ subject?: (...args: A) => string; } /** * A runtime cage for an agent's tool calls. Wrap each tool with {@link Cage.tool}; * every call is policy-checked and recorded, and a denied call is BLOCKED. At the * end {@link Cage.attest} signs an in-bounds receipt verifiable offline by this * same package. */ export declare class Cage { private readonly opts; private readonly records; constructor(opts: CageOptions); /** Wrap a tool function so each call is caged + recorded. Works for sync and * async tools (a denied call throws `CageDenied` before the tool runs). */ tool(name: string, fn: (...args: A) => R, options?: ToolOptions): (...args: A) => R; /** Record a call you invoke yourself (when wrapping the fn isn't convenient). */ record(name: string, allowed: boolean, subject?: string): void; /** How many calls have been caged so far. */ get callCount(): number; /** The raw verdict log — the tool-proxy export the verifier consumes. */ toExport(): ToolProxyExport; /** Sign an in-bounds attestation receipt. Verify it anywhere with * `verifyReceipt` / the `@coproduct_inc/verify` CLI — no trust in you required. */ attest(privateKey: KeyObject, opts?: { signedAt?: string; }): Receipt; }