/** * Run outputs governance: shared types, defaults, and errors. * * Every control here is FINITE and enforceable: a visibility flag persisted at * write time (never inferred at read), hard byte limits checked before * persistence, expiry timestamps computed from a configured TTL and swept by * the expiry service, and ceilings checked at admission. The defaults are the * sane starting point the plan calls for (10MB per output, 100MB per run, * 30-day TTLs, $50/month ceiling); an embedder overrides them explicitly and * every override is still a finite number. */ import type { ServerRunRecord } from "../server/types.js"; /** Output visibility. Runs' outputs are PRIVATE by default; "public" is an explicit opt-in. */ export type OutputVisibility = "private" | "public"; /** Resource envelope a run requests at admission, checked against ceilings. */ export interface RunQuota { /** vCPU, fractional allowed. */ cpu: number; memoryMB: number; durationSeconds: number; networkMB: number; artifactBytes: number; } export interface OutputGovernanceConfig { /** Visibility stamped on every artifact at write time. Default "private". */ defaultVisibility?: OutputVisibility; /** * Pre-persistence redaction patterns applied to run output before it is * stored. Configurable; the default is the shipped credential patterns. */ redactPatterns?: RegExp[]; /** Hard per-output byte cap. Default 10MB. */ perOutputBytes?: number; /** Hard per-run total byte cap (all outputs of one run). Default 100MB. */ perRunTotalBytes?: number; /** * Finite retention in seconds. Every artifact gets expiresAt = * createdAt + ttl at write time. Default 30 days. */ artifactTtlSeconds?: number; } export interface SpendCeilings { /** Per-run resource envelope; any quota above it is refused at admission. */ perRun: RunQuota; /** Max concurrently admitted (queued/running/cancelling) runs per org. */ concurrency: number; /** Max estimated spend per org per calendar month, in cents. Default $50. */ monthlyTotalCents: number; } export declare const DEFAULT_OUTPUT_GOVERNANCE: Required; export declare const DEFAULT_RUN_QUOTA: RunQuota; export declare const DEFAULT_SPEND_CEILINGS: SpendCeilings; /** Machine-readable governance failure codes. Tests assert on these exactly. */ export declare const GOVERNANCE_ERROR_CODES: { /** An output exceeded the per-output byte cap at write time. */ readonly ARTIFACT_LIMIT_EXCEEDED: "ARTIFACT_LIMIT_EXCEEDED"; /** A run's accumulated outputs exceeded the per-run byte cap at write time. */ readonly RUN_ARTIFACT_TOTAL_EXCEEDED: "RUN_ARTIFACT_TOTAL_EXCEEDED"; /** Admission refused: a spend ceiling (per-run, concurrency, or monthly) is exhausted. */ readonly RUN_BUDGET_EXHAUSTED: "RUN_BUDGET_EXHAUSTED"; /** A fenced transition carried a stale lease_generation. */ readonly STALE_LEASE_GENERATION: "STALE_LEASE_GENERATION"; /** Cancellation was requested on a store that cannot fence generations. */ readonly FENCING_UNSUPPORTED: "FENCING_UNSUPPORTED"; /** An event payload carried content that must never enter @hasna/events. */ readonly EVENT_PAYLOAD_REJECTED: "EVENT_PAYLOAD_REJECTED"; /** Offline local run refused: the skill is not in the verified cache. */ readonly SKILL_UNAVAILABLE_OFFLINE: "SKILL_UNAVAILABLE_OFFLINE"; /** A remote run was attempted locally; the client never silently falls back. */ readonly REMOTE_REQUIRED: "REMOTE_REQUIRED"; }; export type GovernanceErrorCode = (typeof GOVERNANCE_ERROR_CODES)[keyof typeof GOVERNANCE_ERROR_CODES]; /** Every governance failure is one typed error with a stable code. */ export declare class GovernanceError extends Error { readonly code: GovernanceErrorCode; /** The ceiling or gate that refused, e.g. "monthly", "cpu", "ARTIFACT_LIMIT_EXCEEDED". */ readonly gate: string; /** Present when the code is RUN_BUDGET_EXHAUSTED: which ceiling exhausted. */ readonly ceiling?: string; constructor(code: GovernanceErrorCode, message: string, options?: { gate?: string; ceiling?: string; }); } /** Stable identity for a run's lifecycle: the pointers every receipt and event carries. */ export interface RunPointers { runId: string; attemptId: string; leaseGeneration: number; correlationId?: string; } export declare function runPointersOf(run: Pick): RunPointers;