/** * Framework-neutral execution causality. * * Traces describe one synchronous/remote observation tree. Causality survives the durable seams a * trace cannot: a command commits an outbox event, a workflow resumes tomorrow, a projection * consumes that event, and reconciliation repairs drift. This module carries only bounded identity * tokens and links; payloads, tenant identifiers, request URLs, and arbitrary attributes cannot enter * the graph by construction. */ /** A node category such as `request`, `command`, `event`, `workflow`, `projection`, or `repair`. */ export type CausalityKind = string; /** A bounded identity within one execution graph. */ export interface CausalityRef { readonly kind: CausalityKind; readonly id: string; } /** Optional OpenTelemetry anchor for the nearest observed ancestor. */ export interface CausalityTrace { readonly traceId: string; readonly spanId: string; } /** The propagation shape carried across commands/events/jobs. */ export interface CausalityContext { readonly executionId: string; readonly current: CausalityRef; /** Nearest observed ancestor; downstream observations can attach a real OTel span link to it. */ readonly trace?: CausalityTrace; } /** One immediate parent edge. Relation is a bounded token (`caused`, `emitted`, `projected`, …). */ export interface CausalityParent extends CausalityRef { readonly relation: string; } /** One append-only graph record. It intentionally has no payload or metadata field. */ export interface CausalityRecord { readonly executionId: string; readonly node: CausalityRef & { readonly at: number; /** Present only when this node itself opened an observation. */ readonly trace?: CausalityTrace; }; readonly parents: readonly CausalityParent[]; } /** A propagation context plus the graph record a durable adapter should append. */ export interface CausalityStep { readonly context: CausalityContext; readonly record: CausalityRecord; } export interface CausalityRecorder { /** Idempotently append one node and its immediate incoming edges. */ record(record: CausalityRecord, tx?: Tx): Promise<"inserted" | "duplicate">; } export interface CausalityTimelineItem { readonly cursor: string; readonly record: CausalityRecord; } export interface CausalityTimelinePage { readonly items: readonly CausalityTimelineItem[]; readonly nextCursor?: string; } export interface CausalityReader { timeline(executionId: string, options?: { readonly after?: string; readonly limit?: number; }): Promise; } export type CausalityGraphStore = CausalityRecorder & CausalityReader; export declare class CausalityConflictError extends Error { readonly executionId: string; readonly node: CausalityRef; constructor(executionId: string, node: CausalityRef); } export declare class CausalityCapacityError extends Error { readonly maxRecords: number; constructor(maxRecords: number); } export interface StartCausalityOptions { /** Stable graph identity. Generate once at the ingress boundary, then propagate it. */ readonly executionId: string; /** Epoch milliseconds. Injectable for deterministic tests. Default `Date.now()`. */ readonly at?: number; /** Observation opened for this exact node. */ readonly trace?: CausalityTrace; } export interface ContinueCausalityOptions { /** Edge relation. Default `caused`. */ readonly relation?: string; /** Epoch milliseconds. Injectable for deterministic tests. Default `Date.now()`. */ readonly at?: number; /** A new observation opened for this exact node; otherwise the nearest anchor is propagated. */ readonly trace?: CausalityTrace; } export type CausalityParseResult = { readonly success: true; readonly context: CausalityContext; } | { readonly success: false; readonly reason: "missing" | "incomplete" | "invalid" | "unknown-field"; }; export type CausalityRecordParseResult = { readonly success: true; readonly record: CausalityRecord; } | { readonly success: false; readonly reason: "incomplete" | "invalid" | "unknown-field"; }; export declare const CAUSALITY_EXECUTION_HEADER = "x-nifra-execution-id"; export declare const CAUSALITY_KIND_HEADER = "x-nifra-causality-kind"; export declare const CAUSALITY_NODE_HEADER = "x-nifra-causality-id"; export declare const CAUSALITY_TRACE_HEADER = "x-nifra-causality-trace"; /** Start a root execution node at an ingress boundary. */ export declare function startCausality(nodeKind: CausalityKind, id: string, options: StartCausalityOptions): CausalityStep; /** Continue one execution from a single immediate parent. */ export declare function continueCausality(parent: CausalityContext, nodeKind: CausalityKind, id: string, options?: ContinueCausalityOptions): CausalityStep; /** Join several immediate parents. Cross-execution joins fail closed. */ export declare function joinCausality(parents: readonly CausalityContext[], nodeKind: CausalityKind, id: string, options?: ContinueCausalityOptions): CausalityStep; /** Parse an untrusted durable graph record. Unknown fields fail closed at every nesting level. */ export declare function parseCausalityRecord(input: unknown): CausalityRecordParseResult; /** Parse an untrusted JSON causality context. Unknown fields fail closed so payloads cannot hitchhike. */ export declare function parseCausalityContext(input: unknown): CausalityParseResult; /** Serialize the propagation context into bounded HTTP headers. */ export declare function causalityHeaders(context: CausalityContext): Readonly>; /** Parse the public header convention without ever throwing on hostile input. */ export declare function readCausalityHeaders(headers: Headers): CausalityParseResult; export interface MemoryCausalityStoreOptions { /** Global record bound. Default 10,000. */ readonly maxRecords?: number; /** In-memory evidence disappears on restart and is rejected in production unless explicitly allowed. */ readonly allowInProduction?: boolean; } /** Bounded dev/test graph store. Production callers should provide a durable adapter. */ export declare function createMemoryCausalityStore(options?: MemoryCausalityStoreOptions): CausalityGraphStore; //# sourceMappingURL=causality.d.ts.map