@fabricorg/platform-host 7.6.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,193 +1,194 @@
1
- import { ActorType, ActionId, ActionStatus, EvidencePacketReference, AgentActionRoute, AgentActionRiskTier, MutationFootprint, ExecutionPrincipal, GovernanceRuntimeEvidence, PolicyOutcome, AssetEventEnvelope, PolicyObligation, PolicyObligationStatus, ExecutionAttestation, ExternalReconciliation, ModuleRegistry, ActionDefinition, AdapterImplementation, AdapterCircuitBreakerProvider, FabricRuntimeServices, AgentActionPolicyEvaluator, MutationGovernanceResolver, RuntimePolicyDefinition } from '@fabricorg/platform';
2
- export { canonicalJson } from '@fabricorg/platform';
3
- import { AssemblyLockfile } from '@fabricorg/assembly';
4
-
1
+ import { ActionDefinition, ActionId, ActionStatus, ActorType, AdapterCircuitBreakerProvider, AdapterImplementation, AgentActionPolicyEvaluator, AgentActionRiskTier, AgentActionRoute, AssetEventEnvelope, EvidencePacketReference, ExecutionAttestation, ExecutionPrincipal, ExternalReconciliation, FabricRuntimeServices, GovernanceRuntimeEvidence, ModuleRegistry, MutationFootprint, MutationGovernanceResolver, PolicyObligation, PolicyObligationStatus, PolicyOutcome, RuntimePolicyDefinition, canonicalJson } from "@fabricorg/platform";
2
+ import { AssemblyLockfile } from "@fabricorg/assembly";
3
+ //#region src/observability.d.ts
5
4
  /** Version of the vendor-neutral health/readiness contract. */
6
- declare const PLATFORM_HOST_HEALTH_CONTRACT_VERSION: 1;
5
+ export declare const PLATFORM_HOST_HEALTH_CONTRACT_VERSION: 1;
7
6
  /**
8
7
  * Stable metric names. Adapters may translate these names to a vendor's
9
8
  * naming convention, but applications should not derive names from labels.
10
9
  */
11
- declare const PLATFORM_HOST_METRIC_NAMES: {
12
- readonly workerCyclesStarted: "fabric.platform.worker.cycles.started";
13
- readonly workerCyclesCompleted: "fabric.platform.worker.cycles.completed";
14
- readonly workerCyclesFailed: "fabric.platform.worker.cycles.failed";
15
- readonly invocationSubmitted: "fabric.platform.invocation.submitted";
16
- readonly invocationAdmissionRefused: "fabric.platform.invocation.admission_refused";
17
- readonly invocationExecutionStarted: "fabric.platform.invocation.execution_started";
18
- readonly invocationLeaseClaimed: "fabric.platform.invocation.lease_claimed";
19
- readonly invocationCompleted: "fabric.platform.invocation.completed";
20
- readonly invocationFailed: "fabric.platform.invocation.failed";
21
- readonly invocationPolicyBlocked: "fabric.platform.invocation.policy_blocked";
22
- readonly invocationValidationFailed: "fabric.platform.invocation.validation_failed";
23
- readonly invocationApprovalWaited: "fabric.platform.invocation.approval_waited";
24
- readonly invocationReconciliationRequired: "fabric.platform.invocation.reconciliation_required";
25
- readonly outboxRelayCyclesStarted: "fabric.platform.outbox.relay_cycles.started";
26
- readonly outboxRelayCyclesCompleted: "fabric.platform.outbox.relay_cycles.completed";
27
- readonly outboxRelayCyclesFailed: "fabric.platform.outbox.relay_cycles.failed";
28
- readonly outboxLeaseClaimed: "fabric.platform.outbox.lease_claimed";
29
- readonly outboxPublished: "fabric.platform.outbox.published";
30
- readonly outboxFailed: "fabric.platform.outbox.failed";
31
- readonly outboxDeadLettered: "fabric.platform.outbox.dead_lettered";
32
- readonly outboxRequeued: "fabric.platform.outbox.requeued";
33
- readonly outboxRequeueRefused: "fabric.platform.outbox.requeue_refused";
34
- readonly invocationBacklog: "fabric.platform.invocation.backlog";
35
- readonly invocationRunning: "fabric.platform.invocation.running";
36
- readonly invocationExpiredLeases: "fabric.platform.invocation.expired_leases";
37
- readonly invocationApprovalWaits: "fabric.platform.invocation.approval_waits";
38
- readonly invocationReconciliationRequiredGauge: "fabric.platform.invocation.reconciliation_required.count";
39
- readonly outboxBacklog: "fabric.platform.outbox.backlog";
40
- readonly outboxExpiredLeases: "fabric.platform.outbox.expired_leases";
41
- readonly outboxDeadLetters: "fabric.platform.outbox.dead_letters";
10
+ export declare const PLATFORM_HOST_METRIC_NAMES: {
11
+ readonly workerCyclesStarted: "fabric.platform.worker.cycles.started";
12
+ readonly workerCyclesCompleted: "fabric.platform.worker.cycles.completed";
13
+ readonly workerCyclesFailed: "fabric.platform.worker.cycles.failed";
14
+ readonly invocationSubmitted: "fabric.platform.invocation.submitted";
15
+ readonly invocationAdmissionRefused: "fabric.platform.invocation.admission_refused";
16
+ readonly invocationExecutionStarted: "fabric.platform.invocation.execution_started";
17
+ readonly invocationLeaseClaimed: "fabric.platform.invocation.lease_claimed";
18
+ readonly invocationCompleted: "fabric.platform.invocation.completed";
19
+ readonly invocationFailed: "fabric.platform.invocation.failed";
20
+ readonly invocationPolicyBlocked: "fabric.platform.invocation.policy_blocked";
21
+ readonly invocationValidationFailed: "fabric.platform.invocation.validation_failed";
22
+ readonly invocationApprovalWaited: "fabric.platform.invocation.approval_waited";
23
+ readonly invocationReconciliationRequired: "fabric.platform.invocation.reconciliation_required";
24
+ readonly adapterEvidenceRefused: "fabric.platform.invocation.adapter_evidence_refused";
25
+ readonly outboxRelayCyclesStarted: "fabric.platform.outbox.relay_cycles.started";
26
+ readonly outboxRelayCyclesCompleted: "fabric.platform.outbox.relay_cycles.completed";
27
+ readonly outboxRelayCyclesFailed: "fabric.platform.outbox.relay_cycles.failed";
28
+ readonly outboxLeaseClaimed: "fabric.platform.outbox.lease_claimed";
29
+ readonly outboxPublished: "fabric.platform.outbox.published";
30
+ readonly outboxFailed: "fabric.platform.outbox.failed";
31
+ readonly outboxDeadLettered: "fabric.platform.outbox.dead_lettered";
32
+ readonly outboxRequeued: "fabric.platform.outbox.requeued";
33
+ readonly outboxRequeueRefused: "fabric.platform.outbox.requeue_refused";
34
+ readonly invocationBacklog: "fabric.platform.invocation.backlog";
35
+ readonly invocationRunning: "fabric.platform.invocation.running";
36
+ readonly invocationExpiredLeases: "fabric.platform.invocation.expired_leases";
37
+ readonly invocationApprovalWaits: "fabric.platform.invocation.approval_waits";
38
+ readonly invocationReconciliationRequiredGauge: "fabric.platform.invocation.reconciliation_required.count";
39
+ readonly outboxBacklog: "fabric.platform.outbox.backlog";
40
+ readonly outboxExpiredLeases: "fabric.platform.outbox.expired_leases";
41
+ readonly outboxDeadLetters: "fabric.platform.outbox.dead_letters";
42
42
  };
43
- type PlatformHostMetricName = (typeof PLATFORM_HOST_METRIC_NAMES)[keyof typeof PLATFORM_HOST_METRIC_NAMES];
44
- type PlatformHostTelemetryEventName = "worker.cycle.started" | "worker.cycle.completed" | "worker.cycle.failed" | "invocation.submitted" | "invocation.admission_refused" | "invocation.execution_started" | "invocation.lease_claimed" | "invocation.completed" | "invocation.failed" | "invocation.policy_blocked" | "invocation.validation_failed" | "invocation.approval_waited" | "invocation.reconciliation_required" | "outbox.relay.started" | "outbox.relay.completed" | "outbox.relay.failed" | "outbox.lease_claimed" | "outbox.published" | "outbox.failed" | "outbox.dead_lettered" | "outbox.requeued" | "outbox.requeue_refused";
45
- type PlatformHostMetricType = "counter" | "gauge";
46
- type PlatformHostTelemetryAttribute = string | number | boolean;
47
- interface PlatformHostLifecycleTelemetry {
48
- kind: "event";
49
- name: PlatformHostTelemetryEventName;
50
- metricName: PlatformHostMetricName;
51
- metricType: "counter";
52
- occurredAt: Date;
53
- tenantId?: string;
54
- spaceId?: string;
55
- attributes?: Readonly<Record<string, PlatformHostTelemetryAttribute>>;
56
- }
57
- interface PlatformHostMetricTelemetry {
58
- kind: "metric";
59
- name: PlatformHostMetricName;
60
- metricType: PlatformHostMetricType;
61
- value: number;
62
- observedAt: Date;
63
- tenantId?: string;
64
- spaceId?: string;
65
- }
66
- type PlatformHostTelemetryRecord = PlatformHostLifecycleTelemetry | PlatformHostMetricTelemetry;
67
- type PlatformHostTelemetryHook = (record: PlatformHostTelemetryRecord) => void | Promise<void>;
43
+ export type PlatformHostMetricName = (typeof PLATFORM_HOST_METRIC_NAMES)[keyof typeof PLATFORM_HOST_METRIC_NAMES];
44
+ export type PlatformHostTelemetryEventName = "worker.cycle.started" | "worker.cycle.completed" | "worker.cycle.failed" | "invocation.submitted" | "invocation.admission_refused" | "invocation.execution_started" | "invocation.lease_claimed" | "invocation.completed" | "invocation.failed" | "invocation.policy_blocked" | "invocation.validation_failed" | "invocation.approval_waited" | "invocation.reconciliation_required" | "invocation.adapter_evidence_refused" | "outbox.relay.started" | "outbox.relay.completed" | "outbox.relay.failed" | "outbox.lease_claimed" | "outbox.published" | "outbox.failed" | "outbox.dead_lettered" | "outbox.requeued" | "outbox.requeue_refused";
45
+ export type PlatformHostMetricType = "counter" | "gauge";
46
+ export type PlatformHostTelemetryAttribute = string | number | boolean;
47
+ export interface PlatformHostLifecycleTelemetry {
48
+ kind: "event";
49
+ name: PlatformHostTelemetryEventName;
50
+ metricName: PlatformHostMetricName;
51
+ metricType: "counter";
52
+ occurredAt: Date;
53
+ tenantId?: string;
54
+ spaceId?: string;
55
+ attributes?: Readonly<Record<string, PlatformHostTelemetryAttribute>>;
56
+ }
57
+ export interface PlatformHostMetricTelemetry {
58
+ kind: "metric";
59
+ name: PlatformHostMetricName;
60
+ metricType: PlatformHostMetricType;
61
+ value: number;
62
+ observedAt: Date;
63
+ tenantId?: string;
64
+ spaceId?: string;
65
+ }
66
+ export type PlatformHostTelemetryRecord = PlatformHostLifecycleTelemetry | PlatformHostMetricTelemetry;
67
+ export type PlatformHostTelemetryHook = (record: PlatformHostTelemetryRecord) => void | Promise<void>;
68
68
  /**
69
69
  * A deliberately small sink contract. No OpenTelemetry, Prometheus, or
70
70
  * vendor SDK is required by Platform Host.
71
71
  */
72
- type PlatformHostTelemetry = PlatformHostTelemetryHook | {
73
- record: PlatformHostTelemetryHook;
72
+ export type PlatformHostTelemetry = PlatformHostTelemetryHook | {
73
+ record: PlatformHostTelemetryHook;
74
74
  };
75
- type PlatformHostTelemetryInput = Omit<PlatformHostLifecycleTelemetry, "occurredAt" | "metricType"> & {
76
- occurredAt?: Date;
75
+ export type PlatformHostTelemetryInput = Omit<PlatformHostLifecycleTelemetry, "occurredAt" | "metricType"> & {
76
+ occurredAt?: Date;
77
77
  } | Omit<PlatformHostMetricTelemetry, "observedAt"> & {
78
- observedAt?: Date;
78
+ observedAt?: Date;
79
79
  };
80
80
  /**
81
81
  * Telemetry is best effort and must never change governed mutation behavior.
82
82
  * Promise-returning hooks are detached and rejected hooks are swallowed.
83
83
  */
84
- declare function emitPlatformHostTelemetry(telemetry: PlatformHostTelemetry | undefined, input: PlatformHostTelemetryInput): void;
85
- interface PlatformHostHealthQuery {
84
+ export declare function emitPlatformHostTelemetry(telemetry: PlatformHostTelemetry | undefined, input: PlatformHostTelemetryInput): void;
85
+ export interface PlatformHostHealthQuery {
86
+ tenantId?: string;
87
+ spaceId?: string;
88
+ now: Date;
89
+ }
90
+ export interface PlatformHostHealthCounts {
91
+ invocationBacklog: number;
92
+ invocationRunning: number;
93
+ invocationExpiredLeases: number;
94
+ invocationApprovalWaits: number;
95
+ invocationReconciliationRequired: number;
96
+ outboxBacklog: number;
97
+ outboxExpiredLeases: number;
98
+ outboxDeadLetters: number;
99
+ }
100
+ export interface PlatformHostWorkerHealthInput {
101
+ lastHeartbeatAt: Date;
102
+ staleAfterMs: number;
103
+ }
104
+ export interface PlatformHostHealthOptions<TDb> {
105
+ store: PlatformHostStore<TDb>;
106
+ tenantId?: string;
107
+ spaceId?: string;
108
+ now?: () => Date;
109
+ /**
110
+ * Worker liveness is supplied by the deployment's supervisor or telemetry
111
+ * bridge. Only aggregate healthy/stale counts are returned.
112
+ */
113
+ workers?: readonly PlatformHostWorkerHealthInput[];
114
+ telemetry?: PlatformHostTelemetry;
115
+ }
116
+ export interface PlatformHostHealthStore<TDb> extends RecoverablePlatformHostStore<TDb> {
117
+ getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
118
+ }
119
+ export type PlatformHostHealthStatus = "healthy" | "degraded" | "unhealthy";
120
+ export interface PlatformHostHealthSnapshot {
121
+ contractVersion: typeof PLATFORM_HOST_HEALTH_CONTRACT_VERSION;
122
+ generatedAt: Date;
123
+ scope: {
86
124
  tenantId?: string;
87
125
  spaceId?: string;
88
- now: Date;
89
- }
90
- interface PlatformHostHealthCounts {
91
- invocationBacklog: number;
92
- invocationRunning: number;
93
- invocationExpiredLeases: number;
94
- invocationApprovalWaits: number;
95
- invocationReconciliationRequired: number;
96
- outboxBacklog: number;
97
- outboxExpiredLeases: number;
98
- outboxDeadLetters: number;
99
- }
100
- interface PlatformHostWorkerHealthInput {
101
- lastHeartbeatAt: Date;
102
- staleAfterMs: number;
103
- }
104
- interface PlatformHostHealthOptions<TDb> {
105
- store: PlatformHostStore<TDb>;
106
- tenantId?: string;
107
- spaceId?: string;
108
- now?: () => Date;
109
- /**
110
- * Worker liveness is supplied by the deployment's supervisor or telemetry
111
- * bridge. Only aggregate healthy/stale counts are returned.
112
- */
113
- workers?: readonly PlatformHostWorkerHealthInput[];
114
- telemetry?: PlatformHostTelemetry;
115
- }
116
- interface PlatformHostHealthStore<TDb> extends RecoverablePlatformHostStore<TDb> {
117
- getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
118
- }
119
- type PlatformHostHealthStatus = "healthy" | "degraded" | "unhealthy";
120
- interface PlatformHostHealthSnapshot {
121
- contractVersion: typeof PLATFORM_HOST_HEALTH_CONTRACT_VERSION;
122
- generatedAt: Date;
123
- scope: {
124
- tenantId?: string;
125
- spaceId?: string;
126
- };
127
- dataAvailable: boolean;
128
- status: PlatformHostHealthStatus;
129
- readiness: {
130
- ready: boolean;
131
- reasonCodes: readonly PlatformHostReadinessReason[];
132
- };
133
- workers: {
134
- reported: number;
135
- healthy: number;
136
- stale: number;
137
- };
138
- invocations: {
139
- backlog: number;
140
- running: number;
141
- expiredLeases: number;
142
- approvalWaits: number;
143
- reconciliationRequired: number;
144
- };
145
- outbox: {
146
- backlog: number;
147
- expiredLeases: number;
148
- deadLetters: number;
149
- };
150
- }
151
- type PlatformHostReadinessReason = "health_source_unavailable" | "workers_stale" | "invocation_expired_leases" | "outbox_expired_leases" | "outbox_dead_letters" | "reconciliation_required";
126
+ };
127
+ dataAvailable: boolean;
128
+ status: PlatformHostHealthStatus;
129
+ readiness: {
130
+ ready: boolean;
131
+ reasonCodes: readonly PlatformHostReadinessReason[];
132
+ };
133
+ workers: {
134
+ reported: number;
135
+ healthy: number;
136
+ stale: number;
137
+ };
138
+ invocations: {
139
+ backlog: number;
140
+ running: number;
141
+ expiredLeases: number;
142
+ approvalWaits: number;
143
+ reconciliationRequired: number;
144
+ };
145
+ outbox: {
146
+ backlog: number;
147
+ expiredLeases: number;
148
+ deadLetters: number;
149
+ };
150
+ }
151
+ export type PlatformHostReadinessReason = "health_source_unavailable" | "workers_stale" | "invocation_expired_leases" | "outbox_expired_leases" | "outbox_dead_letters" | "reconciliation_required";
152
152
  /**
153
153
  * Read tenant/space-scoped operational counts without returning invocation,
154
154
  * actor, parameter, error, event, or adapter data.
155
155
  */
156
- declare function getPlatformHostHealthSnapshot<TDb>(options: PlatformHostHealthOptions<TDb>): Promise<PlatformHostHealthSnapshot>;
157
-
156
+ export declare function getPlatformHostHealthSnapshot<TDb>(options: PlatformHostHealthOptions<TDb>): Promise<PlatformHostHealthSnapshot>;
157
+ //#endregion
158
+ //#region src/types.d.ts
158
159
  /** Durable Host lifecycle generation, independent from the npm package version. */
159
- declare const PLATFORM_HOST_CONTRACT_VERSION: 2;
160
- type InvocationSource = "ui" | "api" | "agent" | "worker" | "system" | (string & {});
161
- type NamespacedAttributes = Record<string, string>;
162
- interface InvocationProvenance {
163
- source: InvocationSource;
164
- correlationId: string;
165
- causationId?: string;
166
- traceAttributes?: NamespacedAttributes;
167
- auditAttributes?: NamespacedAttributes;
168
- }
169
- type AuthorizationGoverningMoment = "capture" | "execution" | "both";
170
- interface AuthorizationBinding {
171
- id: string;
172
- tenantId: string;
173
- actorId: string;
174
- actionId: string;
175
- parameterDigest: string;
176
- resourceScope?: string;
177
- capturedAt: string;
178
- expiresAt?: string;
179
- governingMoment: AuthorizationGoverningMoment;
180
- }
181
- interface IdempotencyConflict {
182
- code: "IDEMPOTENCY_CONFLICT";
183
- idempotencyKey: string;
184
- existingInvocationId: string;
185
- reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters">;
186
- }
187
- declare class IdempotencyConflictError extends Error {
188
- readonly conflict: IdempotencyConflict;
189
- readonly code: "IDEMPOTENCY_CONFLICT";
190
- constructor(conflict: IdempotencyConflict);
160
+ export declare const PLATFORM_HOST_CONTRACT_VERSION: 2;
161
+ export type InvocationSource = "ui" | "api" | "agent" | "worker" | "system" | (string & {});
162
+ export type NamespacedAttributes = Record<string, string>;
163
+ export interface InvocationProvenance {
164
+ source: InvocationSource;
165
+ correlationId: string;
166
+ causationId?: string;
167
+ traceAttributes?: NamespacedAttributes;
168
+ auditAttributes?: NamespacedAttributes;
169
+ }
170
+ export type AuthorizationGoverningMoment = "capture" | "execution" | "both";
171
+ export interface AuthorizationBinding {
172
+ id: string;
173
+ tenantId: string;
174
+ actorId: string;
175
+ actionId: string;
176
+ parameterDigest: string;
177
+ resourceScope?: string;
178
+ capturedAt: string;
179
+ expiresAt?: string;
180
+ governingMoment: AuthorizationGoverningMoment;
181
+ }
182
+ export interface IdempotencyConflict {
183
+ code: "IDEMPOTENCY_CONFLICT";
184
+ idempotencyKey: string;
185
+ existingInvocationId: string;
186
+ reasons: Array<"actor" | "authority_binding" | "action_version" | "parameters">;
187
+ }
188
+ export declare class IdempotencyConflictError extends Error {
189
+ readonly conflict: IdempotencyConflict;
190
+ readonly code: "IDEMPOTENCY_CONFLICT";
191
+ constructor(conflict: IdempotencyConflict);
191
192
  }
192
193
  /**
193
194
  * Why `submitAction` did not admit a submission of an action that declares
@@ -199,7 +200,7 @@ declare class IdempotencyConflictError extends Error {
199
200
  * JSON-data object Host could copy at submission (a Proxy, a function, a
200
201
  * Date, a typed array or SharedArrayBuffer, a cycle, a getter that throws).
201
202
  */
202
- type ActionAdmissionRefusal = "refused" | "failed" | "timed_out" | "invalid_decision" | "invalid_parameters";
203
+ export type ActionAdmissionRefusal = "refused" | "failed" | "timed_out" | "invalid_decision" | "invalid_parameters";
203
204
  /**
204
205
  * Thrown by `submitAction` when a declared admission check did not admit the
205
206
  * submission. Host wrote nothing for it: no invocation, idempotency key,
@@ -207,17 +208,17 @@ type ActionAdmissionRefusal = "refused" | "failed" | "timed_out" | "invalid_deci
207
208
  * refusal and, for `refused`, the check's code; never a submitted value or
208
209
  * anything the check threw.
209
210
  */
210
- declare class ActionAdmissionError extends Error {
211
- readonly actionId: string;
212
- readonly refusal: ActionAdmissionRefusal;
213
- /** The check's own code, present only for `refused`. */
214
- readonly refusalCode?: string | undefined;
215
- readonly code: "ACTION_ADMISSION_REFUSED";
216
- constructor(actionId: string, refusal: ActionAdmissionRefusal,
217
- /** The check's own code, present only for `refused`. */
218
- refusalCode?: string | undefined);
219
- }
220
- type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting" | "immediate_contract" | "reference_mismatch" | "provider_mismatch" | "invalid_completion" | "result_invalid" | "redaction_failed";
211
+ export declare class ActionAdmissionError extends Error {
212
+ readonly actionId: string;
213
+ readonly refusal: ActionAdmissionRefusal;
214
+ /** The check's own code, present only for `refused`. */
215
+ readonly refusalCode?: string | undefined;
216
+ readonly code: "ACTION_ADMISSION_REFUSED";
217
+ constructor(actionId: string, refusal: ActionAdmissionRefusal,
218
+ /** The check's own code, present only for `refused`. */
219
+ refusalCode?: string | undefined);
220
+ }
221
+ export type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting" | "immediate_contract" | "reference_mismatch" | "provider_mismatch" | "invalid_completion" | "result_invalid" | "redaction_failed";
221
222
  /**
222
223
  * Why a completion was not applied, typed so a webhook handler can answer
223
224
  * the external system correctly: `retryable` means the invocation is still
@@ -227,159 +228,162 @@ type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting
227
228
  * `redaction_failed` means completion result or error-text redaction failed before writes;
228
229
  * it is not retryable.
229
230
  */
230
- declare class ExternalCompletionError extends Error {
231
- readonly refusal: ExternalCompletionRefusal;
232
- readonly code: "EXTERNAL_COMPLETION_REFUSED";
233
- constructor(refusal: ExternalCompletionRefusal, message: string);
234
- get retryable(): boolean;
235
- }
236
- interface PendingAssetEvent {
237
- eventType: string;
238
- subjectType: string;
239
- subjectId: string;
240
- payload: unknown;
241
- eventSchemaVersion?: number;
242
- }
243
- interface ActionInvocationRecord {
244
- id: string;
245
- tenantId: string;
246
- spaceId: string;
247
- actionId: ActionId;
248
- actionVersion: number;
249
- actorId: string;
250
- actorType: ActorType;
251
- status: ActionStatus;
252
- parameters: Record<string, unknown>;
253
- result: Record<string, unknown>;
254
- correlationId: string;
255
- causationId?: string;
256
- idempotencyKey?: string;
257
- parameterDigest?: string;
258
- parameterDigestAlgorithm?: "fabric-canonical-json-sha256-v1";
259
- idempotencyActorId?: string;
260
- idempotencyAuthorizationBindingId?: string;
261
- provenance?: Omit<InvocationProvenance, "traceAttributes">;
262
- authorizationBinding?: AuthorizationBinding;
263
- executionReason?: ActionExecutionReason;
264
- authorizationReconciliation?: AuthorizationReconciliationOutcome;
265
- /** Durable evidence when an adapter returned an ambiguous outcome requiring reconciliation. */
266
- adapterReconciliation?: AdapterReconciliationOutcome;
267
- /**
268
- * Transition Host validated for an idempotent after_adapters action, saved
269
- * after handler/result/event validation inside a mutation transaction, or before
270
- * the handler otherwise. Supports recovered StateTransitioned emission and is
271
- * retained as evidence after completion.
272
- */
273
- pendingStateTransition?: {
274
- entityType: string;
275
- entityId: string;
276
- fromState: string;
277
- toState: string;
278
- };
279
- /**
280
- * A handoff the host is waiting on. While present the invocation is
281
- * `running` without a lease: it is not stuck, it is somebody else's turn,
282
- * and the recovery worker must not re-execute it.
283
- */
284
- pendingCompletion?: PendingExternalCompletion;
285
- /** The completion an external system delivered, kept so a repeat is recognised and a contradiction is caught. */
286
- externalCompletion?: RecordedExternalCompletion;
287
- /** Opaque, non-secret reference used to revalidate delegated execution authority. */
288
- authorizationBindingId?: string;
289
- attemptCount: number;
290
- leaseOwner?: string;
291
- leaseExpiresAt?: Date;
292
- /** Monotonic claim generation used to reject writes from expired workers. */
293
- leaseToken?: number;
294
- hitlRoute?: AgentActionRoute;
295
- hitlRiskTier?: AgentActionRiskTier;
296
- hitlReason?: string;
297
- hitlPolicyVersion?: string;
298
- approvalDecision?: PersistedActionApprovalDecision;
299
- mutationFootprint?: MutationFootprint;
300
- executionPrincipal?: ExecutionPrincipal;
301
- runtimeEvidence?: GovernanceRuntimeEvidence;
302
- /**
303
- * When `submitAction` admitted the submission through the action's
304
- * `admitSubmission` check, set on creation and never patched. Host refuses
305
- * to execute an invocation of an action that declares the check when this
306
- * is absent, and passes it to the handler as `ActionContext.admittedAt`.
307
- */
308
- admittedAt?: Date;
309
- error?: string;
310
- createdAt: Date;
311
- updatedAt: Date;
312
- }
313
- interface AuthorizationReconciliationOutcome {
314
- kind: "authorization_expired" | "authorization_denied" | "authorization_missing_capture_evidence";
315
- governingMoment: AuthorizationGoverningMoment;
316
- executionReason: ActionExecutionReason;
317
- authorizationBindingId?: string;
318
- provenance?: Omit<InvocationProvenance, "traceAttributes">;
319
- message: string;
320
- }
321
- interface HitlDecisionEvidence {
322
- route: AgentActionRoute;
323
- riskTier: AgentActionRiskTier;
324
- reason: string;
325
- policyVersion?: string;
326
- evaluatedAt: Date;
327
- }
328
- interface ActionApprovalDecision {
329
- approved: boolean;
330
- approverId: string;
331
- approverType: ActorType;
332
- reason?: string;
333
- editsReference?: string;
334
- decidedAt?: Date;
335
- }
336
- interface PersistedActionApprovalDecision extends Omit<ActionApprovalDecision, "decidedAt"> {
337
- decidedAt: Date;
338
- }
339
- interface PolicyEvaluationRecord {
340
- id: string;
341
- actionInvocationId: string;
342
- tenantId: string;
343
- spaceId: string;
344
- outcome: PolicyOutcome;
345
- createdAt: Date;
346
- }
347
- interface PolicyObligationRecord extends PolicyObligation {
348
- actionInvocationId: string;
349
- tenantId: string;
350
- spaceId: string;
351
- createdAt: Date;
352
- updatedAt: Date;
353
- }
354
- interface ExecutionAttestationRecord extends ExecutionAttestation {
355
- id: string;
356
- actionInvocationId: string;
357
- tenantId: string;
358
- spaceId: string;
359
- adapterInvocationId?: string;
360
- recordedAt: Date;
361
- }
362
- interface ExternalReconciliationRecord extends ExternalReconciliation {
363
- id: string;
364
- actionInvocationId: string;
365
- tenantId: string;
366
- spaceId: string;
367
- }
368
- interface PendingExternalCompletion {
369
- provider: string;
370
- adapterType: string;
371
- operation: string;
372
- adapterInvocationId: string;
373
- externalReference: string;
374
- acceptedAt: Date;
375
- /** Past this instant the host moves the invocation to reconciliation. */
376
- dueAt?: Date;
377
- /**
378
- * Set when the invocation finished executing and parked. A handoff is
379
- * recorded before the remaining steps run, so until this is set a
380
- * completion has nothing settled to settle into; it is asked to retry.
381
- */
382
- parkedAt?: Date;
231
+ export declare class ExternalCompletionError extends Error {
232
+ readonly refusal: ExternalCompletionRefusal;
233
+ readonly code: "EXTERNAL_COMPLETION_REFUSED";
234
+ constructor(refusal: ExternalCompletionRefusal, message: string);
235
+ get retryable(): boolean;
236
+ }
237
+ export interface PendingAssetEvent {
238
+ eventType: string;
239
+ subjectType: string;
240
+ subjectId: string;
241
+ payload: unknown;
242
+ eventSchemaVersion?: number;
243
+ }
244
+ export interface ActionInvocationRecord {
245
+ id: string;
246
+ tenantId: string;
247
+ spaceId: string;
248
+ actionId: ActionId;
249
+ actionVersion: number;
250
+ actorId: string;
251
+ actorType: ActorType;
252
+ status: ActionStatus;
253
+ parameters: Record<string, unknown>;
254
+ result: Record<string, unknown>;
255
+ correlationId: string;
256
+ causationId?: string;
257
+ idempotencyKey?: string;
258
+ parameterDigest?: string;
259
+ parameterDigestAlgorithm?: "fabric-canonical-json-sha256-v1";
260
+ idempotencyActorId?: string;
261
+ idempotencyAuthorizationBindingId?: string;
262
+ provenance?: Omit<InvocationProvenance, "traceAttributes">;
263
+ authorizationBinding?: AuthorizationBinding;
264
+ executionReason?: ActionExecutionReason;
265
+ authorizationReconciliation?: AuthorizationReconciliationOutcome;
266
+ /** Durable evidence when an adapter returned an ambiguous outcome requiring reconciliation. */
267
+ adapterReconciliation?: AdapterReconciliationOutcome;
268
+ /**
269
+ * Transition Host validated for an idempotent after_adapters action, saved
270
+ * after handler/result/event validation inside a mutation transaction, or before
271
+ * the handler otherwise. Supports recovered StateTransitioned emission and is
272
+ * retained as evidence after completion.
273
+ */
274
+ pendingStateTransition?: {
275
+ entityType: string;
276
+ entityId: string;
277
+ fromState: string;
278
+ toState: string;
279
+ };
280
+ /**
281
+ * A handoff the host is waiting on. While present the invocation is
282
+ * `running` without a lease: it is not stuck, it is somebody else's turn,
283
+ * and the recovery worker must not re-execute it.
284
+ */
285
+ pendingCompletion?: PendingExternalCompletion;
286
+ /** The completion an external system delivered, kept so a repeat is recognised and a contradiction is caught. */
287
+ externalCompletion?: RecordedExternalCompletion;
288
+ /** Opaque, non-secret reference used to revalidate delegated execution authority. */
289
+ authorizationBindingId?: string;
290
+ /** Worker claims including the first; approval acceptance sets a minimum of 1. */
291
+ attemptCount: number;
292
+ leaseOwner?: string;
293
+ leaseExpiresAt?: Date;
294
+ /** Monotonic claim generation used to reject writes from expired workers. */
295
+ leaseToken?: number;
296
+ hitlRoute?: AgentActionRoute;
297
+ hitlRiskTier?: AgentActionRiskTier;
298
+ hitlReason?: string;
299
+ hitlPolicyVersion?: string;
300
+ approvalDecision?: PersistedActionApprovalDecision;
301
+ mutationFootprint?: MutationFootprint;
302
+ executionPrincipal?: ExecutionPrincipal;
303
+ runtimeEvidence?: GovernanceRuntimeEvidence;
304
+ /**
305
+ * When `submitAction` admitted the submission through the action's
306
+ * `admitSubmission` check, set on creation and never patched. Host refuses
307
+ * to execute an invocation of an action that declares the check when this
308
+ * is absent, and passes it to the handler as `ActionContext.admittedAt`.
309
+ */
310
+ admittedAt?: Date;
311
+ error?: string;
312
+ createdAt: Date;
313
+ updatedAt: Date;
314
+ }
315
+ export interface AuthorizationReconciliationOutcome {
316
+ kind: "authorization_expired" | "authorization_denied" | "authorization_missing_capture_evidence";
317
+ governingMoment: AuthorizationGoverningMoment;
318
+ executionReason: ActionExecutionReason;
319
+ authorizationBindingId?: string;
320
+ provenance?: Omit<InvocationProvenance, "traceAttributes">;
321
+ message: string;
322
+ }
323
+ export interface HitlDecisionEvidence {
324
+ route: AgentActionRoute;
325
+ riskTier: AgentActionRiskTier;
326
+ reason: string;
327
+ policyVersion?: string;
328
+ evaluatedAt: Date;
329
+ }
330
+ export interface ActionApprovalDecision {
331
+ approved: boolean;
332
+ approverId: string;
333
+ approverType: ActorType;
334
+ reason?: string;
335
+ editsReference?: string;
336
+ decidedAt?: Date;
337
+ }
338
+ export interface PersistedActionApprovalDecision extends Omit<ActionApprovalDecision, "decidedAt"> {
339
+ decidedAt: Date;
340
+ }
341
+ export interface PolicyEvaluationRecord {
342
+ id: string;
343
+ actionInvocationId: string;
344
+ tenantId: string;
345
+ spaceId: string;
346
+ outcome: PolicyOutcome;
347
+ createdAt: Date;
348
+ }
349
+ export interface PolicyObligationRecord extends PolicyObligation {
350
+ actionInvocationId: string;
351
+ tenantId: string;
352
+ spaceId: string;
353
+ createdAt: Date;
354
+ updatedAt: Date;
355
+ }
356
+ export interface ExecutionAttestationRecord extends ExecutionAttestation {
357
+ id: string;
358
+ actionInvocationId: string;
359
+ tenantId: string;
360
+ spaceId: string;
361
+ adapterInvocationId?: string;
362
+ recordedAt: Date;
363
+ }
364
+ export interface ExternalReconciliationRecord extends ExternalReconciliation {
365
+ id: string;
366
+ actionInvocationId: string;
367
+ tenantId: string;
368
+ spaceId: string;
369
+ }
370
+ export interface PendingExternalCompletion {
371
+ provider: string;
372
+ adapterType: string;
373
+ operation: string;
374
+ adapterInvocationId: string;
375
+ externalReference: string;
376
+ acceptedAt: Date;
377
+ /** Past this instant the host moves the invocation to reconciliation. */
378
+ dueAt?: Date;
379
+ /**
380
+ * Set when the invocation finished executing and parked. A handoff is
381
+ * recorded before the remaining steps run, so until this is set a
382
+ * completion has nothing settled to settle into; it is asked to retry.
383
+ */
384
+ parkedAt?: Date;
385
+ /** Set with the overdue sweep verdict; does not prove execution parked. */
386
+ overdueAt?: Date;
383
387
  }
384
388
  /**
385
389
  * What an external system reports when it finishes work the host accepted.
@@ -389,109 +393,180 @@ interface PendingExternalCompletion {
389
393
  * refused, because completing the wrong invocation is worse than dropping a
390
394
  * callback.
391
395
  */
392
- interface ExternalCompletion {
393
- externalReference: string;
394
- outcome: "completed" | "failed";
395
- /** Merged over the handler's result on completion. */
396
- result?: Record<string, unknown>;
397
- error?: string;
398
- provider?: string;
399
- evidenceReferences?: EvidencePacketReference[];
400
- observedAt: Date | string;
401
- }
402
- interface RecordedExternalCompletion extends ExternalCompletion {
403
- recordedAt: Date;
404
- /**
405
- * Canonical digest of provider, reference, outcome, result, error, and
406
- * evidence. A repeat with the same digest is the same news; a repeat with
407
- * the same outcome and a different digest is changed evidence, and is a
408
- * contradiction like a flipped outcome. Observation time is left out,
409
- * since a redelivery legitimately carries a new one.
410
- */
411
- digest: string;
412
- }
413
- interface ReconcileOverdueCompletionsInput {
414
- tenantId?: string;
415
- spaceId?: string;
416
- limit?: number;
417
- now?: Date;
418
- }
419
- type AdapterInvocationStatus = "running" | "succeeded" | "failed" | "ambiguous";
420
- interface AdapterReconciliationOutcome {
421
- kind: "adapter_outcome_ambiguous";
422
- adapterType: string;
423
- operation: string;
424
- vendor: string;
425
- adapterInvocationId: string;
426
- reason?: string;
427
- /** Opaque, non-secret reference to external operation state for reconciliation. */
428
- externalReference?: string;
429
- message: string;
430
- }
431
- interface AdapterInvocationRecord {
432
- id: string;
433
- actionInvocationId: string;
434
- tenantId: string;
435
- spaceId: string;
436
- adapterType: string;
437
- operation: string;
438
- vendor: string;
439
- status: AdapterInvocationStatus;
440
- input: Record<string, unknown>;
441
- output?: Record<string, unknown>;
442
- error?: string;
443
- attempt: number;
444
- createdAt: Date;
445
- updatedAt: Date;
446
- }
447
- interface CreateActionInvocationInput extends Omit<ActionInvocationRecord, "createdAt" | "updatedAt" | "attemptCount" | "leaseOwner" | "leaseExpiresAt" | "leaseToken"> {
396
+ export interface ExternalCompletion {
397
+ externalReference: string;
398
+ outcome: "completed" | "failed";
399
+ /** Merged over the handler's result on completion. */
400
+ result?: Record<string, unknown>;
401
+ error?: string;
402
+ provider?: string;
403
+ evidenceReferences?: EvidencePacketReference[];
404
+ observedAt: Date | string;
405
+ }
406
+ export interface RecordedExternalCompletion extends ExternalCompletion {
407
+ recordedAt: Date;
408
+ /**
409
+ * Canonical digest of provider, reference, outcome, result, error, and
410
+ * evidence. A repeat with the same digest is the same news; a repeat with
411
+ * the same outcome and a different digest is changed evidence, and is a
412
+ * contradiction like a flipped outcome. Observation time is left out,
413
+ * since a redelivery legitimately carries a new one.
414
+ */
415
+ digest: string;
416
+ }
417
+ export interface ReconcileOverdueCompletionsInput {
418
+ tenantId?: string;
419
+ spaceId?: string;
420
+ limit?: number;
421
+ now?: Date;
422
+ }
423
+ export type AdapterInvocationStatus = "running" | "succeeded" | "failed" | "ambiguous";
424
+ export interface AdapterReconciliationOutcome {
425
+ kind: "adapter_outcome_ambiguous";
426
+ adapterType: string;
427
+ operation: string;
428
+ vendor: string;
429
+ adapterInvocationId: string;
430
+ reason?: string;
431
+ /** Opaque, non-secret reference to external operation state for reconciliation. */
432
+ externalReference?: string;
433
+ message: string;
434
+ }
435
+ export interface AdapterInvocationRecord {
436
+ id: string;
437
+ actionInvocationId: string;
438
+ tenantId: string;
439
+ spaceId: string;
440
+ adapterType: string;
441
+ operation: string;
442
+ vendor: string;
443
+ status: AdapterInvocationStatus;
444
+ input: Record<string, unknown>;
445
+ output?: Record<string, unknown>;
446
+ error?: string;
447
+ /** Redacted checkpoint for replaying an ambiguous settlement without another provider call. */
448
+ reconciliation?: AdapterReconciliationOutcome & {
449
+ /** Original event subject, stored only for settlement recovery. */
450
+ adapterEventSubject?: {
451
+ subjectType: string;
452
+ subjectId: string;
453
+ };
454
+ };
455
+ attempt: number;
456
+ createdAt: Date;
457
+ updatedAt: Date;
448
458
  }
459
+ export interface CreateActionInvocationInput extends Omit<ActionInvocationRecord, "createdAt" | "updatedAt" | "attemptCount" | "leaseOwner" | "leaseExpiresAt" | "leaseToken"> {}
449
460
  /** Scope of an adapter checkpoint within its owning action invocation. */
450
- interface AdapterInvocationScope {
451
- tenantId: string;
452
- spaceId: string;
461
+ export interface AdapterInvocationScope {
462
+ tenantId: string;
463
+ spaceId: string;
464
+ actionInvocationId: string;
465
+ }
466
+ /** Authority for an adapter mutation; verdict evidence uses exact status/error equality. */
467
+ export type AdapterInvocationWriteCondition = {
468
+ kind: "lease";
469
+ leaseOwner: string;
470
+ leaseToken: number;
471
+ } | {
472
+ kind: "verdict";
473
+ status: Exclude<ActionInvocationRecord["status"], "pending" | "running" | "waiting_for_approval">;
474
+ error?: string;
475
+ /** Absent requires no recorded completion; a digest requires that same completion. */
476
+ externalCompletionDigest?: string;
477
+ /** Captured handoff row; other adapter rows need only status/error and row-status fencing.
478
+ * Omit to retain the conservative completion check for adapter writes. Parent enrichment
479
+ * compares the completion digest regardless of this member. */
480
+ completionAdapterInvocationId?: string;
481
+ };
482
+ /** Conditionally enrich this execution's settled parent without changing its status. */
483
+ export interface UpdateSettledActionInvocationInput {
484
+ id: string;
485
+ tenantId: string;
486
+ spaceId: string;
487
+ condition: Extract<AdapterInvocationWriteCondition, {
488
+ kind: "verdict";
489
+ }>;
490
+ patch: Pick<ActionInvocationPatch, "error" | "adapterReconciliation">;
491
+ }
492
+ export type AdapterInvocationPatch = Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt" | "reconciliation">>;
493
+ export interface AdapterInvocationWriteInput {
494
+ scope: AdapterInvocationScope;
495
+ condition: AdapterInvocationWriteCondition;
496
+ /** Compare against the current row, inside the same atomic operation. */
497
+ expectedStatuses?: readonly AdapterInvocationRecord["status"][];
498
+ mutation: {
499
+ kind: "create";
500
+ record: AdapterInvocationRecord;
501
+ } | {
502
+ kind: "update";
503
+ id: string;
504
+ patch: AdapterInvocationPatch;
505
+ };
506
+ }
507
+ export interface PlatformHostStore<TDb> {
508
+ readonly db: TDb;
509
+ /**
510
+ * Run against the store's domain handle. This base seam does not promise a
511
+ * database transaction. Use `transactionWithEvents` when domain writes,
512
+ * canonical events, and invocation state must commit atomically.
513
+ */
514
+ transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
515
+ createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
516
+ getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
517
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
518
+ appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
519
+ createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
520
+ /**
521
+ * Optional atomic parent-authorized adapter create/update. Lease authority
522
+ * requires a running parent with the supplied owner/token; verdict authority
523
+ * requires the exact parent status/error (undefined error equals no error).
524
+ * The completion digest guards the captured completionAdapterInvocationId;
525
+ * other rows retain status/error and expectedStatuses checks. Without a captured
526
+ * row ID the digest check applies conservatively to the mutation too.
527
+ * Match tenant, space and invocation on both rows, locking the parent before
528
+ * the adapter. Return false for a predicate miss, missing parent/row, or a
529
+ * duplicate create. Updates cannot move succeeded/ambiguous to running/failed,
530
+ * even when expectedStatuses is omitted. Creation must match input.scope.
531
+ * Transaction implementations recheck predicates at commit or retain locks.
532
+ * Host uses unchecked legacy writes when this capability is absent: custom
533
+ * stores without it do not protect adapter rows against stale workers.
534
+ */
535
+ writeAdapterInvocation?(input: AdapterInvocationWriteInput): Promise<boolean>;
536
+ /**
537
+ * Atomic scoped status/error/completion compare-and-set for post-verdict enrichment.
538
+ * Expected alongside writeAdapterInvocation. When absent, Host skips only parent
539
+ * enrichment and still attempts the remaining evidence writes. Refusal is telemetry;
540
+ * thrown errors join the evidence collector.
541
+ */
542
+ updateSettledActionInvocation?(input: UpdateSettledActionInvocationInput): Promise<boolean>;
543
+ /**
544
+ * Host supplies scope from its store-loaded invocation at adapter call sites.
545
+ * When supplied, stores must match tenant, space, and action invocation:
546
+ * an out-of-scope record returns undefined. Optional for compatibility with
547
+ * existing custom stores and direct callers; tenantIsolationChecks tests
548
+ * scoped read and write conformance.
549
+ */
550
+ getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
551
+ /**
552
+ * Match all three scope fields when supplied, changing nothing outside it
553
+ * (a not-found error is permitted). Host supplies scope as described above;
554
+ * optional only for compatibility with existing stores and direct callers.
555
+ */
556
+ updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt" | "reconciliation">>, scope?: AdapterInvocationScope): Promise<void>;
557
+ appendEvent(event: AssetEventEnvelope): Promise<void>;
558
+ nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
559
+ /**
560
+ * Return the state and invocation writer of the same event selected by
561
+ * getEntityState, scoped to this subject and tenant/space. Return undefined
562
+ * when that event or its invocation provenance is unavailable. Transaction
563
+ * implementations include pending events visible to getEntityState.
564
+ */
565
+ getEntityStateSource?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
566
+ state: string;
453
567
  actionInvocationId: string;
454
- }
455
- interface PlatformHostStore<TDb> {
456
- readonly db: TDb;
457
- /**
458
- * Run against the store's domain handle. This base seam does not promise a
459
- * database transaction. Use `transactionWithEvents` when domain writes,
460
- * canonical events, and invocation state must commit atomically.
461
- */
462
- transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
463
- createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
464
- getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
465
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
466
- appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
467
- createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
468
- /**
469
- * Host supplies scope from its store-loaded invocation at adapter call sites.
470
- * When supplied, stores must match tenant, space, and action invocation:
471
- * an out-of-scope record returns undefined. Optional for compatibility with
472
- * existing custom stores and direct callers; tenantIsolationChecks tests
473
- * scoped read and write conformance.
474
- */
475
- getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
476
- /**
477
- * Match all three scope fields when supplied, changing nothing outside it
478
- * (a not-found error is permitted). Host supplies scope as described above;
479
- * optional only for compatibility with existing stores and direct callers.
480
- */
481
- updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt">>, scope?: AdapterInvocationScope): Promise<void>;
482
- appendEvent(event: AssetEventEnvelope): Promise<void>;
483
- nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
484
- /**
485
- * Return the state and invocation writer of the same event selected by
486
- * getEntityState, scoped to this subject and tenant/space. Return undefined
487
- * when that event or its invocation provenance is unavailable. Transaction
488
- * implementations include pending events visible to getEntityState.
489
- */
490
- getEntityStateSource?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
491
- state: string;
492
- actionInvocationId: string;
493
- } | undefined>;
494
- getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
568
+ } | undefined>;
569
+ getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
495
570
  }
496
571
  /**
497
572
  * Transaction-scoped Host operations used to commit domain writes and their
@@ -501,154 +576,159 @@ interface PlatformHostStore<TDb> {
501
576
  * lifecycle method on this object. Implementations must roll the whole unit
502
577
  * back when `run` throws.
503
578
  */
504
- interface PlatformHostMutationTransaction<TDb> {
505
- readonly db: TDb;
506
- /**
507
- * Read and lock an invocation until this transaction completes.
508
- * Required by serialized saga parent lifecycle transitions.
509
- */
510
- getActionInvocationForUpdate?(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
511
- /**
512
- * Read one event by its stable identity inside the transaction.
513
- * Required by serialized saga parent lifecycle transitions.
514
- */
515
- getEvent?(id: string, tenantId: string, spaceId: string): Promise<AssetEventEnvelope | undefined>;
516
- appendEvent(event: AssetEventEnvelope): Promise<void>;
517
- appendEventWithOutbox?(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
518
- nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
519
- listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
520
- /**
521
- * Return the state and invocation writer of the same event selected by
522
- * getEntityState, scoped to this subject and tenant/space. Return undefined
523
- * when that event or its invocation provenance is unavailable. Transaction
524
- * implementations include pending events visible to getEntityState.
525
- */
526
- getEntityStateSource?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
527
- state: string;
528
- actionInvocationId: string;
529
- } | undefined>;
530
- getEntityState?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
531
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
532
- updateLeasedActionInvocation?(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
533
- /**
534
- * Update an adapter row in this transaction, with the same optional
535
- * tenant/space/invocation scope semantics as the store method. Host uses
536
- * this to commit degraded adapter evidence and its terminal verdict together.
537
- * Omit this member if the adapter row cannot share this transaction.
538
- */
539
- updateAdapterInvocation?: PlatformHostStore<TDb>["updateAdapterInvocation"];
540
- /**
541
- * Append governance reconciliation evidence in this transaction. Host uses
542
- * this for degraded finalization when adapter output is withheld. Omit this
543
- * member if governance evidence cannot share the event/verdict transaction.
544
- */
545
- appendExternalReconciliation?: GovernancePlatformHostStore<TDb>["appendExternalReconciliation"];
546
- }
547
- type OutboxStatus = "pending" | "published" | "dead_letter";
548
- type EventPayloadClassification = "public" | "internal" | "confidential" | "restricted";
549
- interface OutboxEventMetadata {
550
- producerModuleVersion: string;
551
- payloadClassification: EventPayloadClassification;
552
- traceContext?: Record<string, string>;
553
- includeProvenance?: boolean;
554
- /**
555
- * Only `true` puts the event's `actorId` and `actorType` on the outbox envelope. Absent or any
556
- * other value leaves them off, and the outbox record says the actor was `suppressed`.
557
- */
558
- includeActor?: boolean;
579
+ export interface PlatformHostMutationTransaction<TDb> {
580
+ readonly db: TDb;
581
+ /**
582
+ * Read and lock an invocation until this transaction completes.
583
+ * Required by serialized saga parent lifecycle transitions.
584
+ */
585
+ getActionInvocationForUpdate?(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
586
+ /**
587
+ * Read one event by its stable identity inside the transaction.
588
+ * Required by serialized saga parent lifecycle transitions.
589
+ */
590
+ getEvent?(id: string, tenantId: string, spaceId: string): Promise<AssetEventEnvelope | undefined>;
591
+ appendEvent(event: AssetEventEnvelope): Promise<void>;
592
+ appendEventWithOutbox?(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
593
+ nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
594
+ listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
595
+ /**
596
+ * Return the state and invocation writer of the same event selected by
597
+ * getEntityState, scoped to this subject and tenant/space. Return undefined
598
+ * when that event or its invocation provenance is unavailable. Transaction
599
+ * implementations include pending events visible to getEntityState.
600
+ */
601
+ getEntityStateSource?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
602
+ state: string;
603
+ actionInvocationId: string;
604
+ } | undefined>;
605
+ getEntityState?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
606
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
607
+ updateLeasedActionInvocation?(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
608
+ /**
609
+ * Update an adapter row in this transaction, with the same optional
610
+ * tenant/space/invocation scope semantics as the store method. Host uses
611
+ * this to commit degraded adapter evidence and its terminal verdict together.
612
+ * Omit this member if the adapter row cannot share this transaction.
613
+ */
614
+ updateAdapterInvocation?: PlatformHostStore<TDb>["updateAdapterInvocation"];
615
+ /** Same conditional write, sharing this transaction and its rollback. */
616
+ writeAdapterInvocation?: PlatformHostStore<TDb>["writeAdapterInvocation"];
617
+ /**
618
+ * Append governance reconciliation evidence in this transaction. Host uses
619
+ * this for overdue sweeps and degraded finalization when adapter output is
620
+ * withheld or a handoff is refused. Implement it alongside the transaction's
621
+ * invocation row lock; an outer-store append while that lock is held can
622
+ * block on a foreign key referencing the invocation. Omit this member if
623
+ * governance evidence cannot share the event/verdict transaction.
624
+ */
625
+ appendExternalReconciliation?: GovernancePlatformHostStore<TDb>["appendExternalReconciliation"];
626
+ }
627
+ export type OutboxStatus = "pending" | "published" | "dead_letter";
628
+ export type EventPayloadClassification = "public" | "internal" | "confidential" | "restricted";
629
+ export interface OutboxEventMetadata {
630
+ producerModuleVersion: string;
631
+ payloadClassification: EventPayloadClassification;
632
+ traceContext?: Record<string, string>;
633
+ includeProvenance?: boolean;
634
+ /**
635
+ * Only `true` puts the event's `actorId` and `actorType` on the outbox envelope. Absent or any
636
+ * other value leaves them off, and the outbox record says the actor was `suppressed`.
637
+ */
638
+ includeActor?: boolean;
559
639
  }
560
640
  /**
561
641
  * Whether Host put actor identity on an outbox record's envelope, decided by `includeActor` when
562
642
  * the record was written. A record has no value when it predates the decision (`legacy`).
563
643
  */
564
- type OutboxActorDisclosure = "included" | "suppressed";
644
+ export type OutboxActorDisclosure = "included" | "suppressed";
565
645
  /**
566
646
  * What the relay tells a publisher about an envelope's actor identity: the record's
567
647
  * `OutboxActorDisclosure`, or `legacy` for a record with none. The memory and PostgreSQL stores
568
648
  * hydrate actor identity only for `included` records, so their legacy and suppressed envelopes carry
569
649
  * none; a consumer that needs it reads the canonical event.
570
650
  */
571
- type EnterpriseEventActorDisclosure = OutboxActorDisclosure | "legacy";
572
- interface EnterpriseEventEnvelope {
573
- eventId: string;
574
- eventType: string;
575
- eventSchemaVersion: number;
576
- tenantId: string;
577
- spaceId: string;
578
- subjectType: string;
579
- subjectId: string;
580
- sequence: number;
581
- actionInvocationId?: string;
582
- correlationId: string;
583
- causationId?: string;
584
- /** Present only when `includeActor` opted this event in; the key is absent otherwise. */
585
- actorId?: string;
586
- /** Present only when `includeActor` opted this event in; the key is absent otherwise. */
587
- actorType?: string;
588
- occurredAt: Date;
589
- recordedAt: Date;
590
- producerModuleVersion: string;
591
- payloadClassification: EventPayloadClassification;
592
- traceContext?: Record<string, string>;
593
- provenance?: {
594
- source: InvocationSource;
595
- auditAttributes?: NamespacedAttributes;
596
- };
597
- /** Present only for events an action declaring provisional consistency emitted. */
598
- consistency?: "authoritative-now" | "provisional-until-reconciled";
599
- payload: unknown;
600
- }
601
- interface OutboxRecord {
651
+ export type EnterpriseEventActorDisclosure = OutboxActorDisclosure | "legacy";
652
+ export interface EnterpriseEventEnvelope {
653
+ eventId: string;
654
+ eventType: string;
655
+ eventSchemaVersion: number;
656
+ tenantId: string;
657
+ spaceId: string;
658
+ subjectType: string;
659
+ subjectId: string;
660
+ sequence: number;
661
+ actionInvocationId?: string;
662
+ correlationId: string;
663
+ causationId?: string;
664
+ /** Present only when `includeActor` opted this event in; the key is absent otherwise. */
665
+ actorId?: string;
666
+ /** Present only when `includeActor` opted this event in; the key is absent otherwise. */
667
+ actorType?: string;
668
+ occurredAt: Date;
669
+ recordedAt: Date;
670
+ producerModuleVersion: string;
671
+ payloadClassification: EventPayloadClassification;
672
+ traceContext?: Record<string, string>;
673
+ provenance?: {
674
+ source: InvocationSource;
675
+ auditAttributes?: NamespacedAttributes;
676
+ };
677
+ /** Present only for events an action declaring provisional consistency emitted. */
678
+ consistency?: "authoritative-now" | "provisional-until-reconciled";
679
+ payload: unknown;
680
+ }
681
+ export interface OutboxRecord {
682
+ id: string;
683
+ tenantId: string;
684
+ spaceId: string;
685
+ event: EnterpriseEventEnvelope;
686
+ /** Absent for a record written before Host recorded the `includeActor` decision. */
687
+ actorDisclosure?: OutboxActorDisclosure;
688
+ status: OutboxStatus;
689
+ attemptCount: number;
690
+ availableAt: Date;
691
+ leaseOwner?: string;
692
+ leaseExpiresAt?: Date;
693
+ leaseToken?: number;
694
+ lastError?: string;
695
+ createdAt: Date;
696
+ publishedAt?: Date;
697
+ }
698
+ export interface ClaimOutboxInput {
699
+ workerId: string;
700
+ leaseDurationMs: number;
701
+ limit?: number;
702
+ tenantId?: string;
703
+ spaceId?: string;
704
+ now?: Date;
705
+ }
706
+ export interface OutboxPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
707
+ /** True only when transactionWithEvents supplies appendEventWithOutbox in the same unit of work. */
708
+ readonly transactionalOutbox?: boolean;
709
+ appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
710
+ claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
711
+ markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
712
+ markOutboxFailed(input: {
602
713
  id: string;
603
- tenantId: string;
604
- spaceId: string;
605
- event: EnterpriseEventEnvelope;
606
- /** Absent for a record written before Host recorded the `includeActor` decision. */
607
- actorDisclosure?: OutboxActorDisclosure;
608
- status: OutboxStatus;
609
- attemptCount: number;
610
- availableAt: Date;
611
- leaseOwner?: string;
612
- leaseExpiresAt?: Date;
714
+ workerId: string;
613
715
  leaseToken?: number;
614
- lastError?: string;
615
- createdAt: Date;
616
- publishedAt?: Date;
617
- }
618
- interface ClaimOutboxInput {
716
+ error: string;
717
+ availableAt: Date;
718
+ deadLetter: boolean;
719
+ }): Promise<void>;
720
+ renewOutboxLease(input: {
721
+ id: string;
619
722
  workerId: string;
723
+ leaseToken: number;
620
724
  leaseDurationMs: number;
621
- limit?: number;
725
+ now?: Date;
726
+ }): Promise<boolean>;
727
+ listOutbox(input?: {
622
728
  tenantId?: string;
623
729
  spaceId?: string;
624
- now?: Date;
625
- }
626
- interface OutboxPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
627
- /** True only when transactionWithEvents supplies appendEventWithOutbox in the same unit of work. */
628
- readonly transactionalOutbox?: boolean;
629
- appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
630
- claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
631
- markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
632
- markOutboxFailed(input: {
633
- id: string;
634
- workerId: string;
635
- leaseToken?: number;
636
- error: string;
637
- availableAt: Date;
638
- deadLetter: boolean;
639
- }): Promise<void>;
640
- renewOutboxLease(input: {
641
- id: string;
642
- workerId: string;
643
- leaseToken: number;
644
- leaseDurationMs: number;
645
- now?: Date;
646
- }): Promise<boolean>;
647
- listOutbox(input?: {
648
- tenantId?: string;
649
- spaceId?: string;
650
- statuses?: OutboxStatus[];
651
- }): Promise<OutboxRecord[]>;
730
+ statuses?: OutboxStatus[];
731
+ }): Promise<OutboxRecord[]>;
652
732
  }
653
733
  /**
654
734
  * Append-only evidence of one operator requeue of a dead-lettered outbox
@@ -656,42 +736,42 @@ interface OutboxPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
656
736
  * so the failure that exhausted the record stays readable after its attempt
657
737
  * budget is reset.
658
738
  */
659
- interface OutboxRequeueRecord {
660
- id: string;
661
- outboxId: string;
662
- tenantId: string;
663
- spaceId: string;
664
- eventId: string;
665
- actorId: string;
666
- actorType: ActorType;
667
- /** Operator-supplied justification, persisted as audit evidence. Must not carry secrets. */
668
- reason: string;
669
- requeuedAt: Date;
670
- /** When the requeued record became claimable again. */
671
- availableAt: Date;
672
- priorAttemptCount: number;
673
- priorLastError?: string;
674
- priorAvailableAt: Date;
675
- priorLeaseToken: number;
676
- }
677
- interface RequeueOutboxDeadLetterStoreInput {
678
- id: string;
679
- tenantId: string;
680
- spaceId: string;
681
- /** Identity of the evidence row written with the transition. */
682
- requeueId: string;
683
- actorId: string;
684
- actorType: ActorType;
685
- reason: string;
686
- requeuedAt: Date;
687
- availableAt: Date;
688
- /**
689
- * The lease token of the dead letter the caller read and authorized. Every
690
- * claim increments the token and a requeue never lowers it, so a record
691
- * that was requeued, claimed and dead-lettered again carries a higher token
692
- * than the one observed, and the requeue is refused as `stale`.
693
- */
694
- expectedLeaseToken: number;
739
+ export interface OutboxRequeueRecord {
740
+ id: string;
741
+ outboxId: string;
742
+ tenantId: string;
743
+ spaceId: string;
744
+ eventId: string;
745
+ actorId: string;
746
+ actorType: ActorType;
747
+ /** Operator-supplied justification, persisted as audit evidence. Must not carry secrets. */
748
+ reason: string;
749
+ requeuedAt: Date;
750
+ /** When the requeued record became claimable again. */
751
+ availableAt: Date;
752
+ priorAttemptCount: number;
753
+ priorLastError?: string;
754
+ priorAvailableAt: Date;
755
+ priorLeaseToken: number;
756
+ }
757
+ export interface RequeueOutboxDeadLetterStoreInput {
758
+ id: string;
759
+ tenantId: string;
760
+ spaceId: string;
761
+ /** Identity of the evidence row written with the transition. */
762
+ requeueId: string;
763
+ actorId: string;
764
+ actorType: ActorType;
765
+ reason: string;
766
+ requeuedAt: Date;
767
+ availableAt: Date;
768
+ /**
769
+ * The lease token of the dead letter the caller read and authorized. Every
770
+ * claim increments the token and a requeue never lowers it, so a record
771
+ * that was requeued, claimed and dead-lettered again carries a higher token
772
+ * than the one observed, and the requeue is refused as `stale`.
773
+ */
774
+ expectedLeaseToken: number;
695
775
  }
696
776
  /**
697
777
  * `not_found`: no record with this id in the tenant and space, including a
@@ -700,74 +780,74 @@ interface RequeueOutboxDeadLetterStoreInput {
700
780
  * requeue won the compare-and-set. `stale`: the record is a dead letter
701
781
  * again, but not the one the caller observed; read and authorize it afresh.
702
782
  */
703
- type OutboxRequeueRefusal = "not_found" | "not_dead_letter" | "stale";
704
- type RequeueOutboxDeadLetterStoreResult = {
705
- applied: true;
706
- record: OutboxRecord;
707
- requeue: OutboxRequeueRecord;
783
+ export type OutboxRequeueRefusal = "not_found" | "not_dead_letter" | "stale";
784
+ export type RequeueOutboxDeadLetterStoreResult = {
785
+ applied: true;
786
+ record: OutboxRecord;
787
+ requeue: OutboxRequeueRecord;
708
788
  } | {
709
- applied: false;
710
- refusal: OutboxRequeueRefusal;
711
- currentStatus?: OutboxStatus;
789
+ applied: false;
790
+ refusal: OutboxRequeueRefusal;
791
+ currentStatus?: OutboxStatus;
712
792
  };
713
793
  /**
714
794
  * Optional outbox capability that moves a dead-lettered record back to
715
795
  * pending. Kept apart from `OutboxPlatformHostStore` so a custom outbox store
716
796
  * that predates it still satisfies that interface.
717
797
  */
718
- interface OutboxRequeuePlatformHostStore<TDb> extends OutboxPlatformHostStore<TDb> {
719
- getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
720
- /**
721
- * Compare-and-set from `dead_letter` at `expectedLeaseToken` to `pending`
722
- * within the tenant and space: resets `attemptCount` to 0, sets
723
- * `availableAt`, clears any lease owner while keeping the lease token,
724
- * keeps `lastError`, and appends one `OutboxRequeueRecord` in the same
725
- * atomic step. A record in any other state, at another lease token, or in
726
- * another scope is refused and nothing is written. The returned requeue
727
- * evidence shares nothing with stored history. The returned outbox record
728
- * has its own Date fields; its event payload and provenance are shallow.
729
- */
730
- requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
731
- /** Requeue evidence for a scope, oldest first; `outboxId` narrows it to one record. */
732
- listOutboxRequeues(input: {
733
- tenantId: string;
734
- spaceId: string;
735
- outboxId?: string;
736
- }): Promise<OutboxRequeueRecord[]>;
737
- }
738
- interface RequeueOutboxDeadLetterInput {
739
- outboxId: string;
798
+ export interface OutboxRequeuePlatformHostStore<TDb> extends OutboxPlatformHostStore<TDb> {
799
+ getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
800
+ /**
801
+ * Compare-and-set from `dead_letter` at `expectedLeaseToken` to `pending`
802
+ * within the tenant and space: resets `attemptCount` to 0, sets
803
+ * `availableAt`, clears any lease owner while keeping the lease token,
804
+ * keeps `lastError`, and appends one `OutboxRequeueRecord` in the same
805
+ * atomic step. A record in any other state, at another lease token, or in
806
+ * another scope is refused and nothing is written. The returned requeue
807
+ * evidence shares nothing with stored history. The returned outbox record
808
+ * has its own Date fields; its event payload and provenance are shallow.
809
+ */
810
+ requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
811
+ /** Requeue evidence for a scope, oldest first; `outboxId` narrows it to one record. */
812
+ listOutboxRequeues(input: {
740
813
  tenantId: string;
741
814
  spaceId: string;
742
- /** Trusted operator identity from the caller's authenticated session, never from request input. */
743
- actorId: string;
744
- actorType: ActorType;
745
- /** Required justification, at most 1,000 characters, persisted as audit evidence. */
746
- reason: string;
747
- /** When the record becomes claimable again; defaults to the host clock. */
748
- availableAt?: Date;
749
- }
750
- type RequeueOutboxDeadLetterRefusal = OutboxRequeueRefusal | "not_authorized";
751
- type RequeueOutboxDeadLetterResult = {
752
- status: "requeued";
753
- record: OutboxRecord;
754
- requeue: OutboxRequeueRecord;
815
+ outboxId?: string;
816
+ }): Promise<OutboxRequeueRecord[]>;
817
+ }
818
+ export interface RequeueOutboxDeadLetterInput {
819
+ outboxId: string;
820
+ tenantId: string;
821
+ spaceId: string;
822
+ /** Trusted operator identity from the caller's authenticated session, never from request input. */
823
+ actorId: string;
824
+ actorType: ActorType;
825
+ /** Required justification, at most 1,000 characters, persisted as audit evidence. */
826
+ reason: string;
827
+ /** When the record becomes claimable again; defaults to the host clock. */
828
+ availableAt?: Date;
829
+ }
830
+ export type RequeueOutboxDeadLetterRefusal = OutboxRequeueRefusal | "not_authorized";
831
+ export type RequeueOutboxDeadLetterResult = {
832
+ status: "requeued";
833
+ record: OutboxRecord;
834
+ requeue: OutboxRequeueRecord;
755
835
  } | {
756
- status: "refused";
757
- refusal: RequeueOutboxDeadLetterRefusal;
758
- /** Present for `not_dead_letter` and `stale`: the state the record was found in. */
759
- currentStatus?: OutboxStatus;
760
- message: string;
836
+ status: "refused";
837
+ refusal: RequeueOutboxDeadLetterRefusal;
838
+ /** Present for `not_dead_letter` and `stale`: the state the record was found in. */
839
+ currentStatus?: OutboxStatus;
840
+ message: string;
761
841
  };
762
842
  /** Facts given to `authorizeOutboxRequeue`. `record` is absent when no record with this id exists in the scope. */
763
- interface OutboxRequeueAuthorizationInput {
764
- tenantId: string;
765
- spaceId: string;
766
- actorId: string;
767
- actorType: ActorType;
768
- outboxId: string;
769
- reason: string;
770
- record?: Pick<OutboxRecord["event"], "eventId" | "eventType" | "payloadClassification"> & Pick<OutboxRecord, "status" | "attemptCount">;
843
+ export interface OutboxRequeueAuthorizationInput {
844
+ tenantId: string;
845
+ spaceId: string;
846
+ actorId: string;
847
+ actorType: ActorType;
848
+ outboxId: string;
849
+ reason: string;
850
+ record?: Pick<OutboxRecord["event"], "eventId" | "eventType" | "payloadClassification"> & Pick<OutboxRecord, "status" | "attemptCount">;
771
851
  }
772
852
  /**
773
853
  * Optional production capability for atomic domain/event persistence.
@@ -776,60 +856,60 @@ interface OutboxRequeueAuthorizationInput {
776
856
  * not implement it retain the legacy transaction boundary for compatibility,
777
857
  * but cannot claim atomic domain-write/event persistence.
778
858
  */
779
- interface AtomicMutationPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
780
- transactionWithEvents<TResult>(run: (transaction: PlatformHostMutationTransaction<TDb>) => Promise<TResult>): Promise<TResult>;
781
- }
782
- interface BeginApprovalDecisionInput {
783
- actionInvocationId: string;
784
- tenantId: string;
785
- spaceId: string;
786
- decision: PersistedActionApprovalDecision;
787
- leaseOwner: string;
788
- leaseDurationMs: number;
789
- now: Date;
790
- }
791
- interface ApprovalDecisionTransitionResult {
792
- applied: boolean;
793
- invocation?: ActionInvocationRecord;
859
+ export interface AtomicMutationPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
860
+ transactionWithEvents<TResult>(run: (transaction: PlatformHostMutationTransaction<TDb>) => Promise<TResult>): Promise<TResult>;
861
+ }
862
+ export interface BeginApprovalDecisionInput {
863
+ actionInvocationId: string;
864
+ tenantId: string;
865
+ spaceId: string;
866
+ decision: PersistedActionApprovalDecision;
867
+ leaseOwner: string;
868
+ leaseDurationMs: number;
869
+ now: Date;
870
+ }
871
+ export interface ApprovalDecisionTransitionResult {
872
+ applied: boolean;
873
+ invocation?: ActionInvocationRecord;
794
874
  }
795
875
  /** Optional store capability required only when agent HITL or approval resume is used. */
796
- interface ApprovalPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
797
- recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
798
- beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
876
+ export interface ApprovalPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
877
+ recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
878
+ beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
799
879
  }
800
880
  /** Optional durable capabilities used when external-governance enrichment is configured. */
801
- interface GovernancePlatformHostStore<TDb> extends PlatformHostStore<TDb> {
802
- recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: {
803
- footprint: MutationFootprint;
804
- executionPrincipal: ExecutionPrincipal;
805
- }): Promise<ActionInvocationRecord>;
806
- appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
807
- listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
808
- updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationStatus, evidenceReferences?: PolicyObligation["evidenceReferences"]): Promise<void>;
809
- appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
810
- listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
811
- appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
812
- }
813
- interface ListActionInvocationsInput {
814
- tenantId?: string;
815
- spaceId?: string;
816
- statuses?: readonly ActionStatus[];
817
- updatedBefore?: Date;
818
- /** Only invocations holding a pending external completion. */
819
- awaitingCompletion?: boolean;
820
- /** Only pending completions due at or before this instant. Implies `awaitingCompletion`. */
821
- completionDueBefore?: Date;
822
- /** Only invocations no worker holds a lease on. */
823
- unleased?: boolean;
824
- limit?: number;
825
- }
826
- interface ClaimActionInvocationsInput {
827
- workerId: string;
828
- leaseDurationMs: number;
829
- limit?: number;
830
- tenantId?: string;
831
- spaceId?: string;
832
- now?: Date;
881
+ export interface GovernancePlatformHostStore<TDb> extends PlatformHostStore<TDb> {
882
+ recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: {
883
+ footprint: MutationFootprint;
884
+ executionPrincipal: ExecutionPrincipal;
885
+ }): Promise<ActionInvocationRecord>;
886
+ appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
887
+ listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
888
+ updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationStatus, evidenceReferences?: PolicyObligation["evidenceReferences"]): Promise<void>;
889
+ appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
890
+ listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
891
+ appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
892
+ }
893
+ export interface ListActionInvocationsInput {
894
+ tenantId?: string;
895
+ spaceId?: string;
896
+ statuses?: readonly ActionStatus[];
897
+ updatedBefore?: Date;
898
+ /** Only invocations holding a pending external completion. */
899
+ awaitingCompletion?: boolean;
900
+ /** Only pending completions due at or before this instant. Implies `awaitingCompletion`. */
901
+ completionDueBefore?: Date;
902
+ /** Only invocations no worker holds a lease on. */
903
+ unleased?: boolean;
904
+ limit?: number;
905
+ }
906
+ export interface ClaimActionInvocationsInput {
907
+ workerId: string;
908
+ leaseDurationMs: number;
909
+ limit?: number;
910
+ tenantId?: string;
911
+ spaceId?: string;
912
+ now?: Date;
833
913
  }
834
914
  /**
835
915
  * What the host writes back to an invocation.
@@ -844,55 +924,55 @@ interface ClaimActionInvocationsInput {
844
924
  * - `claimActionInvocations` must never claim a running invocation without a
845
925
  * lease, which is what a parked invocation is.
846
926
  */
847
- type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation" | "pendingStateTransition" | "pendingCompletion" | "externalCompletion">>;
848
- interface UpdateLeasedActionInvocationInput {
849
- id: string;
850
- tenantId: string;
851
- spaceId: string;
852
- workerId: string;
853
- leaseToken: number;
854
- patch: ActionInvocationPatch;
855
- }
856
- interface RenewActionInvocationLeaseInput {
857
- id: string;
858
- tenantId: string;
859
- spaceId: string;
860
- workerId: string;
861
- leaseToken: number;
862
- leaseDurationMs: number;
863
- now?: Date;
927
+ export type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation" | "pendingStateTransition" | "pendingCompletion" | "externalCompletion">>;
928
+ export interface UpdateLeasedActionInvocationInput {
929
+ id: string;
930
+ tenantId: string;
931
+ spaceId: string;
932
+ workerId: string;
933
+ leaseToken: number;
934
+ patch: ActionInvocationPatch;
935
+ }
936
+ export interface RenewActionInvocationLeaseInput {
937
+ id: string;
938
+ tenantId: string;
939
+ spaceId: string;
940
+ workerId: string;
941
+ leaseToken: number;
942
+ leaseDurationMs: number;
943
+ now?: Date;
864
944
  }
865
945
  /** Store capabilities required by the durable polling worker and operator tooling. */
866
- interface RecoverablePlatformHostStore<TDb> extends PlatformHostStore<TDb> {
867
- listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
868
- claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
869
- updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
870
- renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
871
- listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
872
- }
873
- interface ActionAuthorizationInput {
874
- actionId: ActionId;
875
- namespace: string;
876
- requiredPermissions: readonly string[];
877
- requiredRoles: readonly string[];
878
- tenantId: string;
879
- spaceId: string;
880
- actorId: string;
881
- actorType: ActorType;
882
- }
883
- type KnownActionExecutionReason = "initial" | "approval_resume" | "recovery" | "offline_replay";
884
- type ActionExecutionReason = KnownActionExecutionReason | (string & {});
946
+ export interface RecoverablePlatformHostStore<TDb> extends PlatformHostStore<TDb> {
947
+ listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
948
+ claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
949
+ updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
950
+ renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
951
+ listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
952
+ }
953
+ export interface ActionAuthorizationInput {
954
+ actionId: ActionId;
955
+ namespace: string;
956
+ requiredPermissions: readonly string[];
957
+ requiredRoles: readonly string[];
958
+ tenantId: string;
959
+ spaceId: string;
960
+ actorId: string;
961
+ actorType: ActorType;
962
+ }
963
+ export type KnownActionExecutionReason = "initial" | "approval_resume" | "recovery" | "offline_replay";
964
+ export type ActionExecutionReason = KnownActionExecutionReason | (string & {});
885
965
  /**
886
966
  * Trusted execution-boundary authorization input.
887
967
  *
888
968
  * Parameters are the schema-parsed durable parameters, never caller-supplied
889
969
  * transient values. `invocation` is the canonical record that will execute.
890
970
  */
891
- interface ActionExecutionAuthorizationInput extends ActionAuthorizationInput {
892
- actionInvocationId: string;
893
- parameters: unknown;
894
- invocation: Readonly<ActionInvocationRecord>;
895
- executionReason: ActionExecutionReason;
971
+ export interface ActionExecutionAuthorizationInput extends ActionAuthorizationInput {
972
+ actionInvocationId: string;
973
+ parameters: unknown;
974
+ invocation: Readonly<ActionInvocationRecord>;
975
+ executionReason: ActionExecutionReason;
896
976
  }
897
977
  /**
898
978
  * Input to `resolvePolicies`. Carries the invocation identity and the
@@ -901,41 +981,41 @@ interface ActionExecutionAuthorizationInput extends ActionAuthorizationInput {
901
981
  * persisted evaluation per invocation and policy, so return the same snapshot
902
982
  * for an `actionInvocationId` on every attempt.
903
983
  */
904
- interface ResolvePoliciesInput extends ActionExecutionAuthorizationInput {
905
- declaredPolicyIds: readonly string[];
906
- }
907
- interface PlatformHostAuthorization {
908
- checkEntitlement(input: ActionAuthorizationInput): Promise<boolean>;
909
- authorize(input: ActionAuthorizationInput): Promise<boolean>;
910
- /**
911
- * Optional final authorization immediately before policies and mutation
912
- * execution. When absent, the Host reuses `authorize` at this boundary.
913
- */
914
- authorizeExecution?(input: ActionExecutionAuthorizationInput): Promise<boolean>;
915
- /** Optional distinct authorization boundary for human/system approval decisions. */
916
- authorizeApproval?(input: ActionAuthorizationInput & {
917
- decision: ActionApprovalDecision;
918
- }): Promise<boolean>;
919
- /**
920
- * Authorization for `requeueOutboxDeadLetter`. There is no action to fall
921
- * back to, so when this is absent every requeue is refused as
922
- * `not_authorized`. A throw propagates and nothing is requeued.
923
- */
924
- authorizeOutboxRequeue?(input: OutboxRequeueAuthorizationInput): Promise<boolean>;
925
- }
926
- interface DispatchActionInput {
927
- actionInvocationId: string;
928
- actionId: ActionId;
929
- tenantId: string;
930
- spaceId: string;
931
- workflowId: string;
932
- }
933
- interface DispatchActionResult {
934
- workflowId: string;
935
- runId?: string;
936
- }
937
- interface PlatformActionDispatcher {
938
- dispatch(input: DispatchActionInput): Promise<DispatchActionResult>;
984
+ export interface ResolvePoliciesInput extends ActionExecutionAuthorizationInput {
985
+ declaredPolicyIds: readonly string[];
986
+ }
987
+ export interface PlatformHostAuthorization {
988
+ checkEntitlement(input: ActionAuthorizationInput): Promise<boolean>;
989
+ authorize(input: ActionAuthorizationInput): Promise<boolean>;
990
+ /**
991
+ * Optional final authorization immediately before policies and mutation
992
+ * execution. When absent, the Host reuses `authorize` at this boundary.
993
+ */
994
+ authorizeExecution?(input: ActionExecutionAuthorizationInput): Promise<boolean>;
995
+ /** Optional distinct authorization boundary for human/system approval decisions. */
996
+ authorizeApproval?(input: ActionAuthorizationInput & {
997
+ decision: ActionApprovalDecision;
998
+ }): Promise<boolean>;
999
+ /**
1000
+ * Authorization for `requeueOutboxDeadLetter`. There is no action to fall
1001
+ * back to, so when this is absent every requeue is refused as
1002
+ * `not_authorized`. A throw propagates and nothing is requeued.
1003
+ */
1004
+ authorizeOutboxRequeue?(input: OutboxRequeueAuthorizationInput): Promise<boolean>;
1005
+ }
1006
+ export interface DispatchActionInput {
1007
+ actionInvocationId: string;
1008
+ actionId: ActionId;
1009
+ tenantId: string;
1010
+ spaceId: string;
1011
+ workflowId: string;
1012
+ }
1013
+ export interface DispatchActionResult {
1014
+ workflowId: string;
1015
+ runId?: string;
1016
+ }
1017
+ export interface PlatformActionDispatcher {
1018
+ dispatch(input: DispatchActionInput): Promise<DispatchActionResult>;
939
1019
  }
940
1020
  /**
941
1021
  * One submission. `submitAction` reads the scalar fields (`actionId`, scope,
@@ -949,452 +1029,474 @@ interface PlatformActionDispatcher {
949
1029
  * as the caller's objects, read where and as often as before (README,
950
1030
  * "Submission snapshot").
951
1031
  */
952
- interface SubmitActionInput {
953
- actionId: ActionId;
954
- parameters: Record<string, unknown>;
955
- tenantId: string;
956
- spaceId: string;
957
- actorId: string;
958
- actorType: ActorType;
959
- correlationId?: string;
960
- causationId?: string;
961
- provenance?: InvocationProvenance;
962
- executionReason?: Extract<KnownActionExecutionReason, "initial" | "offline_replay">;
963
- /** Stable logical command key. Reusing it returns the original invocation; a pending failed dispatch may retry its stable workflow ID. */
964
- idempotencyKey?: string;
965
- /** Opaque, non-secret authorization/admission reference persisted with the invocation. */
966
- authorizationBindingId?: string;
967
- authorizationBinding?: AuthorizationBinding;
968
- }
969
- interface SubmitActionResult {
970
- actionInvocationId: string;
971
- status: ActionStatus;
972
- workflowId: string;
973
- runId?: string;
974
- result?: Record<string, unknown>;
975
- error?: string;
976
- reconciliation?: AuthorizationReconciliationOutcome;
977
- adapterReconciliation?: AdapterReconciliationOutcome;
978
- /** Present while the invocation waits for an external system to complete it. */
979
- pendingCompletion?: PendingExternalCompletion;
980
- /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
981
- consistency?: "authoritative-now" | "provisional-until-reconciled";
982
- hitlRoute?: AgentActionRoute;
983
- hitlRiskTier?: AgentActionRiskTier;
984
- }
985
- interface ExecuteActionResult {
986
- actionInvocationId: string;
987
- status: ActionStatus;
988
- result?: Record<string, unknown>;
989
- error?: string;
990
- reconciliation?: AuthorizationReconciliationOutcome;
991
- adapterReconciliation?: AdapterReconciliationOutcome;
992
- /** Present while the invocation waits for an external system to complete it. */
993
- pendingCompletion?: PendingExternalCompletion;
994
- /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
995
- consistency?: "authoritative-now" | "provisional-until-reconciled";
996
- hitlRoute?: AgentActionRoute;
997
- hitlRiskTier?: AgentActionRiskTier;
998
- }
999
- interface ExecuteInvocationOptions {
1000
- /** Required when executing a row already protected by a worker or approval-resume lease. */
1001
- leaseOwner?: string;
1002
- /** Claim generation paired with leaseOwner; stale generations are rejected. */
1003
- leaseToken?: number;
1004
- }
1005
- interface PlatformActionWorkerOptions<TDb> {
1006
- host: GovernedActionHost;
1007
- store: RecoverablePlatformHostStore<TDb>;
1008
- workerId: string;
1009
- batchSize?: number;
1010
- leaseDurationMs?: number;
1011
- leaseRenewalIntervalMs?: number;
1012
- pollIntervalMs?: number;
1013
- tenantId?: string;
1014
- spaceId?: string;
1015
- signal?: AbortSignal;
1016
- onError?: (error: unknown, invocation?: ActionInvocationRecord) => void;
1017
- telemetry?: PlatformHostTelemetry;
1018
- /**
1019
- * Sweep overdue external handoffs each cycle. Defaults to on. Turn it off
1020
- * for a store without the governance seam, where the sweep would refuse
1021
- * on every cycle, and run the sweep elsewhere.
1022
- */
1023
- sweepOverdueCompletions?: boolean;
1024
- }
1025
- interface PlatformActionWorkerCycleResult {
1026
- claimed: number;
1027
- completed: number;
1028
- failed: number;
1029
- /** Present when claimed agent work was durably parked instead of failing. */
1030
- waitingForApproval?: number;
1031
- /**
1032
- * Present only when > 0: claimed invocations whose execution threw a
1033
- * RetryableExecutionError (counted by error type, not by where it was thrown).
1034
- * The row stays leased and a later claim retries it; excluded from failed.
1035
- */
1036
- deferred?: number;
1032
+ export interface SubmitActionInput {
1033
+ actionId: ActionId;
1034
+ parameters: Record<string, unknown>;
1035
+ tenantId: string;
1036
+ spaceId: string;
1037
+ actorId: string;
1038
+ actorType: ActorType;
1039
+ correlationId?: string;
1040
+ causationId?: string;
1041
+ provenance?: InvocationProvenance;
1042
+ executionReason?: Extract<KnownActionExecutionReason, "initial" | "offline_replay">;
1043
+ /** Stable logical command key. Reusing it returns the original invocation; a pending failed dispatch may retry its stable workflow ID. */
1044
+ idempotencyKey?: string;
1045
+ /** Opaque, non-secret authorization/admission reference persisted with the invocation. */
1046
+ authorizationBindingId?: string;
1047
+ authorizationBinding?: AuthorizationBinding;
1048
+ }
1049
+ export interface SubmitActionResult {
1050
+ actionInvocationId: string;
1051
+ status: ActionStatus;
1052
+ workflowId: string;
1053
+ runId?: string;
1054
+ result?: Record<string, unknown>;
1055
+ error?: string;
1056
+ reconciliation?: AuthorizationReconciliationOutcome;
1057
+ adapterReconciliation?: AdapterReconciliationOutcome;
1058
+ /** Present while the invocation waits for an external system to complete it. */
1059
+ pendingCompletion?: PendingExternalCompletion;
1060
+ /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
1061
+ consistency?: "authoritative-now" | "provisional-until-reconciled";
1062
+ hitlRoute?: AgentActionRoute;
1063
+ hitlRiskTier?: AgentActionRiskTier;
1064
+ }
1065
+ export interface ExecuteActionResult {
1066
+ actionInvocationId: string;
1067
+ status: ActionStatus;
1068
+ result?: Record<string, unknown>;
1069
+ error?: string;
1070
+ reconciliation?: AuthorizationReconciliationOutcome;
1071
+ adapterReconciliation?: AdapterReconciliationOutcome;
1072
+ /** Present while the invocation waits for an external system to complete it. */
1073
+ pendingCompletion?: PendingExternalCompletion;
1074
+ /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
1075
+ consistency?: "authoritative-now" | "provisional-until-reconciled";
1076
+ hitlRoute?: AgentActionRoute;
1077
+ hitlRiskTier?: AgentActionRiskTier;
1078
+ }
1079
+ export interface ExecuteInvocationOptions {
1080
+ /** Required when executing a row already protected by a worker or approval-resume lease. */
1081
+ leaseOwner?: string;
1082
+ /** Claim generation paired with leaseOwner; stale generations are rejected. */
1083
+ leaseToken?: number;
1084
+ }
1085
+ export interface PlatformActionWorkerOptions<TDb> {
1086
+ host: GovernedActionHost;
1087
+ store: RecoverablePlatformHostStore<TDb>;
1088
+ workerId: string;
1089
+ batchSize?: number;
1090
+ leaseDurationMs?: number;
1091
+ leaseRenewalIntervalMs?: number;
1092
+ pollIntervalMs?: number;
1093
+ tenantId?: string;
1094
+ spaceId?: string;
1095
+ signal?: AbortSignal;
1096
+ onError?: (error: unknown, invocation?: ActionInvocationRecord) => void;
1097
+ telemetry?: PlatformHostTelemetry;
1098
+ /**
1099
+ * Sweep overdue external handoffs each cycle. Defaults to on. Turn it off
1100
+ * for a store without the governance seam, where the sweep would refuse
1101
+ * on every cycle, and run the sweep elsewhere.
1102
+ */
1103
+ sweepOverdueCompletions?: boolean;
1104
+ }
1105
+ export interface PlatformActionWorkerCycleResult {
1106
+ claimed: number;
1107
+ completed: number;
1108
+ failed: number;
1109
+ /** Present when claimed agent work was durably parked instead of failing. */
1110
+ waitingForApproval?: number;
1111
+ /**
1112
+ * Present only when > 0: claimed invocations whose execution threw a
1113
+ * RetryableExecutionError (counted by error type, not by where it was thrown).
1114
+ * The row stays leased and a later claim retries it; excluded from failed.
1115
+ */
1116
+ deferred?: number;
1037
1117
  }
1038
1118
  /** Origin of error text redacted before Host records or returns it. */
1039
- interface ErrorTextRedactionContext {
1040
- actionId: ActionId;
1041
- source: "handler" | "adapter" | "external_completion" | "execution";
1042
- adapterType?: string;
1043
- operation?: string;
1044
- /** Adapter vendor or external completion provider. */
1045
- provider?: string;
1046
- }
1047
- interface PlatformHostOptions<TDb> {
1048
- store: PlatformHostStore<TDb>;
1049
- authorization: PlatformHostAuthorization;
1050
- /** Preferred explicit catalog assembled from this runtime's Fabric modules. */
1051
- registry?: Pick<ModuleRegistry<TDb>, "resolveAction" | "resolvePolicy" | "resolveStateMachine"> & Partial<Pick<ModuleRegistry<TDb>, "orderedModules">>;
1052
- /** Resolve vertical- or runtime-local actions without mutating the process-wide registry. */
1053
- resolveAction?: (actionId: ActionId) => ActionDefinition<TDb> | undefined;
1054
- adapters?: readonly AdapterImplementation[];
1055
- /**
1056
- * Supplies the circuit breaker for each adapter call. Defaults to a new
1057
- * `AdapterCircuitBreakerRegistry` per Host instance, which creates one
1058
- * in-process breaker per `adapterType:operation` from that adapter's own
1059
- * `circuitBreaker` config, on first use, and none for adapters without one.
1060
- * Pass a shared registry or a custom provider to share breakers between
1061
- * Host instances, receive breaker telemetry, or set manual overrides.
1062
- * The default key shares failures across tenants and vendors in a registry.
1063
- * Use `new AdapterCircuitBreakerRegistry({ key: scopedAdapterCircuitBreakerKey })`
1064
- * for tenant/space/vendor isolation. Host passes trusted tenant/space scope
1065
- * to the provider. The registry keeps the first config seen for a key;
1066
- * later conflicting configs reuse that breaker without throwing. Breakers
1067
- * are never evicted, so scoped keys keep one breaker per scope seen.
1068
- */
1069
- adapterCircuitBreakers?: AdapterCircuitBreakerProvider;
1070
- /**
1071
- * Positive integer attempt cap for RetryableExecutionError during governance,
1072
- * before policy-evaluation persistence (default 5). A leased, idempotent action
1073
- * below the cap is left running for worker reclaim after lease expiry.
1074
- * Inline execution, approval resume, exhausted attempts, and non-idempotent
1075
- * actions fail. Policy persistence, obligation listing/resolution/persistence, state-machine checks,
1076
- * the handler transaction, handlers, adapters, and finalization are excluded;
1077
- * their existing failure/reconciliation/recovery semantics apply.
1078
- */
1079
- retryableExecutionMaxAttempts?: number;
1080
- dispatcher?: PlatformActionDispatcher;
1081
- services?: FabricRuntimeServices;
1082
- idempotency?: {
1083
- conflictMode?: "audit-only" | "enforce";
1084
- onConflict?(conflict: IdempotencyConflict): void;
1085
- onLegacyRecord?(invocation: ActionInvocationRecord): void;
1086
- };
1087
- provenance?: {
1088
- auditAttributeAllowlist?: readonly string[];
1089
- maxAttributes?: number;
1090
- maxValueLength?: number;
1091
- redactAuditAttributes?(attributes: NamespacedAttributes): NamespacedAttributes;
1092
- onTrace?(provenance: InvocationProvenance): void;
1093
- };
1094
- /** Requires an outbox-capable store; every canonical event is then appended with delivery state. */
1095
- outbox?: {
1096
- producerModuleVersion(actionId: ActionId, actionVersion: number): string;
1097
- classifyPayload(event: AssetEventEnvelope): EventPayloadClassification;
1098
- includeProvenance?(event: AssetEventEnvelope, classification: EventPayloadClassification): boolean;
1099
- /**
1100
- * Opt an event's `actorId` and `actorType` into its outbox envelope. Absent, the actor is
1101
- * excluded for every classification. Only `true` includes it. An included actor reaches every
1102
- * sink of every relay reading this outbox.
1103
- */
1104
- includeActor?(event: AssetEventEnvelope, classification: EventPayloadClassification): boolean;
1105
- traceContext?(event: AssetEventEnvelope): Record<string, string> | undefined;
1106
- /** Host lifecycle events are excluded by default; opt in only after making their payload audit-safe. */
1107
- shouldPublish?(event: AssetEventEnvelope): boolean;
1108
- };
1109
- /** Optional vertical-owned evaluator. When absent, agent behavior is unchanged. */
1110
- hitlEvaluator?: AgentActionPolicyEvaluator;
1111
- /** Durable evaluator/ruleset version recorded with every HITL decision. */
1112
- hitlPolicyVersion?: string;
1113
- /** Optional portable resolver; provider-specific implementations belong in integration packages. */
1114
- resolveMutationGovernance?: MutationGovernanceResolver;
1115
- /** Translate policy outcomes into durable, enforceable obligations. */
1116
- resolvePolicyObligations?: (outcomes: readonly PolicyOutcome[]) => Promise<PolicyObligation[]> | PolicyObligation[];
1117
- /** Translate a successful adapter result into audit-safe external execution evidence. */
1118
- extractExecutionAttestation?: (input: {
1119
- actionInvocationId: string;
1120
- adapterInvocationId: string;
1121
- adapterType: string;
1122
- operation: string;
1123
- vendor: string;
1124
- /** Audit-safe adapter input after redactAdapterInput has been applied. */
1125
- input: Record<string, unknown>;
1126
- startedAt: Date;
1127
- completedAt: Date;
1128
- /** Adapter output after redactAdapterOutput, when configured. */
1129
- output: Record<string, unknown>;
1130
- }) => Promise<ExecutionAttestation | undefined> | ExecutionAttestation | undefined;
1131
- /** Package/provider/ruleset generations persisted with every newly created invocation. */
1132
- runtimeEvidence?: Partial<GovernanceRuntimeEvidence>;
1133
- /**
1134
- * Trusted composition identity attached by the Host configuration, never
1135
- * accepted directly from submission input. Requires an explicit registry;
1136
- * its module namespaces and versions are checked against these identities.
1137
- */
1138
- composition?: {
1139
- assembly: AssemblyLockfile;
1140
- /**
1141
- * Receives a fresh object whose action, scope, actor, correlation,
1142
- * causation, idempotency key, binding id and execution reason are the
1143
- * ones Host read at submission and persists, whatever the caller
1144
- * changed on its own object since. For an action without
1145
- * `admitSubmission`, its `parameters`, `provenance` and
1146
- * `authorizationBinding` read and assign the caller's input, as when
1147
- * the callback was handed that input itself; for an action that
1148
- * declares it, they are fresh copies of Host's snapshot.
1149
- */
1150
- resolveInitiatingReleaseDigest?(input: SubmitActionInput): Promise<string | undefined> | string | undefined;
1151
- };
1152
- /** Lease held while an approved invocation resumes; defaults to five minutes. */
1153
- approvalResumeLeaseDurationMs?: number;
1154
- /**
1155
- * Remove forbidden/sensitive fields before durable invocation persistence.
1156
- * For an action without `admitSubmission`, receives the caller's
1157
- * parameters object, before provenance normalization and the composition
1158
- * callback, as before. For an action that declares it, receives Host's
1159
- * copy, after the check admitted the submission.
1160
- */
1161
- redactActionParameters?: (actionId: ActionId, parameters: Record<string, unknown>) => Record<string, unknown>;
1162
- /**
1163
- * The bound on an action's `admitSubmission` check. An answer that
1164
- * settles this many milliseconds or more after the check was called,
1165
- * measured on the monotonic clock when its promise settles, is refused as
1166
- * `timed_out` and the check's signal is aborted. A whole number from 1 to
1167
- * 2 147 483 647 (the timer maximum), or `createGovernedActionHost` throws;
1168
- * default 10 000.
1169
- */
1170
- admissionTimeoutMs?: number;
1171
- resolvePolicies?: (input: ResolvePoliciesInput) => Promise<RuntimePolicyDefinition[]>;
1172
- extractEvents?: (data: Record<string, unknown>) => PendingAssetEvent[];
1173
- /** Handler-result fields consumed by extractEvents and omitted from the durable result. */
1174
- eventResultFields?: readonly string[];
1175
- redactAdapterInput?: (actionId: ActionId, adapterType: string, operation: string, input: Record<string, unknown>) => Record<string, unknown>;
1176
- /**
1177
- * Redact successful adapter output before row/event persistence and attestation extraction.
1178
- * A throwing hook or a null, array or non-object return withholds output and requires reconciliation.
1179
- * Class instances and Dates are accepted, matching the adapter output record contract.
1180
- * Keep redactors deterministic and stable across deploys.
1181
- * Accepted-operation references are read from the original adapter result.
1182
- */
1183
- redactAdapterOutput?: (actionId: ActionId, adapterType: string, operation: string, output: Record<string, unknown>) => Record<string, unknown>;
1184
- /**
1185
- * Redact originating handler, adapter, completion and caught execution error text.
1186
- * Host-authored fixed text bypasses this hook; circuit and consistency errors use adapter context.
1187
- * Empty originating text bypasses the hook unchanged. For non-empty input, throwing or returning
1188
- * a non-string or empty string uses a placeholder on execution paths, but refuses a completion
1189
- * as redaction_failed before writes. State-machine `transition.error` text uses `source: "handler"`.
1190
- * Keep redactors deterministic and stable across deploys: changed output can make a repeat
1191
- * completion look like different evidence.
1192
- */
1193
- redactErrorText?: (context: ErrorTextRedactionContext, message: string) => string;
1194
- /**
1195
- * Redact completion results before merging, schema validation, persistence and digesting.
1196
- * Contradiction detection compares retained values; legacy raw digests also match repeats.
1197
- * A throwing hook or a null, array or non-object return refuses as redaction_failed before writes.
1198
- * Class instances and Dates are accepted by the same record predicate as adapter output.
1199
- * Keep redactors deterministic and stable across deploys: changes can make a repeat look like
1200
- * different evidence. A matching legacy raw digest is acknowledged before invoking hooks.
1201
- */
1202
- redactExternalCompletionResult?: (actionId: ActionId, provider: string, result: Record<string, unknown>) => Record<string, unknown>;
1203
- adapterEventSubject?: (actionId: ActionId, parameters: unknown, handlerResult: Record<string, unknown>) => {
1204
- subjectType: string;
1205
- subjectId: string;
1206
- } | undefined;
1207
- now?: () => Date;
1208
- /** Vendor-neutral lifecycle and metric sink. Telemetry is best effort. */
1209
- telemetry?: PlatformHostTelemetry;
1210
- /**
1211
- * Epoch-millis deadline delivered to every adapter execution context.
1212
- * When omitted, no deadline is set and adapters receive no AbortSignal.
1213
- */
1214
- adapterDeadlineMs?: number;
1215
- }
1216
- interface GovernedActionHost {
1217
- submitAction(input: SubmitActionInput): Promise<SubmitActionResult>;
1218
- executeInvocation(actionInvocationId: string, tenantId: string, spaceId: string, options?: ExecuteInvocationOptions): Promise<ExecuteActionResult>;
1219
- resumeApprovedInvocation(actionInvocationId: string, tenantId: string, spaceId: string, decision: ActionApprovalDecision): Promise<ExecuteActionResult>;
1220
- recordExecutionAttestation(actionInvocationId: string, tenantId: string, spaceId: string, attestation: ExecutionAttestation): Promise<void>;
1221
- recordExternalReconciliation(actionInvocationId: string, tenantId: string, spaceId: string, reconciliation: ExternalReconciliation): Promise<void>;
1119
+ export interface ErrorTextRedactionContext {
1120
+ actionId: ActionId;
1121
+ source: "handler" | "adapter" | "external_completion" | "execution";
1122
+ adapterType?: string;
1123
+ operation?: string;
1124
+ /** Adapter vendor or external completion provider. */
1125
+ provider?: string;
1126
+ }
1127
+ export interface PlatformHostOptions<TDb> {
1128
+ store: PlatformHostStore<TDb>;
1129
+ authorization: PlatformHostAuthorization;
1130
+ /** Preferred explicit catalog assembled from this runtime's Fabric modules. */
1131
+ registry?: Pick<ModuleRegistry<TDb>, "resolveAction" | "resolvePolicy" | "resolveStateMachine"> & Partial<Pick<ModuleRegistry<TDb>, "orderedModules">>;
1132
+ /** Resolve vertical- or runtime-local actions without mutating the process-wide registry. */
1133
+ resolveAction?: (actionId: ActionId) => ActionDefinition<TDb> | undefined;
1134
+ adapters?: readonly AdapterImplementation[];
1135
+ /**
1136
+ * Supplies the circuit breaker for each adapter call. Defaults to a new
1137
+ * `AdapterCircuitBreakerRegistry` per Host instance, which creates one
1138
+ * in-process breaker per `adapterType:operation` from that adapter's own
1139
+ * `circuitBreaker` config, on first use, and none for adapters without one.
1140
+ * Pass a shared registry or a custom provider to share breakers between
1141
+ * Host instances, receive breaker telemetry, or set manual overrides.
1142
+ * The default key shares failures across tenants and vendors in a registry.
1143
+ * Use `new AdapterCircuitBreakerRegistry({ key: scopedAdapterCircuitBreakerKey })`
1144
+ * for tenant/space/vendor isolation. Host passes trusted tenant/space scope
1145
+ * to the provider. The registry keeps the first config seen for a key;
1146
+ * later conflicting configs reuse that breaker without throwing. Breakers
1147
+ * are never evicted, so scoped keys keep one breaker per scope seen.
1148
+ */
1149
+ adapterCircuitBreakers?: AdapterCircuitBreakerProvider;
1150
+ /**
1151
+ * Positive integer attempt cap for RetryableExecutionError during governance,
1152
+ * before policy-evaluation persistence (default 5). A leased, idempotent action
1153
+ * below the cap is left running for worker reclaim after lease expiry.
1154
+ * Inline execution, approval resume, exhausted attempts, and non-idempotent
1155
+ * actions fail. Policy persistence, obligation listing/resolution/persistence, state-machine checks,
1156
+ * the handler transaction, handlers, adapters, and finalization are excluded;
1157
+ * their failure/reconciliation/recovery semantics apply, subject to recoveryMaxAttempts.
1158
+ */
1159
+ retryableExecutionMaxAttempts?: number;
1160
+ /**
1161
+ * Positive integer cap on worker claims for resumed leased running invocations
1162
+ * including the first (default max(5, retryableExecutionMaxAttempts); Infinity is rejected).
1163
+ * An explicit value must be at least retryableExecutionMaxAttempts. Claims above
1164
+ * the cap settle reconciliation_required before
1165
+ * handler or adapter execution. Inline/direct execution and approval resume
1166
+ * do not increment this counter. Approval resume is admitted at the cap and settles
1167
+ * reconciliation above it; approval does not reset the count. Parked handoffs are excluded. A worker dying
1168
+ * before the check consumes a claim without executing a provider at that point.
1169
+ */
1170
+ recoveryMaxAttempts?: number;
1171
+ dispatcher?: PlatformActionDispatcher;
1172
+ services?: FabricRuntimeServices;
1173
+ idempotency?: {
1174
+ conflictMode?: "audit-only" | "enforce";
1175
+ onConflict?(conflict: IdempotencyConflict): void;
1176
+ onLegacyRecord?(invocation: ActionInvocationRecord): void;
1177
+ };
1178
+ provenance?: {
1179
+ auditAttributeAllowlist?: readonly string[];
1180
+ maxAttributes?: number;
1181
+ maxValueLength?: number;
1182
+ redactAuditAttributes?(attributes: NamespacedAttributes): NamespacedAttributes;
1183
+ onTrace?(provenance: InvocationProvenance): void;
1184
+ };
1185
+ /** Requires an outbox-capable store; every canonical event is then appended with delivery state. */
1186
+ outbox?: {
1187
+ producerModuleVersion(actionId: ActionId, actionVersion: number): string;
1188
+ classifyPayload(event: AssetEventEnvelope): EventPayloadClassification;
1189
+ includeProvenance?(event: AssetEventEnvelope, classification: EventPayloadClassification): boolean;
1222
1190
  /**
1223
- * Complete an invocation an adapter handed off, by the reference the
1224
- * external system was given. Idempotent for a repeated identical
1225
- * completion; a contradictory one moves the invocation to reconciliation.
1191
+ * Opt an event's `actorId` and `actorType` into its outbox envelope. Absent, the actor is
1192
+ * excluded for every classification. Only `true` includes it. An included actor reaches every
1193
+ * sink of every relay reading this outbox.
1226
1194
  */
1227
- completeExternalInvocation(actionInvocationId: string, tenantId: string, spaceId: string, completion: ExternalCompletion): Promise<ExecuteActionResult>;
1195
+ includeActor?(event: AssetEventEnvelope, classification: EventPayloadClassification): boolean;
1196
+ traceContext?(event: AssetEventEnvelope): Record<string, string> | undefined;
1197
+ /** Host lifecycle events are excluded by default; opt in only after making their payload audit-safe. */
1198
+ shouldPublish?(event: AssetEventEnvelope): boolean;
1199
+ };
1200
+ /** Optional vertical-owned evaluator. When absent, agent behavior is unchanged. */
1201
+ hitlEvaluator?: AgentActionPolicyEvaluator;
1202
+ /** Durable evaluator/ruleset version recorded with every HITL decision. */
1203
+ hitlPolicyVersion?: string;
1204
+ /** Optional portable resolver; provider-specific implementations belong in integration packages. */
1205
+ resolveMutationGovernance?: MutationGovernanceResolver;
1206
+ /** Translate policy outcomes into durable, enforceable obligations. */
1207
+ resolvePolicyObligations?: (outcomes: readonly PolicyOutcome[]) => Promise<PolicyObligation[]> | PolicyObligation[];
1208
+ /** Translate a successful adapter result into audit-safe evidence. Recovery may call this
1209
+ * again with stored input/output; return deterministic evidence for the same input. */
1210
+ extractExecutionAttestation?: (input: {
1211
+ actionInvocationId: string;
1212
+ adapterInvocationId: string;
1213
+ adapterType: string;
1214
+ operation: string;
1215
+ vendor: string;
1216
+ /** Audit-safe adapter input after redactAdapterInput has been applied. */
1217
+ input: Record<string, unknown>;
1218
+ startedAt: Date;
1219
+ completedAt: Date;
1220
+ /** Adapter output after redactAdapterOutput, when configured. */
1221
+ output: Record<string, unknown>;
1222
+ }) => Promise<ExecutionAttestation | undefined> | ExecutionAttestation | undefined;
1223
+ /** Package/provider/ruleset generations persisted with every newly created invocation. */
1224
+ runtimeEvidence?: Partial<GovernanceRuntimeEvidence>;
1225
+ /**
1226
+ * Trusted composition identity attached by the Host configuration, never
1227
+ * accepted directly from submission input. Requires an explicit registry;
1228
+ * its module namespaces and versions are checked against these identities.
1229
+ */
1230
+ composition?: {
1231
+ assembly: AssemblyLockfile;
1228
1232
  /**
1229
- * Move handoffs past their deadline to `reconciliation_required`, so a
1230
- * callback that never comes is a finding and not a silent wait. The
1231
- * pending handoff is kept, so a late completion can still land.
1233
+ * Receives a fresh object whose action, scope, actor, correlation,
1234
+ * causation, idempotency key, binding id and execution reason are the
1235
+ * ones Host read at submission and persists, whatever the caller
1236
+ * changed on its own object since. For an action without
1237
+ * `admitSubmission`, its `parameters`, `provenance` and
1238
+ * `authorizationBinding` read and assign the caller's input, as when
1239
+ * the callback was handed that input itself; for an action that
1240
+ * declares it, they are fresh copies of Host's snapshot.
1232
1241
  */
1233
- reconcileOverdueCompletions(input?: ReconcileOverdueCompletionsInput): Promise<{
1234
- overdue: string[];
1235
- }>;
1242
+ resolveInitiatingReleaseDigest?(input: SubmitActionInput): Promise<string | undefined> | string | undefined;
1243
+ };
1244
+ /** Lease held while an approved invocation resumes; defaults to five minutes. */
1245
+ approvalResumeLeaseDurationMs?: number;
1246
+ /**
1247
+ * Remove forbidden/sensitive fields before durable invocation persistence.
1248
+ * For an action without `admitSubmission`, receives the caller's
1249
+ * parameters object, before provenance normalization and the composition
1250
+ * callback, as before. For an action that declares it, receives Host's
1251
+ * copy, after the check admitted the submission.
1252
+ */
1253
+ redactActionParameters?: (actionId: ActionId, parameters: Record<string, unknown>) => Record<string, unknown>;
1254
+ /**
1255
+ * The bound on an action's `admitSubmission` check. An answer that
1256
+ * settles this many milliseconds or more after the check was called,
1257
+ * measured on the monotonic clock when its promise settles, is refused as
1258
+ * `timed_out` and the check's signal is aborted. A whole number from 1 to
1259
+ * 2 147 483 647 (the timer maximum), or `createGovernedActionHost` throws;
1260
+ * default 10 000.
1261
+ */
1262
+ admissionTimeoutMs?: number;
1263
+ resolvePolicies?: (input: ResolvePoliciesInput) => Promise<RuntimePolicyDefinition[]>;
1264
+ extractEvents?: (data: Record<string, unknown>) => PendingAssetEvent[];
1265
+ /** Handler-result fields consumed by extractEvents and omitted from the durable result. */
1266
+ eventResultFields?: readonly string[];
1267
+ redactAdapterInput?: (actionId: ActionId, adapterType: string, operation: string, input: Record<string, unknown>) => Record<string, unknown>;
1268
+ /**
1269
+ * Redact successful adapter output before row/event persistence and attestation extraction.
1270
+ * A throwing hook or a null, array or non-object return withholds output and requires reconciliation.
1271
+ * Class instances and Dates are accepted, matching the adapter output record contract.
1272
+ * Keep redactors deterministic and stable across deploys.
1273
+ * Accepted-operation references are read from the original adapter result.
1274
+ */
1275
+ redactAdapterOutput?: (actionId: ActionId, adapterType: string, operation: string, output: Record<string, unknown>) => Record<string, unknown>;
1276
+ /**
1277
+ * Redact originating handler, adapter, completion and caught execution error text.
1278
+ * Host-authored fixed text bypasses this hook; circuit and consistency errors use adapter context.
1279
+ * Empty originating text bypasses the hook unchanged. For non-empty input, throwing or returning
1280
+ * a non-string or empty string uses a placeholder on execution paths, but refuses a completion
1281
+ * as redaction_failed before writes. State-machine `transition.error` text uses `source: "handler"`.
1282
+ * Keep redactors deterministic and stable across deploys: changed output can make a repeat
1283
+ * completion look like different evidence.
1284
+ */
1285
+ redactErrorText?: (context: ErrorTextRedactionContext, message: string) => string;
1286
+ /**
1287
+ * Redact completion results before merging, schema validation, persistence and digesting.
1288
+ * Contradiction detection compares retained values; legacy raw digests also match repeats.
1289
+ * A throwing hook or a null, array or non-object return refuses as redaction_failed before writes.
1290
+ * Class instances and Dates are accepted by the same record predicate as adapter output.
1291
+ * Keep redactors deterministic and stable across deploys: changes can make a repeat look like
1292
+ * different evidence. A matching legacy raw digest is acknowledged before invoking hooks.
1293
+ */
1294
+ redactExternalCompletionResult?: (actionId: ActionId, provider: string, result: Record<string, unknown>) => Record<string, unknown>;
1295
+ adapterEventSubject?: (actionId: ActionId, parameters: unknown, handlerResult: Record<string, unknown>) => {
1296
+ subjectType: string;
1297
+ subjectId: string;
1298
+ } | undefined;
1299
+ now?: () => Date;
1300
+ /** Vendor-neutral lifecycle and metric sink. Telemetry is best effort. */
1301
+ telemetry?: PlatformHostTelemetry;
1302
+ /**
1303
+ * Epoch-millis deadline delivered to every adapter execution context.
1304
+ * When omitted, no deadline is set and adapters receive no AbortSignal.
1305
+ */
1306
+ adapterDeadlineMs?: number;
1307
+ }
1308
+ export interface GovernedActionHost {
1309
+ submitAction(input: SubmitActionInput): Promise<SubmitActionResult>;
1310
+ executeInvocation(actionInvocationId: string, tenantId: string, spaceId: string, options?: ExecuteInvocationOptions): Promise<ExecuteActionResult>;
1311
+ resumeApprovedInvocation(actionInvocationId: string, tenantId: string, spaceId: string, decision: ActionApprovalDecision): Promise<ExecuteActionResult>;
1312
+ recordExecutionAttestation(actionInvocationId: string, tenantId: string, spaceId: string, attestation: ExecutionAttestation): Promise<void>;
1313
+ recordExternalReconciliation(actionInvocationId: string, tenantId: string, spaceId: string, reconciliation: ExternalReconciliation): Promise<void>;
1314
+ /**
1315
+ * Complete an invocation an adapter handed off, by the reference the
1316
+ * external system was given. Idempotent for a repeated identical
1317
+ * completion; a contradictory one moves the invocation to reconciliation.
1318
+ */
1319
+ completeExternalInvocation(actionInvocationId: string, tenantId: string, spaceId: string, completion: ExternalCompletion): Promise<ExecuteActionResult>;
1320
+ /**
1321
+ * Move eligible running, unleased overdue handoffs to `reconciliation_required`
1322
+ * and retain the handoff with overdueAt. A callback can settle that verdict
1323
+ * only after parking; callbacks for swept unparked invocations record redacted
1324
+ * evidence without result-schema validation. Parked rows lacking overdueAt
1325
+ * retain the weaker "did not complete by" error-substring fallback.
1326
+ */
1327
+ reconcileOverdueCompletions(input?: ReconcileOverdueCompletionsInput): Promise<{
1328
+ overdue: string[];
1329
+ }>;
1236
1330
  }
1237
1331
  /**
1238
1332
  * Host operator operations kept outside `GovernedActionHost`, so an existing
1239
1333
  * hand-written `GovernedActionHost` still satisfies that interface.
1240
1334
  * `createGovernedActionHost()` returns both.
1241
1335
  */
1242
- interface OutboxRequeueHost {
1243
- /**
1244
- * Operator replay of a dead-lettered outbox record: authorize the trusted
1245
- * actor for the tenant and space against the record as read, then move
1246
- * that same dead letter back to pending with a fresh attempt budget and
1247
- * append who, when, and why beside the earlier failure. The relay
1248
- * republishes it under the same `eventId`. Requires an
1249
- * `OutboxRequeuePlatformHostStore`; refusals are returned, not thrown.
1250
- */
1251
- requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterInput): Promise<RequeueOutboxDeadLetterResult>;
1252
- }
1253
-
1254
- declare function createGovernedActionHost<TDb>(options: PlatformHostOptions<TDb>): GovernedActionHost & OutboxRequeueHost;
1255
-
1256
- interface MemoryPlatformHostTransactionProvider<TDb> {
1257
- snapshot(db: TDb): TDb;
1258
- restore(db: TDb, snapshot: TDb): void;
1259
- }
1260
- declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1261
- readonly db: TDb;
1262
- readonly transactionalOutbox: boolean;
1263
- transactionWithEvents?: <TResult>(run: (transaction: PlatformHostMutationTransaction<TDb>) => Promise<TResult>) => Promise<TResult>;
1264
- private transactionTail;
1265
- readonly invocations: ActionInvocationRecord[];
1266
- readonly policyEvaluations: PolicyEvaluationRecord[];
1267
- readonly adapterInvocations: AdapterInvocationRecord[];
1268
- readonly events: AssetEventEnvelope[];
1269
- readonly policyObligations: PolicyObligationRecord[];
1270
- readonly executionAttestations: ExecutionAttestationRecord[];
1271
- readonly externalReconciliations: ExternalReconciliationRecord[];
1272
- readonly outbox: OutboxRecord[];
1273
- /**
1274
- * Requeue evidence is append-only audit history, so unlike the ledger
1275
- * arrays above, which tests have always inspected and seeded directly, it
1276
- * is not public: `listOutboxRequeues` returns copies with their own Dates. TypeScript
1277
- * `private`, as for the store's other internals, is a compile-time guard.
1278
- */
1279
- private readonly outboxRequeues;
1280
- constructor(db: TDb, transactionProvider?: MemoryPlatformHostTransactionProvider<TDb>);
1281
- transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1282
- private runTransactionWithEvents;
1283
- createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1284
- getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1285
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1286
- recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1287
- beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
1288
- appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
1289
- recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: Pick<ActionInvocationRecord, "mutationFootprint" | "executionPrincipal"> & {
1290
- footprint: NonNullable<ActionInvocationRecord["mutationFootprint"]>;
1291
- executionPrincipal: NonNullable<ActionInvocationRecord["executionPrincipal"]>;
1292
- }): Promise<ActionInvocationRecord>;
1293
- appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
1294
- listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
1295
- updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationRecord["status"], evidenceReferences?: PolicyObligationRecord["evidenceReferences"]): Promise<void>;
1296
- appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
1297
- listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
1298
- appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
1299
- createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
1300
- getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
1301
- updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt">>, scope?: AdapterInvocationScope): Promise<void>;
1302
- appendEvent(event: AssetEventEnvelope): Promise<void>;
1303
- appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
1304
- claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
1305
- markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
1306
- markOutboxFailed(input: {
1307
- id: string;
1308
- workerId: string;
1309
- leaseToken?: number;
1310
- error: string;
1311
- availableAt: Date;
1312
- deadLetter: boolean;
1313
- }): Promise<void>;
1314
- renewOutboxLease(input: {
1315
- id: string;
1316
- workerId: string;
1317
- leaseToken: number;
1318
- leaseDurationMs: number;
1319
- now?: Date;
1320
- }): Promise<boolean>;
1321
- listOutbox(input?: {
1322
- tenantId?: string;
1323
- spaceId?: string;
1324
- statuses?: OutboxStatus[];
1325
- }): Promise<OutboxRecord[]>;
1326
- getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
1327
- requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
1328
- listOutboxRequeues(input: {
1329
- tenantId: string;
1330
- spaceId: string;
1331
- outboxId?: string;
1332
- }): Promise<OutboxRequeueRecord[]>;
1333
- private requireLeasedOutbox;
1334
- nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
1335
- getEntityStateSource(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
1336
- state: string;
1337
- actionInvocationId: string;
1338
- } | undefined>;
1339
- getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
1340
- listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1341
- getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
1342
- claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1343
- updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
1344
- renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
1345
- listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
1346
- }
1347
-
1348
- declare function toEnterpriseEventEnvelope(event: AssetEventEnvelope, metadata: OutboxEventMetadata): EnterpriseEventEnvelope;
1349
- /** The `includeActor` decision a store records with the outbox record it writes from `metadata`. */
1350
- declare function outboxActorDisclosure(metadata: OutboxEventMetadata): OutboxActorDisclosure;
1351
- interface EnterpriseEventPublishContext {
1352
- signal: AbortSignal;
1353
- /**
1354
- * Why the envelope does or does not carry `actorId`/`actorType`. `runOutboxRelayCycle()` always
1355
- * sets it; a caller other than the relay may omit it, which a consumer should treat like `legacy`.
1356
- */
1357
- actorDisclosure?: EnterpriseEventActorDisclosure;
1358
- }
1359
- interface EnterpriseEventPublisher {
1360
- publish(event: EnterpriseEventEnvelope, context?: EnterpriseEventPublishContext): Promise<void>;
1361
- }
1362
- interface OutboxRelayOptions<TDb> {
1363
- store: OutboxPlatformHostStore<TDb>;
1364
- publisher: EnterpriseEventPublisher;
1336
+ export interface OutboxRequeueHost {
1337
+ /**
1338
+ * Operator replay of a dead-lettered outbox record: authorize the trusted
1339
+ * actor for the tenant and space against the record as read, then move
1340
+ * that same dead letter back to pending with a fresh attempt budget and
1341
+ * append who, when, and why beside the earlier failure. The relay
1342
+ * republishes it under the same `eventId`. Requires an
1343
+ * `OutboxRequeuePlatformHostStore`; refusals are returned, not thrown.
1344
+ */
1345
+ requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterInput): Promise<RequeueOutboxDeadLetterResult>;
1346
+ }
1347
+ //#endregion
1348
+ //#region src/host.d.ts
1349
+ export declare function createGovernedActionHost<TDb>(options: PlatformHostOptions<TDb>): GovernedActionHost & OutboxRequeueHost;
1350
+ //#endregion
1351
+ //#region src/memory-store.d.ts
1352
+ export interface MemoryPlatformHostTransactionProvider<TDb> {
1353
+ snapshot(db: TDb): TDb;
1354
+ restore(db: TDb, snapshot: TDb): void;
1355
+ }
1356
+ export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1357
+ readonly db: TDb;
1358
+ readonly transactionalOutbox: boolean;
1359
+ transactionWithEvents?: <TResult>(run: (transaction: PlatformHostMutationTransaction<TDb>) => Promise<TResult>) => Promise<TResult>;
1360
+ private adapterCommit;
1361
+ private transactionTail;
1362
+ readonly invocations: ActionInvocationRecord[];
1363
+ readonly policyEvaluations: PolicyEvaluationRecord[];
1364
+ readonly adapterInvocations: AdapterInvocationRecord[];
1365
+ readonly events: AssetEventEnvelope[];
1366
+ readonly policyObligations: PolicyObligationRecord[];
1367
+ readonly executionAttestations: ExecutionAttestationRecord[];
1368
+ readonly externalReconciliations: ExternalReconciliationRecord[];
1369
+ readonly outbox: OutboxRecord[];
1370
+ /**
1371
+ * Requeue evidence is append-only audit history, so unlike the ledger
1372
+ * arrays above, which tests have always inspected and seeded directly, it
1373
+ * is not public: `listOutboxRequeues` returns copies with their own Dates. TypeScript
1374
+ * `private`, as for the store's other internals, is a compile-time guard.
1375
+ */
1376
+ private readonly outboxRequeues;
1377
+ constructor(db: TDb, transactionProvider?: MemoryPlatformHostTransactionProvider<TDb>);
1378
+ transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1379
+ private runTransactionWithEvents;
1380
+ createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1381
+ getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1382
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1383
+ recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1384
+ beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
1385
+ appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
1386
+ recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: Pick<ActionInvocationRecord, "mutationFootprint" | "executionPrincipal"> & {
1387
+ footprint: NonNullable<ActionInvocationRecord["mutationFootprint"]>;
1388
+ executionPrincipal: NonNullable<ActionInvocationRecord["executionPrincipal"]>;
1389
+ }): Promise<ActionInvocationRecord>;
1390
+ appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
1391
+ listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
1392
+ updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationRecord["status"], evidenceReferences?: PolicyObligationRecord["evidenceReferences"]): Promise<void>;
1393
+ appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
1394
+ listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
1395
+ appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
1396
+ private adapterWriteMatches;
1397
+ updateSettledActionInvocation(input: UpdateSettledActionInvocationInput): Promise<boolean>;
1398
+ writeAdapterInvocation(input: AdapterInvocationWriteInput): Promise<boolean>;
1399
+ createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
1400
+ getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
1401
+ updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt" | "reconciliation">>, scope?: AdapterInvocationScope): Promise<void>;
1402
+ appendEvent(event: AssetEventEnvelope): Promise<void>;
1403
+ appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
1404
+ claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
1405
+ markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
1406
+ markOutboxFailed(input: {
1407
+ id: string;
1365
1408
  workerId: string;
1366
- leaseDurationMs?: number;
1367
- leaseRenewalIntervalMs?: number;
1368
- publishTimeoutMs?: number;
1369
- batchSize?: number;
1370
- maxAttempts?: number;
1371
- retryDelayMs?: (attempt: number) => number;
1372
- now?: () => Date;
1373
- telemetry?: PlatformHostTelemetry;
1374
- }
1375
- interface OutboxRelayResult {
1376
- claimed: number;
1377
- published: number;
1378
- failed: number;
1379
- deadLettered: number;
1380
- }
1381
- declare function runOutboxRelayCycle<TDb>(options: OutboxRelayOptions<TDb>): Promise<OutboxRelayResult>;
1409
+ leaseToken?: number;
1410
+ error: string;
1411
+ availableAt: Date;
1412
+ deadLetter: boolean;
1413
+ }): Promise<void>;
1414
+ renewOutboxLease(input: {
1415
+ id: string;
1416
+ workerId: string;
1417
+ leaseToken: number;
1418
+ leaseDurationMs: number;
1419
+ now?: Date;
1420
+ }): Promise<boolean>;
1421
+ listOutbox(input?: {
1422
+ tenantId?: string;
1423
+ spaceId?: string;
1424
+ statuses?: OutboxStatus[];
1425
+ }): Promise<OutboxRecord[]>;
1426
+ getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
1427
+ requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
1428
+ listOutboxRequeues(input: {
1429
+ tenantId: string;
1430
+ spaceId: string;
1431
+ outboxId?: string;
1432
+ }): Promise<OutboxRequeueRecord[]>;
1433
+ private requireLeasedOutbox;
1434
+ nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
1435
+ getEntityStateSource(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
1436
+ state: string;
1437
+ actionInvocationId: string;
1438
+ } | undefined>;
1439
+ getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
1440
+ listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1441
+ getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
1442
+ claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1443
+ updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
1444
+ renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
1445
+ listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
1446
+ }
1447
+ //#endregion
1448
+ //#region src/outbox.d.ts
1449
+ export declare function toEnterpriseEventEnvelope(event: AssetEventEnvelope, metadata: OutboxEventMetadata): EnterpriseEventEnvelope;
1450
+ /** The `includeActor` decision a store records with the outbox record it writes from `metadata`. */
1451
+ export declare function outboxActorDisclosure(metadata: OutboxEventMetadata): OutboxActorDisclosure;
1452
+ export interface EnterpriseEventPublishContext {
1453
+ signal: AbortSignal;
1454
+ /**
1455
+ * Why the envelope does or does not carry `actorId`/`actorType`. `runOutboxRelayCycle()` always
1456
+ * sets it; a caller other than the relay may omit it, which a consumer should treat like `legacy`.
1457
+ */
1458
+ actorDisclosure?: EnterpriseEventActorDisclosure;
1459
+ }
1460
+ export interface EnterpriseEventPublisher {
1461
+ publish(event: EnterpriseEventEnvelope, context?: EnterpriseEventPublishContext): Promise<void>;
1462
+ }
1463
+ export interface OutboxRelayOptions<TDb> {
1464
+ store: OutboxPlatformHostStore<TDb>;
1465
+ publisher: EnterpriseEventPublisher;
1466
+ workerId: string;
1467
+ leaseDurationMs?: number;
1468
+ leaseRenewalIntervalMs?: number;
1469
+ publishTimeoutMs?: number;
1470
+ batchSize?: number;
1471
+ maxAttempts?: number;
1472
+ retryDelayMs?: (attempt: number) => number;
1473
+ now?: () => Date;
1474
+ telemetry?: PlatformHostTelemetry;
1475
+ }
1476
+ export interface OutboxRelayResult {
1477
+ claimed: number;
1478
+ published: number;
1479
+ failed: number;
1480
+ deadLettered: number;
1481
+ }
1482
+ export declare function runOutboxRelayCycle<TDb>(options: OutboxRelayOptions<TDb>): Promise<OutboxRelayResult>;
1382
1483
  /**
1383
1484
  * A copy with its own Date fields and trace context. The event payload and
1384
1485
  * provenance are shallow: the copy shares them with the record, as before.
1385
1486
  */
1386
- declare function cloneOutboxRecord(record: OutboxRecord): OutboxRecord;
1387
-
1388
- interface PlatformHostSqlResult<Row = Record<string, unknown>> {
1389
- rows: Row[];
1487
+ export declare function cloneOutboxRecord(record: OutboxRecord): OutboxRecord;
1488
+ //#endregion
1489
+ //#region src/postgres-store.d.ts
1490
+ export interface PlatformHostSqlResult<Row = Record<string, unknown>> {
1491
+ rows: Row[];
1390
1492
  }
1391
1493
  /** Structural subset implemented by `pg.Pool` and Lakebase-compatible clients. */
1392
- interface PlatformHostSqlClient {
1393
- query<Row = Record<string, unknown>>(sql: string, values?: unknown[]): Promise<PlatformHostSqlResult<Row>>;
1494
+ export interface PlatformHostSqlClient {
1495
+ query<Row = Record<string, unknown>>(sql: string, values?: unknown[]): Promise<PlatformHostSqlResult<Row>>;
1394
1496
  }
1395
- interface PostgresPlatformHostTransactionContext<TDb> {
1396
- db: TDb;
1397
- sql: PlatformHostSqlClient;
1497
+ export interface PostgresPlatformHostTransactionContext<TDb> {
1498
+ db: TDb;
1499
+ sql: PlatformHostSqlClient;
1398
1500
  }
1399
1501
  /**
1400
1502
  * Application-owned transaction binder.
@@ -1403,87 +1505,90 @@ interface PostgresPlatformHostTransactionContext<TDb> {
1403
1505
  * `pg.PoolClient`. Production applications provide this adapter so domain
1404
1506
  * methods and Host ledger writes share one PostgreSQL transaction.
1405
1507
  */
1406
- interface PostgresPlatformHostTransactionProvider<TDb> {
1407
- run<TResult>(run: (context: PostgresPlatformHostTransactionContext<TDb>) => Promise<TResult>): Promise<TResult>;
1508
+ export interface PostgresPlatformHostTransactionProvider<TDb> {
1509
+ run<TResult>(run: (context: PostgresPlatformHostTransactionContext<TDb>) => Promise<TResult>): Promise<TResult>;
1408
1510
  }
1409
1511
  /** Durable mutation-pipeline ledger for Databricks Lakebase or standard Postgres. */
1410
- declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1411
- readonly db: TDb;
1412
- private readonly sql;
1413
- readonly transactionWithEvents?: AtomicMutationPlatformHostStore<TDb>["transactionWithEvents"];
1414
- readonly transactionalOutbox: boolean;
1415
- constructor(db: TDb, sql: PlatformHostSqlClient, transactionProvider?: PostgresPlatformHostTransactionProvider<TDb>);
1416
- ensureSchema(): Promise<void>;
1417
- transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1418
- createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1419
- getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1420
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1421
- recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1422
- beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
1423
- appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
1424
- recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: {
1425
- footprint: NonNullable<ActionInvocationRecord["mutationFootprint"]>;
1426
- executionPrincipal: NonNullable<ActionInvocationRecord["executionPrincipal"]>;
1427
- }): Promise<ActionInvocationRecord>;
1428
- appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
1429
- listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
1430
- updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationRecord["status"], evidenceReferences?: PolicyObligationRecord["evidenceReferences"]): Promise<void>;
1431
- appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
1432
- listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
1433
- appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
1434
- createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
1435
- getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
1436
- updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt">>, scope?: AdapterInvocationScope): Promise<void>;
1437
- appendEvent(event: AssetEventEnvelope): Promise<void>;
1438
- appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
1439
- claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
1440
- markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
1441
- markOutboxFailed(input: {
1442
- id: string;
1443
- workerId: string;
1444
- leaseToken?: number;
1445
- error: string;
1446
- availableAt: Date;
1447
- deadLetter: boolean;
1448
- }): Promise<void>;
1449
- renewOutboxLease(input: {
1450
- id: string;
1451
- workerId: string;
1452
- leaseToken: number;
1453
- leaseDurationMs: number;
1454
- now?: Date;
1455
- }): Promise<boolean>;
1456
- listOutbox(input?: {
1457
- tenantId?: string;
1458
- spaceId?: string;
1459
- statuses?: OutboxStatus[];
1460
- }): Promise<OutboxRecord[]>;
1461
- getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
1462
- requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
1463
- listOutboxRequeues(input: {
1464
- tenantId: string;
1465
- spaceId: string;
1466
- outboxId?: string;
1467
- }): Promise<OutboxRequeueRecord[]>;
1468
- nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
1469
- getEntityStateSource(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
1470
- state: string;
1471
- actionInvocationId: string;
1472
- } | undefined>;
1473
- getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
1474
- listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1475
- getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
1476
- claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1477
- updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
1478
- renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
1479
- listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
1480
- getEvent(id: string, tenantId: string, spaceId: string): Promise<AssetEventEnvelope | undefined>;
1481
- }
1482
-
1483
- interface PostgresMigration {
1484
- version: number;
1485
- name: string;
1486
- sql: string;
1512
+ export declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1513
+ readonly db: TDb;
1514
+ private readonly sql;
1515
+ readonly transactionWithEvents?: AtomicMutationPlatformHostStore<TDb>["transactionWithEvents"];
1516
+ readonly transactionalOutbox: boolean;
1517
+ constructor(db: TDb, sql: PlatformHostSqlClient, transactionProvider?: PostgresPlatformHostTransactionProvider<TDb>);
1518
+ ensureSchema(): Promise<void>;
1519
+ transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1520
+ createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1521
+ getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1522
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1523
+ recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1524
+ beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
1525
+ appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
1526
+ recordMutationGovernance(actionInvocationId: string, tenantId: string, spaceId: string, context: {
1527
+ footprint: NonNullable<ActionInvocationRecord["mutationFootprint"]>;
1528
+ executionPrincipal: NonNullable<ActionInvocationRecord["executionPrincipal"]>;
1529
+ }): Promise<ActionInvocationRecord>;
1530
+ appendPolicyObligations(records: PolicyObligationRecord[]): Promise<void>;
1531
+ listPolicyObligations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<PolicyObligationRecord[]>;
1532
+ updatePolicyObligation(actionInvocationId: string, obligationId: string, status: PolicyObligationRecord["status"], evidenceReferences?: PolicyObligationRecord["evidenceReferences"]): Promise<void>;
1533
+ appendExecutionAttestation(record: ExecutionAttestationRecord): Promise<void>;
1534
+ listExecutionAttestations(actionInvocationId: string, tenantId: string, spaceId: string): Promise<ExecutionAttestationRecord[]>;
1535
+ appendExternalReconciliation(record: ExternalReconciliationRecord): Promise<void>;
1536
+ updateSettledActionInvocation(input: UpdateSettledActionInvocationInput): Promise<boolean>;
1537
+ writeAdapterInvocation(input: AdapterInvocationWriteInput): Promise<boolean>;
1538
+ createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
1539
+ getAdapterInvocation(id: string, scope?: AdapterInvocationScope): Promise<AdapterInvocationRecord | undefined>;
1540
+ updateAdapterInvocation(id: string, patch: Partial<Pick<AdapterInvocationRecord, "status" | "output" | "error" | "attempt" | "updatedAt" | "reconciliation">>, scope?: AdapterInvocationScope): Promise<void>;
1541
+ appendEvent(event: AssetEventEnvelope): Promise<void>;
1542
+ appendEventWithOutbox(event: AssetEventEnvelope, metadata: OutboxEventMetadata): Promise<void>;
1543
+ claimOutbox(input: ClaimOutboxInput): Promise<OutboxRecord[]>;
1544
+ markOutboxPublished(id: string, workerId: string, publishedAt: Date, leaseToken?: number): Promise<void>;
1545
+ markOutboxFailed(input: {
1546
+ id: string;
1547
+ workerId: string;
1548
+ leaseToken?: number;
1549
+ error: string;
1550
+ availableAt: Date;
1551
+ deadLetter: boolean;
1552
+ }): Promise<void>;
1553
+ renewOutboxLease(input: {
1554
+ id: string;
1555
+ workerId: string;
1556
+ leaseToken: number;
1557
+ leaseDurationMs: number;
1558
+ now?: Date;
1559
+ }): Promise<boolean>;
1560
+ listOutbox(input?: {
1561
+ tenantId?: string;
1562
+ spaceId?: string;
1563
+ statuses?: OutboxStatus[];
1564
+ }): Promise<OutboxRecord[]>;
1565
+ getOutboxRecord(id: string, tenantId: string, spaceId: string): Promise<OutboxRecord | undefined>;
1566
+ requeueOutboxDeadLetter(input: RequeueOutboxDeadLetterStoreInput): Promise<RequeueOutboxDeadLetterStoreResult>;
1567
+ listOutboxRequeues(input: {
1568
+ tenantId: string;
1569
+ spaceId: string;
1570
+ outboxId?: string;
1571
+ }): Promise<OutboxRequeueRecord[]>;
1572
+ nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
1573
+ getEntityStateSource(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
1574
+ state: string;
1575
+ actionInvocationId: string;
1576
+ } | undefined>;
1577
+ getEntityState(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
1578
+ listActionInvocations(input?: ListActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1579
+ getHealthCounts(input: PlatformHostHealthQuery): Promise<PlatformHostHealthCounts>;
1580
+ claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1581
+ updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
1582
+ renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
1583
+ listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
1584
+ getEvent(id: string, tenantId: string, spaceId: string): Promise<AssetEventEnvelope | undefined>;
1585
+ }
1586
+ //#endregion
1587
+ //#region src/postgres-migrations.d.ts
1588
+ export interface PostgresMigration {
1589
+ version: number;
1590
+ name: string;
1591
+ sql: string;
1487
1592
  }
1488
1593
  /**
1489
1594
  * Applies an immutable, ordered migration set in one PostgreSQL transaction.
@@ -1491,74 +1596,76 @@ interface PostgresMigration {
1491
1596
  * The transaction-scoped advisory lock serializes migrators. A previously
1492
1597
  * applied version may be presented again only when its checksum is unchanged.
1493
1598
  */
1494
- declare function applyPostgresMigrations(client: PlatformHostSqlClient, migrations: readonly PostgresMigration[]): Promise<void>;
1495
-
1496
- declare const PARAMETER_DIGEST_ALGORITHM: "fabric-canonical-json-sha256-v1";
1497
-
1498
- declare function digestParameters(parameters: unknown): string;
1499
-
1599
+ export declare function applyPostgresMigrations(client: PlatformHostSqlClient, migrations: readonly PostgresMigration[]): Promise<void>;
1600
+ //#endregion
1601
+ //#region src/command-identity.d.ts
1602
+ export declare const PARAMETER_DIGEST_ALGORITHM: "fabric-canonical-json-sha256-v1";
1603
+ export declare function digestParameters(parameters: unknown): string;
1604
+ //#endregion
1605
+ //#region src/worker.d.ts
1500
1606
  /**
1501
1607
  * Durable store-backed dispatch: the pending invocation row is the queue item.
1502
1608
  * Repeated dispatches are safe because the workflow id is stable per invocation.
1503
1609
  */
1504
- declare function createStoreBackedActionDispatcher(): PlatformActionDispatcher;
1610
+ export declare function createStoreBackedActionDispatcher(): PlatformActionDispatcher;
1505
1611
  /** Claim and execute one bounded batch. Safe to run concurrently across workers. */
1506
- declare function runPlatformActionWorkerCycle<TDb>(options: PlatformActionWorkerOptions<TDb>): Promise<PlatformActionWorkerCycleResult>;
1612
+ export declare function runPlatformActionWorkerCycle<TDb>(options: PlatformActionWorkerOptions<TDb>): Promise<PlatformActionWorkerCycleResult>;
1507
1613
  /** Poll until aborted. Each iteration is bounded and waits without busy-spinning. */
1508
- declare function runPlatformActionWorker<TDb>(options: PlatformActionWorkerOptions<TDb>): Promise<void>;
1509
-
1614
+ export declare function runPlatformActionWorker<TDb>(options: PlatformActionWorkerOptions<TDb>): Promise<void>;
1615
+ //#endregion
1616
+ //#region src/saga-parent-lifecycle.d.ts
1510
1617
  interface HostSagaParentLifecycleIdentity {
1511
- /** Stable identity shared by every retry of the same lifecycle transition. */
1512
- lifecycleId?: string;
1618
+ /** Stable identity shared by every retry of the same lifecycle transition. */
1619
+ lifecycleId?: string;
1513
1620
  }
1514
1621
  /**
1515
1622
  * Durable record of a single step completing within a saga parent.
1516
1623
  * Structurally compatible with {@link import("@fabricorg/platform-temporal").SagaParentProgressRecord}.
1517
1624
  */
1518
- interface HostSagaParentProgressRecord {
1519
- stepId: string;
1520
- index: number;
1521
- total: number;
1522
- completedAt: string;
1523
- }
1524
- interface HostSagaParentProgressInput extends HostSagaParentLifecycleIdentity {
1525
- parentInvocationId: string;
1526
- tenantId: string;
1527
- spaceId: string;
1528
- progress: HostSagaParentProgressRecord;
1529
- }
1530
- interface HostSagaParentApprovalInput extends HostSagaParentLifecycleIdentity {
1531
- parentInvocationId: string;
1532
- tenantId: string;
1533
- spaceId: string;
1534
- stepId: string;
1535
- approvalId: string;
1536
- reason: string;
1537
- }
1538
- interface HostSagaParentCancellationInput extends HostSagaParentLifecycleIdentity {
1539
- parentInvocationId: string;
1540
- tenantId: string;
1541
- spaceId: string;
1542
- reason: string;
1543
- actorId: string;
1544
- }
1545
- interface HostSagaParentCompletionInput extends HostSagaParentLifecycleIdentity {
1546
- parentInvocationId: string;
1547
- tenantId: string;
1548
- spaceId: string;
1549
- result: Record<string, unknown>;
1550
- }
1551
- interface HostSagaParentFailureInput extends HostSagaParentLifecycleIdentity {
1552
- parentInvocationId: string;
1553
- tenantId: string;
1554
- spaceId: string;
1555
- error: string;
1556
- compensation: HostCompensationRecord[];
1557
- }
1558
- interface HostCompensationRecord {
1559
- stepId: string;
1560
- actionId: string;
1561
- error?: string;
1625
+ export interface HostSagaParentProgressRecord {
1626
+ stepId: string;
1627
+ index: number;
1628
+ total: number;
1629
+ completedAt: string;
1630
+ }
1631
+ export interface HostSagaParentProgressInput extends HostSagaParentLifecycleIdentity {
1632
+ parentInvocationId: string;
1633
+ tenantId: string;
1634
+ spaceId: string;
1635
+ progress: HostSagaParentProgressRecord;
1636
+ }
1637
+ export interface HostSagaParentApprovalInput extends HostSagaParentLifecycleIdentity {
1638
+ parentInvocationId: string;
1639
+ tenantId: string;
1640
+ spaceId: string;
1641
+ stepId: string;
1642
+ approvalId: string;
1643
+ reason: string;
1644
+ }
1645
+ export interface HostSagaParentCancellationInput extends HostSagaParentLifecycleIdentity {
1646
+ parentInvocationId: string;
1647
+ tenantId: string;
1648
+ spaceId: string;
1649
+ reason: string;
1650
+ actorId: string;
1651
+ }
1652
+ export interface HostSagaParentCompletionInput extends HostSagaParentLifecycleIdentity {
1653
+ parentInvocationId: string;
1654
+ tenantId: string;
1655
+ spaceId: string;
1656
+ result: Record<string, unknown>;
1657
+ }
1658
+ export interface HostSagaParentFailureInput extends HostSagaParentLifecycleIdentity {
1659
+ parentInvocationId: string;
1660
+ tenantId: string;
1661
+ spaceId: string;
1662
+ error: string;
1663
+ compensation: HostCompensationRecord[];
1664
+ }
1665
+ export interface HostCompensationRecord {
1666
+ stepId: string;
1667
+ actionId: string;
1668
+ error?: string;
1562
1669
  }
1563
1670
  /**
1564
1671
  * Durable saga parent lifecycle contract backed by a Platform Host store.
@@ -1573,17 +1680,17 @@ interface HostCompensationRecord {
1573
1680
  * the persisted progress, approval park, cancellation, completion, or failure
1574
1681
  * without in-memory state.
1575
1682
  */
1576
- interface HostSagaParentLifecycle {
1577
- recordProgress(input: HostSagaParentProgressInput): Promise<void>;
1578
- parkApproval(input: HostSagaParentApprovalInput): Promise<void>;
1579
- cancel(input: HostSagaParentCancellationInput): Promise<void>;
1580
- complete(input: HostSagaParentCompletionInput): Promise<void>;
1581
- fail(input: HostSagaParentFailureInput): Promise<void>;
1582
- }
1583
- interface CreateDurableSagaParentLifecycleOptions<TDb> {
1584
- store: PlatformHostStore<TDb>;
1585
- /** Optional clock for deterministic tests. */
1586
- now?: () => Date;
1683
+ export interface HostSagaParentLifecycle {
1684
+ recordProgress(input: HostSagaParentProgressInput): Promise<void>;
1685
+ parkApproval(input: HostSagaParentApprovalInput): Promise<void>;
1686
+ cancel(input: HostSagaParentCancellationInput): Promise<void>;
1687
+ complete(input: HostSagaParentCompletionInput): Promise<void>;
1688
+ fail(input: HostSagaParentFailureInput): Promise<void>;
1689
+ }
1690
+ export interface CreateDurableSagaParentLifecycleOptions<TDb> {
1691
+ store: PlatformHostStore<TDb>;
1692
+ /** Optional clock for deterministic tests. */
1693
+ now?: () => Date;
1587
1694
  }
1588
1695
  /**
1589
1696
  * Create a {@link HostSagaParentLifecycle} backed by a Platform Host store.
@@ -1593,55 +1700,56 @@ interface CreateDurableSagaParentLifecycleOptions<TDb> {
1593
1700
  * lifecycle event and transitions the parent invocation to the appropriate
1594
1701
  * status so a fresh worker can observe the persisted state after a rollover.
1595
1702
  */
1596
- declare function createDurableSagaParentLifecycle<TDb>(options: CreateDurableSagaParentLifecycleOptions<TDb>): HostSagaParentLifecycle;
1597
-
1598
- interface TenantIsolationScope {
1599
- tenantId: string;
1600
- spaceId: string;
1601
- actorId: string;
1602
- actorType: ActorType;
1603
- }
1604
- interface TenantIsolationSubject<TDb = unknown> {
1605
- host: GovernedActionHost;
1606
- store: RecoverablePlatformHostStore<TDb>;
1607
- /** A governed action registered on the host, and parameters it accepts. */
1608
- actionId: ActionId;
1609
- parameters?: Record<string, unknown>;
1610
- /** Two scopes in different tenants. */
1611
- ours: TenantIsolationScope;
1612
- theirs: TenantIsolationScope;
1613
- /**
1614
- * Optional: a governed read the subject exposes, scoped as the projection
1615
- * host scopes it. Returns what a viewer in `scope` sees for the view. Every
1616
- * row must carry the `tenantId` it belongs to, so the check can tell a row
1617
- * of ours from a row of theirs that merely looks the same; two tenants may
1618
- * legitimately hold equal-looking rows.
1619
- */
1620
- read?(scope: TenantIsolationScope): Promise<{
1621
- allowed: boolean;
1622
- rows: readonly {
1623
- tenantId: string;
1624
- }[];
1625
- }>;
1626
- /**
1627
- * Optional: put the host and store back to a known state before a check.
1628
- * The checks tolerate accumulated state, and each retires any row it
1629
- * creates directly, so this exists for subjects whose store is shared.
1630
- */
1631
- reset?(): Promise<void> | void;
1632
- }
1633
- interface TenantIsolationCheck {
1634
- id: "fabric.tenancy.invocation-scoped-read.v1" | "fabric.tenancy.idempotency-key-scoped.v1" | "fabric.tenancy.events-scoped.v1" | "fabric.tenancy.worker-claim-scoped.v1" | "fabric.tenancy.completion-scoped.v1" | "fabric.tenancy.projection-scoped.v1" | "fabric.tenancy.adapter-invocation-read-scoped.v1" | "fabric.tenancy.adapter-invocation-write-scoped.v1";
1635
- run(subject: TenantIsolationSubject): Promise<string[]>;
1636
- }
1637
- interface TenantIsolationResult {
1638
- passed: boolean;
1639
- checks: Array<{
1640
- id: TenantIsolationCheck["id"];
1641
- status: "passed" | "failed" | "skipped";
1642
- evidence: string[];
1643
- error?: string;
1644
- }>;
1703
+ export declare function createDurableSagaParentLifecycle<TDb>(options: CreateDurableSagaParentLifecycleOptions<TDb>): HostSagaParentLifecycle;
1704
+ //#endregion
1705
+ //#region src/tenant-isolation.d.ts
1706
+ export interface TenantIsolationScope {
1707
+ tenantId: string;
1708
+ spaceId: string;
1709
+ actorId: string;
1710
+ actorType: ActorType;
1711
+ }
1712
+ export interface TenantIsolationSubject<TDb = unknown> {
1713
+ host: GovernedActionHost;
1714
+ store: RecoverablePlatformHostStore<TDb>;
1715
+ /** A governed action registered on the host, and parameters it accepts. */
1716
+ actionId: ActionId;
1717
+ parameters?: Record<string, unknown>;
1718
+ /** Two scopes in different tenants. */
1719
+ ours: TenantIsolationScope;
1720
+ theirs: TenantIsolationScope;
1721
+ /**
1722
+ * Optional: a governed read the subject exposes, scoped as the projection
1723
+ * host scopes it. Returns what a viewer in `scope` sees for the view. Every
1724
+ * row must carry the `tenantId` it belongs to, so the check can tell a row
1725
+ * of ours from a row of theirs that merely looks the same; two tenants may
1726
+ * legitimately hold equal-looking rows.
1727
+ */
1728
+ read?(scope: TenantIsolationScope): Promise<{
1729
+ allowed: boolean;
1730
+ rows: readonly {
1731
+ tenantId: string;
1732
+ }[];
1733
+ }>;
1734
+ /**
1735
+ * Optional: put the host and store back to a known state before a check.
1736
+ * The checks tolerate accumulated state, and each retires any row it
1737
+ * creates directly, so this exists for subjects whose store is shared.
1738
+ */
1739
+ reset?(): Promise<void> | void;
1740
+ }
1741
+ export interface TenantIsolationCheck {
1742
+ id: "fabric.tenancy.invocation-scoped-read.v1" | "fabric.tenancy.idempotency-key-scoped.v1" | "fabric.tenancy.events-scoped.v1" | "fabric.tenancy.worker-claim-scoped.v1" | "fabric.tenancy.completion-scoped.v1" | "fabric.tenancy.projection-scoped.v1" | "fabric.tenancy.adapter-invocation-read-scoped.v1" | "fabric.tenancy.adapter-invocation-write-scoped.v1";
1743
+ run(subject: TenantIsolationSubject): Promise<string[]>;
1744
+ }
1745
+ export interface TenantIsolationResult {
1746
+ passed: boolean;
1747
+ checks: Array<{
1748
+ id: TenantIsolationCheck["id"];
1749
+ status: "passed" | "failed" | "skipped";
1750
+ evidence: string[];
1751
+ error?: string;
1752
+ }>;
1645
1753
  }
1646
1754
  /**
1647
1755
  * The suite any deployment of the host must pass before it claims isolation.
@@ -1654,8 +1762,8 @@ interface TenantIsolationResult {
1654
1762
  * space, or owning invocation; and, when the subject lends a read, a viewer in
1655
1763
  * the other tenant sees nothing of ours.
1656
1764
  */
1657
- declare function tenantIsolationChecks(): readonly TenantIsolationCheck[];
1765
+ export declare function tenantIsolationChecks(): readonly TenantIsolationCheck[];
1658
1766
  /** Run every check, returning each result rather than throwing on the first. */
1659
- declare function runTenantIsolationChecks(subject: TenantIsolationSubject): Promise<TenantIsolationResult>;
1660
-
1661
- export { ActionAdmissionError, type ActionAdmissionRefusal, type ActionApprovalDecision, type ActionAuthorizationInput, type ActionExecutionAuthorizationInput, type ActionExecutionReason, type ActionInvocationPatch, type ActionInvocationRecord, type AdapterInvocationRecord, type AdapterInvocationScope, type AdapterInvocationStatus, type AdapterReconciliationOutcome, type ApprovalDecisionTransitionResult, type ApprovalPlatformHostStore, type AtomicMutationPlatformHostStore, type AuthorizationBinding, type AuthorizationGoverningMoment, type AuthorizationReconciliationOutcome, type BeginApprovalDecisionInput, type ClaimActionInvocationsInput, type ClaimOutboxInput, type CreateActionInvocationInput, type CreateDurableSagaParentLifecycleOptions, type DispatchActionInput, type DispatchActionResult, type EnterpriseEventActorDisclosure, type EnterpriseEventEnvelope, type EnterpriseEventPublishContext, type EnterpriseEventPublisher, type ErrorTextRedactionContext, type EventPayloadClassification, type ExecuteActionResult, type ExecuteInvocationOptions, type ExecutionAttestationRecord, type ExternalCompletion, ExternalCompletionError, type ExternalCompletionRefusal, type ExternalReconciliationRecord, type GovernancePlatformHostStore, type GovernedActionHost, type HitlDecisionEvidence, type HostCompensationRecord, type HostSagaParentApprovalInput, type HostSagaParentCancellationInput, type HostSagaParentCompletionInput, type HostSagaParentFailureInput, type HostSagaParentLifecycle, type HostSagaParentProgressInput, type HostSagaParentProgressRecord, type IdempotencyConflict, IdempotencyConflictError, type InvocationProvenance, type InvocationSource, type KnownActionExecutionReason, type ListActionInvocationsInput, MemoryPlatformHostStore, type MemoryPlatformHostTransactionProvider, type NamespacedAttributes, type OutboxActorDisclosure, type OutboxEventMetadata, type OutboxPlatformHostStore, type OutboxRecord, type OutboxRelayOptions, type OutboxRelayResult, type OutboxRequeueAuthorizationInput, type OutboxRequeueHost, type OutboxRequeuePlatformHostStore, type OutboxRequeueRecord, type OutboxRequeueRefusal, type OutboxStatus, PARAMETER_DIGEST_ALGORITHM, PLATFORM_HOST_CONTRACT_VERSION, PLATFORM_HOST_HEALTH_CONTRACT_VERSION, PLATFORM_HOST_METRIC_NAMES, type PendingAssetEvent, type PendingExternalCompletion, type PersistedActionApprovalDecision, type PlatformActionDispatcher, type PlatformActionWorkerCycleResult, type PlatformActionWorkerOptions, type PlatformHostAuthorization, type PlatformHostHealthCounts, type PlatformHostHealthOptions, type PlatformHostHealthQuery, type PlatformHostHealthSnapshot, type PlatformHostHealthStatus, type PlatformHostHealthStore, type PlatformHostLifecycleTelemetry, type PlatformHostMetricName, type PlatformHostMetricTelemetry, type PlatformHostMetricType, type PlatformHostMutationTransaction, type PlatformHostOptions, type PlatformHostReadinessReason, type PlatformHostSqlClient, type PlatformHostSqlResult, type PlatformHostStore, type PlatformHostTelemetry, type PlatformHostTelemetryAttribute, type PlatformHostTelemetryEventName, type PlatformHostTelemetryHook, type PlatformHostTelemetryInput, type PlatformHostTelemetryRecord, type PlatformHostWorkerHealthInput, type PolicyEvaluationRecord, type PolicyObligationRecord, type PostgresMigration, PostgresPlatformHostStore, type PostgresPlatformHostTransactionContext, type PostgresPlatformHostTransactionProvider, type ReconcileOverdueCompletionsInput, type RecordedExternalCompletion, type RecoverablePlatformHostStore, type RenewActionInvocationLeaseInput, type RequeueOutboxDeadLetterInput, type RequeueOutboxDeadLetterRefusal, type RequeueOutboxDeadLetterResult, type RequeueOutboxDeadLetterStoreInput, type RequeueOutboxDeadLetterStoreResult, type ResolvePoliciesInput, type SubmitActionInput, type SubmitActionResult, type TenantIsolationCheck, type TenantIsolationResult, type TenantIsolationScope, type TenantIsolationSubject, type UpdateLeasedActionInvocationInput, applyPostgresMigrations, cloneOutboxRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, getPlatformHostHealthSnapshot, outboxActorDisclosure, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, runTenantIsolationChecks, tenantIsolationChecks, toEnterpriseEventEnvelope };
1767
+ export declare function runTenantIsolationChecks(subject: TenantIsolationSubject): Promise<TenantIsolationResult>;
1768
+ //#endregion
1769
+ export { canonicalJson };