/** * Transport-neutral fault model for the operation pipeline. * * `OperationFault` is what `executeOperation` returns when a request fails. * It carries a stable `code` (the discriminator), a human-readable `message` * for logs, and a typed `data` payload narrowed per-code via discriminated * union — so transport adapters can serialize the fault into the exact * wire shape their protocol expects without a string-sniffing layer. * * Two pure mapper functions translate the fault into a transport-specific * shape: * - `faultToHttpResponse(fault)` for REST. * - `faultToJsonRpcError(fault)` for the JSON-RPC transports. * Both consume `OperationFault` directly; serialization is not a method on * the fault class because that would force every transport to know about * every other transport's wire shape. * * **Scope.** The union covers operation-pipeline faults — what * `executeOperation` produces. Pure protocol-frame errors (JSON parse * failure, invalid JSON-RPC request envelope) live in the JSON-RPC parser * and use the spec-mandated reserved codes (-32700 / -32600); they do NOT * pass through this fault model. The v1 union is open for additive * extension — future codes (e.g. `PreconditionFailed`, `PayloadTooLarge`, * `ResourceExhausted`) can be added without breaking existing serializers * because the per-code mapping tables are exhaustive `Record` * and the JSON-RPC payload extractor is an exhaustive switch. * * **Every fault has a `data` field.** Even codes with no payload-specific * detail (`NotImplemented`, `EngineFailure`) carry `data: {}` so transport * adapters never branch on `data === undefined`. This uniformity is what * lets the exhaustive switch in `extractFaultDataPayload` stay small. * * The stable fault model with transport-neutral code, message, and typed * `data` payload forms the basis of cross-transport parity: every fault is * serialized consistently across REST and JSON-RPC transports. */ import type { WorkflowCompatibilityReason } from '../core/contract/compatibility.ts'; import type { FaultCode } from '../core/fault-code.ts'; import type { WorkflowSourceRejectionReason } from '../core/source/errors.ts'; import { type WeftErrorCode } from '../core/weft-error.ts'; /** Transport identifiers as seen by `executeOperation`. */ export type TransportKind = 'http-rest' | 'jsonRpcHttp' | 'jsonRpcWebSocket' | 'jsonRpcStdio'; /** A flattened zod issue, kept loose so we don't pin a zod version here. */ export type FlattenedZodIssue = { readonly path: ReadonlyArray; readonly message: string; readonly code: string; }; /** * Transport-neutral fault returned by `executeOperation`. Each variant has a * typed `data` payload — transport adapters destructure on `code` to access * the shape they need. */ export type OperationFault = { code: 'Unauthorized'; message: string; data: { reason: string; }; } | { code: 'Forbidden'; message: string; data: { reason: string; }; } | { code: 'NotFound'; message: string; data: { resource: string; identifier?: string | undefined; weftCode?: WeftErrorCode; }; } | { code: 'Conflict'; message: string; data: { reason: string; weftCode?: WeftErrorCode; missingTypes?: readonly string[] | undefined; missingWorkflowCount?: number | undefined; samplesTruncated?: boolean | undefined; currentGeneration?: number | undefined; compatibilityReasons?: readonly WorkflowCompatibilityReason[] | undefined; sourceValidationReasons?: readonly WorkflowSourceRejectionReason[] | undefined; }; } | { code: 'Unprocessable'; message: string; data: { reason: string; }; } | { code: 'PayloadTooLarge'; message: string; data: { maxBytes: number; }; } | { code: 'Timeout'; message: string; data: { operationName?: string | undefined; }; } | { code: 'NotImplemented'; message: string; data: Record; } | { code: 'UnsupportedTransport'; message: string; data: { transport: TransportKind; supported: ReadonlyArray; }; } | { code: 'SubscriptionOverflow'; message: string; data: { subscriptionId: string; droppedCount: number; }; } | { code: 'InvalidParams'; message: string; data: { issues: ReadonlyArray; weftCode?: WeftErrorCode; }; } | { code: 'MethodNotFound'; message: string; data: { method: string; }; } | { code: 'EngineFailure'; message: string; data: Record; }; /** * HTTP status code for each fault, used by `faultToHttpResponse`. Values * align with REST conventions; both `NotImplemented` and * `UnsupportedTransport` map to 501 because the caller asked for something * the server cannot fulfill. */ export declare const FAULT_CODE_TO_HTTP_STATUS: Readonly>; /** * Format an `InvalidParams` fault as a single human-readable error string * suitable for the body of a JSON response. Joins each Zod issue as * `path: message` (or just `message` at the root) with `; ` separators. */ export declare function formatInvalidParamsMessage(fault: Extract): string; export type RestFaultResponseOptions = { /** REST-only status override for a binding with an established non-canonical status. */ readonly status?: number; /** REST-only public message override for a binding with an established response message. */ readonly message?: string; }; export type RestFaultBody = { readonly error: string; readonly weftCode?: WeftErrorCode; readonly data?: Readonly>; }; /** * Map an `OperationFault` to the canonical additive REST body: * `{ error, weftCode?, data? }`. The existing string `error` and optional * fine-grained `weftCode` remain unchanged; `data` contains only fields from * the audited allowlist above. JSON-RPC uses its own broader projection. * * `EngineFailure` is a hard exception: its exact body remains * `{ "error": "Internal server error" }`, regardless of response overrides. */ export declare function shapeOperationFaultAsJson(fault: OperationFault, options?: RestFaultResponseOptions): Response; /** Canonical REST response used by bindings and route-dispatch fallback. */ export declare function shapeRestFaultAsJson(fault: OperationFault, options?: RestFaultResponseOptions): Response; /** * JSON-RPC error code for each fault. Reserved codes (-32700..-32603) keep * the spec meanings (`InvalidParams`, `MethodNotFound`); Weft domain codes * live in -32010..-32099 documented per design decision 4. */ export declare const FAULT_CODE_TO_JSON_RPC_CODE: Readonly>;