@fabricorg/platform-host 7.0.0 → 7.1.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.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActorType, ActionId, ActionStatus, AgentActionRoute, AgentActionRiskTier, MutationFootprint, ExecutionPrincipal, GovernanceRuntimeEvidence, PolicyOutcome, AssetEventEnvelope, ExecutionAttestation, ExternalReconciliation, PolicyObligation, PolicyObligationStatus, ModuleRegistry, ActionDefinition, AdapterImplementation, FabricRuntimeServices, AgentActionPolicyEvaluator, MutationGovernanceResolver, RuntimePolicyDefinition } from '@fabricorg/platform';
1
+ import { ActorType, ActionId, ActionStatus, EvidencePacketReference, AgentActionRoute, AgentActionRiskTier, MutationFootprint, ExecutionPrincipal, GovernanceRuntimeEvidence, PolicyOutcome, AssetEventEnvelope, ExecutionAttestation, ExternalReconciliation, PolicyObligation, PolicyObligationStatus, ModuleRegistry, ActionDefinition, AdapterImplementation, FabricRuntimeServices, AgentActionPolicyEvaluator, MutationGovernanceResolver, RuntimePolicyDefinition } from '@fabricorg/platform';
2
2
  import { AssemblyLockfile } from '@fabricorg/assembly';
3
3
 
4
4
  /** Version of the vendor-neutral health/readiness contract. */
@@ -185,6 +185,20 @@ declare class IdempotencyConflictError extends Error {
185
185
  readonly code: "IDEMPOTENCY_CONFLICT";
186
186
  constructor(conflict: IdempotencyConflict);
187
187
  }
188
+ type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting" | "immediate_contract" | "reference_mismatch" | "provider_mismatch" | "invalid_completion" | "result_invalid";
189
+ /**
190
+ * Why a completion was not applied, typed so a webhook handler can answer
191
+ * the external system correctly: `retryable` means the invocation is still
192
+ * being finalized and the same callback will be accepted once it parks, so
193
+ * answer with something the sender retries; anything else is permanent and
194
+ * a retry will get the same refusal.
195
+ */
196
+ declare class ExternalCompletionError extends Error {
197
+ readonly refusal: ExternalCompletionRefusal;
198
+ readonly code: "EXTERNAL_COMPLETION_REFUSED";
199
+ constructor(refusal: ExternalCompletionRefusal, message: string);
200
+ get retryable(): boolean;
201
+ }
188
202
  interface PendingAssetEvent {
189
203
  eventType: string;
190
204
  subjectType: string;
@@ -216,6 +230,14 @@ interface ActionInvocationRecord {
216
230
  authorizationReconciliation?: AuthorizationReconciliationOutcome;
217
231
  /** Durable evidence when an adapter returned an ambiguous outcome requiring reconciliation. */
218
232
  adapterReconciliation?: AdapterReconciliationOutcome;
233
+ /**
234
+ * A handoff the host is waiting on. While present the invocation is
235
+ * `running` without a lease: it is not stuck, it is somebody else's turn,
236
+ * and the recovery worker must not re-execute it.
237
+ */
238
+ pendingCompletion?: PendingExternalCompletion;
239
+ /** The completion an external system delivered, kept so a repeat is recognised and a contradiction is caught. */
240
+ externalCompletion?: RecordedExternalCompletion;
219
241
  /** Opaque, non-secret reference used to revalidate delegated execution authority. */
220
242
  authorizationBindingId?: string;
221
243
  attemptCount: number;
@@ -290,6 +312,49 @@ interface ExternalReconciliationRecord extends ExternalReconciliation {
290
312
  tenantId: string;
291
313
  spaceId: string;
292
314
  }
315
+ interface PendingExternalCompletion {
316
+ provider: string;
317
+ adapterType: string;
318
+ operation: string;
319
+ adapterInvocationId: string;
320
+ externalReference: string;
321
+ acceptedAt: Date;
322
+ /** Past this instant the host moves the invocation to reconciliation. */
323
+ dueAt?: Date;
324
+ /**
325
+ * Set when the invocation finished executing and parked. A handoff is
326
+ * recorded before the remaining steps run, so until this is set a
327
+ * completion has nothing settled to settle into; it is asked to retry.
328
+ */
329
+ parkedAt?: Date;
330
+ }
331
+ /**
332
+ * What an external system reports when it finishes work the host accepted.
333
+ *
334
+ * Matched to the invocation by `externalReference`, never by guesswork: a
335
+ * completion that names a reference the invocation is not waiting on is
336
+ * refused, because completing the wrong invocation is worse than dropping a
337
+ * callback.
338
+ */
339
+ interface ExternalCompletion {
340
+ externalReference: string;
341
+ outcome: "completed" | "failed";
342
+ /** Merged over the handler's result on completion. */
343
+ result?: Record<string, unknown>;
344
+ error?: string;
345
+ provider?: string;
346
+ evidenceReferences?: EvidencePacketReference[];
347
+ observedAt: Date | string;
348
+ }
349
+ interface RecordedExternalCompletion extends ExternalCompletion {
350
+ recordedAt: Date;
351
+ }
352
+ interface ReconcileOverdueCompletionsInput {
353
+ tenantId?: string;
354
+ spaceId?: string;
355
+ limit?: number;
356
+ now?: Date;
357
+ }
293
358
  type AdapterInvocationStatus = "running" | "succeeded" | "failed" | "ambiguous";
294
359
  interface AdapterReconciliationOutcome {
295
360
  kind: "adapter_outcome_ambiguous";
@@ -330,7 +395,7 @@ interface PlatformHostStore<TDb> {
330
395
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
331
396
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
332
397
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
333
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
398
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
334
399
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
335
400
  createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
336
401
  getAdapterInvocation(id: string): Promise<AdapterInvocationRecord | undefined>;
@@ -364,7 +429,7 @@ interface PlatformHostMutationTransaction<TDb> {
364
429
  nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
365
430
  listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
366
431
  getEntityState?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
367
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
432
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
368
433
  updateLeasedActionInvocation?(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
369
434
  }
370
435
  type OutboxStatus = "pending" | "published" | "dead_letter";
@@ -496,6 +561,12 @@ interface ListActionInvocationsInput {
496
561
  spaceId?: string;
497
562
  statuses?: readonly ActionStatus[];
498
563
  updatedBefore?: Date;
564
+ /** Only invocations holding a pending external completion. */
565
+ awaitingCompletion?: boolean;
566
+ /** Only pending completions due at or before this instant. Implies `awaitingCompletion`. */
567
+ completionDueBefore?: Date;
568
+ /** Only invocations no worker holds a lease on. */
569
+ unleased?: boolean;
499
570
  limit?: number;
500
571
  }
501
572
  interface ClaimActionInvocationsInput {
@@ -506,7 +577,20 @@ interface ClaimActionInvocationsInput {
506
577
  spaceId?: string;
507
578
  now?: Date;
508
579
  }
509
- type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>;
580
+ /**
581
+ * What the host writes back to an invocation.
582
+ *
583
+ * Store obligations for `pendingCompletion`, which a custom store must honour
584
+ * or the recovery worker will re-run an external handoff:
585
+ * - a patch that sets `pendingCompletion` together with `status: "running"`
586
+ * parks the invocation and must clear its lease;
587
+ * - a patch that sets `pendingCompletion` without a status records the handoff
588
+ * and must leave the lease alone;
589
+ * - a patch with `pendingCompletion: undefined` clears it;
590
+ * - `claimActionInvocations` must never claim a running invocation without a
591
+ * lease, which is what a parked invocation is.
592
+ */
593
+ type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation" | "pendingCompletion" | "externalCompletion">>;
510
594
  interface UpdateLeasedActionInvocationInput {
511
595
  id: string;
512
596
  tenantId: string;
@@ -609,6 +693,8 @@ interface SubmitActionResult {
609
693
  error?: string;
610
694
  reconciliation?: AuthorizationReconciliationOutcome;
611
695
  adapterReconciliation?: AdapterReconciliationOutcome;
696
+ /** Present while the invocation waits for an external system to complete it. */
697
+ pendingCompletion?: PendingExternalCompletion;
612
698
  /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
613
699
  consistency?: "authoritative-now" | "provisional-until-reconciled";
614
700
  hitlRoute?: AgentActionRoute;
@@ -621,6 +707,8 @@ interface ExecuteActionResult {
621
707
  error?: string;
622
708
  reconciliation?: AuthorizationReconciliationOutcome;
623
709
  adapterReconciliation?: AdapterReconciliationOutcome;
710
+ /** Present while the invocation waits for an external system to complete it. */
711
+ pendingCompletion?: PendingExternalCompletion;
624
712
  /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
625
713
  consistency?: "authoritative-now" | "provisional-until-reconciled";
626
714
  hitlRoute?: AgentActionRoute;
@@ -645,6 +733,12 @@ interface PlatformActionWorkerOptions<TDb> {
645
733
  signal?: AbortSignal;
646
734
  onError?: (error: unknown, invocation?: ActionInvocationRecord) => void;
647
735
  telemetry?: PlatformHostTelemetry;
736
+ /**
737
+ * Sweep overdue external handoffs each cycle. Defaults to on. Turn it off
738
+ * for a store without the governance seam, where the sweep would refuse
739
+ * on every cycle, and run the sweep elsewhere.
740
+ */
741
+ sweepOverdueCompletions?: boolean;
648
742
  }
649
743
  interface PlatformActionWorkerCycleResult {
650
744
  claimed: number;
@@ -746,6 +840,20 @@ interface GovernedActionHost {
746
840
  resumeApprovedInvocation(actionInvocationId: string, tenantId: string, spaceId: string, decision: ActionApprovalDecision): Promise<ExecuteActionResult>;
747
841
  recordExecutionAttestation(actionInvocationId: string, tenantId: string, spaceId: string, attestation: ExecutionAttestation): Promise<void>;
748
842
  recordExternalReconciliation(actionInvocationId: string, tenantId: string, spaceId: string, reconciliation: ExternalReconciliation): Promise<void>;
843
+ /**
844
+ * Complete an invocation an adapter handed off, by the reference the
845
+ * external system was given. Idempotent for a repeated identical
846
+ * completion; a contradictory one moves the invocation to reconciliation.
847
+ */
848
+ completeExternalInvocation(actionInvocationId: string, tenantId: string, spaceId: string, completion: ExternalCompletion): Promise<ExecuteActionResult>;
849
+ /**
850
+ * Move handoffs past their deadline to `reconciliation_required`, so a
851
+ * callback that never comes is a finding and not a silent wait. The
852
+ * pending handoff is kept, so a late completion can still land.
853
+ */
854
+ reconcileOverdueCompletions(input?: ReconcileOverdueCompletionsInput): Promise<{
855
+ overdue: string[];
856
+ }>;
749
857
  }
750
858
 
751
859
  declare function createGovernedActionHost<TDb>(options: PlatformHostOptions<TDb>): GovernedActionHost;
@@ -772,7 +880,7 @@ declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostSto
772
880
  private runTransactionWithEvents;
773
881
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
774
882
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
775
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
883
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
776
884
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
777
885
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
778
886
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
@@ -884,7 +992,7 @@ declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostS
884
992
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
885
993
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
886
994
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
887
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
995
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
888
996
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
889
997
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
890
998
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
@@ -1051,4 +1159,4 @@ interface CreateDurableSagaParentLifecycleOptions<TDb> {
1051
1159
  */
1052
1160
  declare function createDurableSagaParentLifecycle<TDb>(options: CreateDurableSagaParentLifecycleOptions<TDb>): HostSagaParentLifecycle;
1053
1161
 
1054
- export { type ActionApprovalDecision, type ActionAuthorizationInput, type ActionExecutionAuthorizationInput, type ActionExecutionReason, type ActionInvocationPatch, type ActionInvocationRecord, type AdapterInvocationRecord, 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 EnterpriseEventEnvelope, type EnterpriseEventPublisher, type EventPayloadClassification, type ExecuteActionResult, type ExecuteInvocationOptions, type ExecutionAttestationRecord, 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 OutboxEventMetadata, type OutboxPlatformHostStore, type OutboxRecord, type OutboxRelayOptions, type OutboxRelayResult, type OutboxStatus, PARAMETER_DIGEST_ALGORITHM, PLATFORM_HOST_CONTRACT_VERSION, PLATFORM_HOST_HEALTH_CONTRACT_VERSION, PLATFORM_HOST_METRIC_NAMES, type PendingAssetEvent, 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 RecoverablePlatformHostStore, type RenewActionInvocationLeaseInput, type SubmitActionInput, type SubmitActionResult, type UpdateLeasedActionInvocationInput, applyPostgresMigrations, canonicalJson, cloneOutboxRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, getPlatformHostHealthSnapshot, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, toEnterpriseEventEnvelope };
1162
+ export { type ActionApprovalDecision, type ActionAuthorizationInput, type ActionExecutionAuthorizationInput, type ActionExecutionReason, type ActionInvocationPatch, type ActionInvocationRecord, type AdapterInvocationRecord, 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 EnterpriseEventEnvelope, type EnterpriseEventPublisher, 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 OutboxEventMetadata, type OutboxPlatformHostStore, type OutboxRecord, type OutboxRelayOptions, type OutboxRelayResult, 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 SubmitActionInput, type SubmitActionResult, type UpdateLeasedActionInvocationInput, applyPostgresMigrations, canonicalJson, cloneOutboxRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, getPlatformHostHealthSnapshot, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, toEnterpriseEventEnvelope };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ActorType, ActionId, ActionStatus, AgentActionRoute, AgentActionRiskTier, MutationFootprint, ExecutionPrincipal, GovernanceRuntimeEvidence, PolicyOutcome, AssetEventEnvelope, ExecutionAttestation, ExternalReconciliation, PolicyObligation, PolicyObligationStatus, ModuleRegistry, ActionDefinition, AdapterImplementation, FabricRuntimeServices, AgentActionPolicyEvaluator, MutationGovernanceResolver, RuntimePolicyDefinition } from '@fabricorg/platform';
1
+ import { ActorType, ActionId, ActionStatus, EvidencePacketReference, AgentActionRoute, AgentActionRiskTier, MutationFootprint, ExecutionPrincipal, GovernanceRuntimeEvidence, PolicyOutcome, AssetEventEnvelope, ExecutionAttestation, ExternalReconciliation, PolicyObligation, PolicyObligationStatus, ModuleRegistry, ActionDefinition, AdapterImplementation, FabricRuntimeServices, AgentActionPolicyEvaluator, MutationGovernanceResolver, RuntimePolicyDefinition } from '@fabricorg/platform';
2
2
  import { AssemblyLockfile } from '@fabricorg/assembly';
3
3
 
4
4
  /** Version of the vendor-neutral health/readiness contract. */
@@ -185,6 +185,20 @@ declare class IdempotencyConflictError extends Error {
185
185
  readonly code: "IDEMPOTENCY_CONFLICT";
186
186
  constructor(conflict: IdempotencyConflict);
187
187
  }
188
+ type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting" | "immediate_contract" | "reference_mismatch" | "provider_mismatch" | "invalid_completion" | "result_invalid";
189
+ /**
190
+ * Why a completion was not applied, typed so a webhook handler can answer
191
+ * the external system correctly: `retryable` means the invocation is still
192
+ * being finalized and the same callback will be accepted once it parks, so
193
+ * answer with something the sender retries; anything else is permanent and
194
+ * a retry will get the same refusal.
195
+ */
196
+ declare class ExternalCompletionError extends Error {
197
+ readonly refusal: ExternalCompletionRefusal;
198
+ readonly code: "EXTERNAL_COMPLETION_REFUSED";
199
+ constructor(refusal: ExternalCompletionRefusal, message: string);
200
+ get retryable(): boolean;
201
+ }
188
202
  interface PendingAssetEvent {
189
203
  eventType: string;
190
204
  subjectType: string;
@@ -216,6 +230,14 @@ interface ActionInvocationRecord {
216
230
  authorizationReconciliation?: AuthorizationReconciliationOutcome;
217
231
  /** Durable evidence when an adapter returned an ambiguous outcome requiring reconciliation. */
218
232
  adapterReconciliation?: AdapterReconciliationOutcome;
233
+ /**
234
+ * A handoff the host is waiting on. While present the invocation is
235
+ * `running` without a lease: it is not stuck, it is somebody else's turn,
236
+ * and the recovery worker must not re-execute it.
237
+ */
238
+ pendingCompletion?: PendingExternalCompletion;
239
+ /** The completion an external system delivered, kept so a repeat is recognised and a contradiction is caught. */
240
+ externalCompletion?: RecordedExternalCompletion;
219
241
  /** Opaque, non-secret reference used to revalidate delegated execution authority. */
220
242
  authorizationBindingId?: string;
221
243
  attemptCount: number;
@@ -290,6 +312,49 @@ interface ExternalReconciliationRecord extends ExternalReconciliation {
290
312
  tenantId: string;
291
313
  spaceId: string;
292
314
  }
315
+ interface PendingExternalCompletion {
316
+ provider: string;
317
+ adapterType: string;
318
+ operation: string;
319
+ adapterInvocationId: string;
320
+ externalReference: string;
321
+ acceptedAt: Date;
322
+ /** Past this instant the host moves the invocation to reconciliation. */
323
+ dueAt?: Date;
324
+ /**
325
+ * Set when the invocation finished executing and parked. A handoff is
326
+ * recorded before the remaining steps run, so until this is set a
327
+ * completion has nothing settled to settle into; it is asked to retry.
328
+ */
329
+ parkedAt?: Date;
330
+ }
331
+ /**
332
+ * What an external system reports when it finishes work the host accepted.
333
+ *
334
+ * Matched to the invocation by `externalReference`, never by guesswork: a
335
+ * completion that names a reference the invocation is not waiting on is
336
+ * refused, because completing the wrong invocation is worse than dropping a
337
+ * callback.
338
+ */
339
+ interface ExternalCompletion {
340
+ externalReference: string;
341
+ outcome: "completed" | "failed";
342
+ /** Merged over the handler's result on completion. */
343
+ result?: Record<string, unknown>;
344
+ error?: string;
345
+ provider?: string;
346
+ evidenceReferences?: EvidencePacketReference[];
347
+ observedAt: Date | string;
348
+ }
349
+ interface RecordedExternalCompletion extends ExternalCompletion {
350
+ recordedAt: Date;
351
+ }
352
+ interface ReconcileOverdueCompletionsInput {
353
+ tenantId?: string;
354
+ spaceId?: string;
355
+ limit?: number;
356
+ now?: Date;
357
+ }
293
358
  type AdapterInvocationStatus = "running" | "succeeded" | "failed" | "ambiguous";
294
359
  interface AdapterReconciliationOutcome {
295
360
  kind: "adapter_outcome_ambiguous";
@@ -330,7 +395,7 @@ interface PlatformHostStore<TDb> {
330
395
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
331
396
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
332
397
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
333
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
398
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
334
399
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
335
400
  createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
336
401
  getAdapterInvocation(id: string): Promise<AdapterInvocationRecord | undefined>;
@@ -364,7 +429,7 @@ interface PlatformHostMutationTransaction<TDb> {
364
429
  nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
365
430
  listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
366
431
  getEntityState?(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<string | undefined>;
367
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
432
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
368
433
  updateLeasedActionInvocation?(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
369
434
  }
370
435
  type OutboxStatus = "pending" | "published" | "dead_letter";
@@ -496,6 +561,12 @@ interface ListActionInvocationsInput {
496
561
  spaceId?: string;
497
562
  statuses?: readonly ActionStatus[];
498
563
  updatedBefore?: Date;
564
+ /** Only invocations holding a pending external completion. */
565
+ awaitingCompletion?: boolean;
566
+ /** Only pending completions due at or before this instant. Implies `awaitingCompletion`. */
567
+ completionDueBefore?: Date;
568
+ /** Only invocations no worker holds a lease on. */
569
+ unleased?: boolean;
499
570
  limit?: number;
500
571
  }
501
572
  interface ClaimActionInvocationsInput {
@@ -506,7 +577,20 @@ interface ClaimActionInvocationsInput {
506
577
  spaceId?: string;
507
578
  now?: Date;
508
579
  }
509
- type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>;
580
+ /**
581
+ * What the host writes back to an invocation.
582
+ *
583
+ * Store obligations for `pendingCompletion`, which a custom store must honour
584
+ * or the recovery worker will re-run an external handoff:
585
+ * - a patch that sets `pendingCompletion` together with `status: "running"`
586
+ * parks the invocation and must clear its lease;
587
+ * - a patch that sets `pendingCompletion` without a status records the handoff
588
+ * and must leave the lease alone;
589
+ * - a patch with `pendingCompletion: undefined` clears it;
590
+ * - `claimActionInvocations` must never claim a running invocation without a
591
+ * lease, which is what a parked invocation is.
592
+ */
593
+ type ActionInvocationPatch = Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation" | "pendingCompletion" | "externalCompletion">>;
510
594
  interface UpdateLeasedActionInvocationInput {
511
595
  id: string;
512
596
  tenantId: string;
@@ -609,6 +693,8 @@ interface SubmitActionResult {
609
693
  error?: string;
610
694
  reconciliation?: AuthorizationReconciliationOutcome;
611
695
  adapterReconciliation?: AdapterReconciliationOutcome;
696
+ /** Present while the invocation waits for an external system to complete it. */
697
+ pendingCompletion?: PendingExternalCompletion;
612
698
  /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
613
699
  consistency?: "authoritative-now" | "provisional-until-reconciled";
614
700
  hitlRoute?: AgentActionRoute;
@@ -621,6 +707,8 @@ interface ExecuteActionResult {
621
707
  error?: string;
622
708
  reconciliation?: AuthorizationReconciliationOutcome;
623
709
  adapterReconciliation?: AdapterReconciliationOutcome;
710
+ /** Present while the invocation waits for an external system to complete it. */
711
+ pendingCompletion?: PendingExternalCompletion;
624
712
  /** Mirrors the action's declared consistency so a caller knows whether the result is settled. */
625
713
  consistency?: "authoritative-now" | "provisional-until-reconciled";
626
714
  hitlRoute?: AgentActionRoute;
@@ -645,6 +733,12 @@ interface PlatformActionWorkerOptions<TDb> {
645
733
  signal?: AbortSignal;
646
734
  onError?: (error: unknown, invocation?: ActionInvocationRecord) => void;
647
735
  telemetry?: PlatformHostTelemetry;
736
+ /**
737
+ * Sweep overdue external handoffs each cycle. Defaults to on. Turn it off
738
+ * for a store without the governance seam, where the sweep would refuse
739
+ * on every cycle, and run the sweep elsewhere.
740
+ */
741
+ sweepOverdueCompletions?: boolean;
648
742
  }
649
743
  interface PlatformActionWorkerCycleResult {
650
744
  claimed: number;
@@ -746,6 +840,20 @@ interface GovernedActionHost {
746
840
  resumeApprovedInvocation(actionInvocationId: string, tenantId: string, spaceId: string, decision: ActionApprovalDecision): Promise<ExecuteActionResult>;
747
841
  recordExecutionAttestation(actionInvocationId: string, tenantId: string, spaceId: string, attestation: ExecutionAttestation): Promise<void>;
748
842
  recordExternalReconciliation(actionInvocationId: string, tenantId: string, spaceId: string, reconciliation: ExternalReconciliation): Promise<void>;
843
+ /**
844
+ * Complete an invocation an adapter handed off, by the reference the
845
+ * external system was given. Idempotent for a repeated identical
846
+ * completion; a contradictory one moves the invocation to reconciliation.
847
+ */
848
+ completeExternalInvocation(actionInvocationId: string, tenantId: string, spaceId: string, completion: ExternalCompletion): Promise<ExecuteActionResult>;
849
+ /**
850
+ * Move handoffs past their deadline to `reconciliation_required`, so a
851
+ * callback that never comes is a finding and not a silent wait. The
852
+ * pending handoff is kept, so a late completion can still land.
853
+ */
854
+ reconcileOverdueCompletions(input?: ReconcileOverdueCompletionsInput): Promise<{
855
+ overdue: string[];
856
+ }>;
749
857
  }
750
858
 
751
859
  declare function createGovernedActionHost<TDb>(options: PlatformHostOptions<TDb>): GovernedActionHost;
@@ -772,7 +880,7 @@ declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostSto
772
880
  private runTransactionWithEvents;
773
881
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
774
882
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
775
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
883
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
776
884
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
777
885
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
778
886
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
@@ -884,7 +992,7 @@ declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostS
884
992
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
885
993
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
886
994
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
887
- updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: Partial<Pick<ActionInvocationRecord, "status" | "result" | "error" | "authorizationReconciliation" | "adapterReconciliation">>): Promise<void>;
995
+ updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
888
996
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
889
997
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
890
998
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
@@ -1051,4 +1159,4 @@ interface CreateDurableSagaParentLifecycleOptions<TDb> {
1051
1159
  */
1052
1160
  declare function createDurableSagaParentLifecycle<TDb>(options: CreateDurableSagaParentLifecycleOptions<TDb>): HostSagaParentLifecycle;
1053
1161
 
1054
- export { type ActionApprovalDecision, type ActionAuthorizationInput, type ActionExecutionAuthorizationInput, type ActionExecutionReason, type ActionInvocationPatch, type ActionInvocationRecord, type AdapterInvocationRecord, 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 EnterpriseEventEnvelope, type EnterpriseEventPublisher, type EventPayloadClassification, type ExecuteActionResult, type ExecuteInvocationOptions, type ExecutionAttestationRecord, 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 OutboxEventMetadata, type OutboxPlatformHostStore, type OutboxRecord, type OutboxRelayOptions, type OutboxRelayResult, type OutboxStatus, PARAMETER_DIGEST_ALGORITHM, PLATFORM_HOST_CONTRACT_VERSION, PLATFORM_HOST_HEALTH_CONTRACT_VERSION, PLATFORM_HOST_METRIC_NAMES, type PendingAssetEvent, 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 RecoverablePlatformHostStore, type RenewActionInvocationLeaseInput, type SubmitActionInput, type SubmitActionResult, type UpdateLeasedActionInvocationInput, applyPostgresMigrations, canonicalJson, cloneOutboxRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, getPlatformHostHealthSnapshot, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, toEnterpriseEventEnvelope };
1162
+ export { type ActionApprovalDecision, type ActionAuthorizationInput, type ActionExecutionAuthorizationInput, type ActionExecutionReason, type ActionInvocationPatch, type ActionInvocationRecord, type AdapterInvocationRecord, 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 EnterpriseEventEnvelope, type EnterpriseEventPublisher, 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 OutboxEventMetadata, type OutboxPlatformHostStore, type OutboxRecord, type OutboxRelayOptions, type OutboxRelayResult, 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 SubmitActionInput, type SubmitActionResult, type UpdateLeasedActionInvocationInput, applyPostgresMigrations, canonicalJson, cloneOutboxRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, getPlatformHostHealthSnapshot, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, toEnterpriseEventEnvelope };