@fabricorg/platform-host 8.2.0 → 8.3.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,4 +1,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";
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, StagedInvocationRequest, canonicalJson } from "@fabricorg/platform";
2
2
  import { AssemblyLockfile } from "@fabricorg/assembly";
3
3
  //#region src/observability.d.ts
4
4
  /** Version of the vendor-neutral health/readiness contract. */
@@ -218,6 +218,14 @@ export declare class ActionAdmissionError extends Error {
218
218
  /** The check's own code, present only for `refused`. */
219
219
  refusalCode?: string | undefined);
220
220
  }
221
+ export type SubmissionRefusal = "entitlement" | "authorization";
222
+ /** A definitive authorization-boundary refusal before an invocation is created. */
223
+ export declare class SubmissionRefusalError extends Error {
224
+ readonly actionId: string;
225
+ readonly refusal: SubmissionRefusal;
226
+ readonly code: "ACTION_SUBMISSION_REFUSED";
227
+ constructor(actionId: string, refusal: SubmissionRefusal, message: string);
228
+ }
221
229
  export type ExternalCompletionRefusal = "still_executing" | "not_found" | "not_awaiting" | "immediate_contract" | "reference_mismatch" | "provider_mismatch" | "invalid_completion" | "result_invalid" | "redaction_failed";
222
230
  /**
223
231
  * Why a completion was not applied, typed so a webhook handler can answer
@@ -259,6 +267,12 @@ export interface FinalizationCheckpoint {
259
267
  payload: import("@fabricorg/platform").FinalizationJson;
260
268
  };
261
269
  skipped: number[];
270
+ /** Handler requests retained so finalization replay stages the identical batch. */
271
+ stagedInvocations?: readonly import("@fabricorg/platform").StagedInvocationRequest[];
272
+ }
273
+ export interface StagedInvocationOrigin {
274
+ parentInvocationId: string;
275
+ stageKey: string;
262
276
  }
263
277
  export interface ActionInvocationRecord {
264
278
  id: string;
@@ -278,6 +292,8 @@ export interface ActionInvocationRecord {
278
292
  parameterDigestAlgorithm?: "fabric-canonical-json-sha256-v1";
279
293
  idempotencyActorId?: string;
280
294
  idempotencyAuthorizationBindingId?: string;
295
+ /** Host-only identity for a staged child; public submissions cannot set it. */
296
+ stagedOrigin?: StagedInvocationOrigin;
281
297
  provenance?: Omit<InvocationProvenance, "traceAttributes">;
282
298
  authorizationBinding?: AuthorizationBinding;
283
299
  executionReason?: ActionExecutionReason;
@@ -479,7 +495,7 @@ export interface AdapterInvocationRecord {
479
495
  createdAt: Date;
480
496
  updatedAt: Date;
481
497
  }
482
- export interface CreateActionInvocationInput extends Omit<ActionInvocationRecord, "createdAt" | "updatedAt" | "attemptCount" | "leaseOwner" | "leaseExpiresAt" | "leaseToken"> {}
498
+ export interface CreateActionInvocationInput extends Omit<ActionInvocationRecord, "createdAt" | "updatedAt" | "attemptCount" | "leaseOwner" | "leaseExpiresAt" | "leaseToken" | "stagedOrigin"> {}
483
499
  /** Scope of an adapter checkpoint within its owning action invocation. */
484
500
  export interface AdapterInvocationScope {
485
501
  tenantId: string;
@@ -537,6 +553,8 @@ export interface PlatformHostStore<TDb> {
537
553
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
538
554
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
539
555
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
556
+ /** Resolve Host-owned staged identity within one tenant and space. */
557
+ getActionInvocationByStagedOrigin?(tenantId: string, spaceId: string, origin: StagedInvocationOrigin): Promise<ActionInvocationRecord | undefined>;
540
558
  updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
541
559
  appendPolicyEvaluation(record: PolicyEvaluationRecord): Promise<void>;
542
560
  createAdapterInvocation(record: AdapterInvocationRecord): Promise<void>;
@@ -668,6 +686,135 @@ export interface PlatformHostMutationTransaction<TDb> {
668
686
  * governance evidence cannot share the event/verdict transaction.
669
687
  */
670
688
  appendExternalReconciliation?: GovernancePlatformHostStore<TDb>["appendExternalReconciliation"];
689
+ /** Atomically retain an immutable staged batch with the parent mutation. */
690
+ stageInvocations?(records: readonly StagedInvocationRecord[]): Promise<void>;
691
+ }
692
+ export type StagedInvocationStatus = "pending" | "dispatched" | "rejected" | "dead_lettered" | "cancelled";
693
+ export interface StagedInvocationRecord {
694
+ id: string;
695
+ tenantId: string;
696
+ spaceId: string;
697
+ parentInvocationId: string;
698
+ parentActionId: ActionId;
699
+ key: string;
700
+ actionId: ActionId;
701
+ expectedActionVersion: number;
702
+ parameters: Record<string, unknown>;
703
+ parameterDigest: string;
704
+ batchDigest: string;
705
+ status: StagedInvocationStatus;
706
+ /**
707
+ * The child's id, recorded by the first settlement whose attempt knew it.
708
+ * A settlement without an id leaves an earlier one in place. After a crash
709
+ * between child creation and settlement it stays absent until a later
710
+ * attempt finds the child by its staged origin.
711
+ */
712
+ childInvocationId?: string;
713
+ attemptCount: number;
714
+ availableAt: Date;
715
+ leaseOwner?: string;
716
+ leaseExpiresAt?: Date;
717
+ leaseToken: number;
718
+ lastError?: string;
719
+ createdAt: Date;
720
+ updatedAt: Date;
721
+ }
722
+ export interface ClaimStagedInvocationsInput {
723
+ workerId: string;
724
+ leaseDurationMs: number;
725
+ limit?: number;
726
+ tenantId?: string;
727
+ spaceId?: string;
728
+ now?: Date;
729
+ }
730
+ export interface CreateStagedActionInvocationInput {
731
+ stageId: string;
732
+ workerId: string;
733
+ leaseToken: number;
734
+ now?: Date;
735
+ invocation: CreateActionInvocationInput & {
736
+ stagedOrigin: StagedInvocationOrigin;
737
+ };
738
+ }
739
+ export type CreateStagedActionInvocationResult = {
740
+ kind: "created" | "existing";
741
+ invocation: ActionInvocationRecord;
742
+ } | {
743
+ kind: "lease_lost";
744
+ };
745
+ /** Optional durable capability for transactional staging and post-completion dispatch. */
746
+ export interface StagedInvocationPlatformHostStore<TDb> extends PlatformHostStore<TDb> {
747
+ readonly transactionalStagedInvocations?: boolean;
748
+ getActionInvocationByStagedOrigin(tenantId: string, spaceId: string, origin: StagedInvocationOrigin): Promise<ActionInvocationRecord | undefined>;
749
+ /** Return the existing origin or create it only while this exact stage lease is live. */
750
+ createActionInvocationForStagedLease(input: CreateStagedActionInvocationInput): Promise<CreateStagedActionInvocationResult>;
751
+ claimStagedInvocations(input: ClaimStagedInvocationsInput): Promise<StagedInvocationRecord[]>;
752
+ /**
753
+ * The settlements below are each one compare-and-set on a pending row's
754
+ * lease owner and token, and release the lease. A settlement that carries
755
+ * `childInvocationId` records it; one without leaves a recorded id in place.
756
+ */
757
+ markStagedInvocationDispatched(input: {
758
+ id: string;
759
+ workerId: string;
760
+ leaseToken: number;
761
+ childInvocationId: string;
762
+ now?: Date;
763
+ }): Promise<boolean>;
764
+ markStagedInvocationRejected(input: {
765
+ id: string;
766
+ workerId: string;
767
+ leaseToken: number;
768
+ error: string;
769
+ now?: Date;
770
+ }): Promise<boolean>;
771
+ markStagedInvocationFailed(input: {
772
+ id: string;
773
+ workerId: string;
774
+ leaseToken: number;
775
+ error: string;
776
+ availableAt: Date;
777
+ deadLetter: boolean;
778
+ childInvocationId?: string;
779
+ now?: Date;
780
+ }): Promise<boolean>;
781
+ renewStagedInvocationLease(input: {
782
+ id: string;
783
+ workerId: string;
784
+ leaseToken: number;
785
+ leaseDurationMs: number;
786
+ now?: Date;
787
+ }): Promise<boolean>;
788
+ /**
789
+ * Replace the lease token of a pending row this worker leases with a larger
790
+ * one and extend the lease, in one compare-and-set on owner, token and an
791
+ * unexpired lease. Returns the new token, or `undefined` when the lease no
792
+ * longer matches. Tokens only grow, as with claims, so a later claim never
793
+ * hands an old token out again. Afterwards the old token fails the
794
+ * child-creation fence, renewal and every settlement. A store must order
795
+ * the rotation after any child creation the fence already admitted under
796
+ * the old token (PostgreSQL: the fence's `FOR SHARE` row lock makes the
797
+ * rotation wait). Host rotates before the lookup that decides a stage
798
+ * whose attempt holds no child id.
799
+ */
800
+ rotateStagedInvocationLease(input: {
801
+ id: string;
802
+ workerId: string;
803
+ leaseToken: number;
804
+ leaseDurationMs: number;
805
+ now?: Date;
806
+ }): Promise<number | undefined>;
807
+ cancelStagedInvocationsForFailedParents(input?: {
808
+ tenantId?: string;
809
+ spaceId?: string;
810
+ now?: Date;
811
+ }): Promise<number>;
812
+ listStagedInvocations(input: {
813
+ tenantId: string;
814
+ spaceId: string;
815
+ parentInvocationId?: string;
816
+ statuses?: readonly StagedInvocationStatus[];
817
+ }): Promise<StagedInvocationRecord[]>;
671
818
  }
672
819
  export type OutboxStatus = "pending" | "published" | "dead_letter";
673
820
  export type EventPayloadClassification = "public" | "internal" | "confidential" | "restricted";
@@ -1013,7 +1160,7 @@ export interface ActionAuthorizationInput {
1013
1160
  actorId: string;
1014
1161
  actorType: ActorType;
1015
1162
  }
1016
- export type KnownActionExecutionReason = "initial" | "approval_resume" | "recovery" | "offline_replay";
1163
+ export type KnownActionExecutionReason = "initial" | "approval_resume" | "recovery" | "offline_replay" | "staged_dispatch";
1017
1164
  export type ActionExecutionReason = KnownActionExecutionReason | (string & {});
1018
1165
  /**
1019
1166
  * Trusted execution-boundary authorization input.
@@ -1154,6 +1301,14 @@ export interface PlatformActionWorkerOptions<TDb> {
1154
1301
  * on every cycle, and run the sweep elsewhere.
1155
1302
  */
1156
1303
  sweepOverdueCompletions?: boolean;
1304
+ /** Dispatch staged descendants each cycle. Defaults to on when a registered action declares them. */
1305
+ dispatchStagedInvocations?: boolean;
1306
+ stagedInvocationBatchSize?: number;
1307
+ stagedInvocationLeaseDurationMs?: number;
1308
+ stagedInvocationLeaseRenewalIntervalMs?: number;
1309
+ stagedInvocationSubmissionTimeoutMs?: number;
1310
+ stagedInvocationMaxAttempts?: number;
1311
+ stagedInvocationRetryDelayMs?: (attempt: number) => number;
1157
1312
  }
1158
1313
  export interface PlatformActionWorkerCycleResult {
1159
1314
  claimed: number;
@@ -1167,6 +1322,38 @@ export interface PlatformActionWorkerCycleResult {
1167
1322
  * The row stays leased and a later claim retries it; excluded from failed.
1168
1323
  */
1169
1324
  deferred?: number;
1325
+ staged?: StagedInvocationDispatchResult;
1326
+ }
1327
+ export interface StagedInvocationDispatchInput {
1328
+ workerId: string;
1329
+ limit?: number;
1330
+ leaseDurationMs?: number;
1331
+ leaseRenewalIntervalMs?: number;
1332
+ submissionTimeoutMs?: number;
1333
+ maxAttempts?: number;
1334
+ retryDelayMs?: (attempt: number) => number;
1335
+ tenantId?: string;
1336
+ spaceId?: string;
1337
+ /**
1338
+ * Receives a failed staged-origin lookup and any error that ends one claimed
1339
+ * row's processing early (a store error from renewal, rotation or
1340
+ * settlement). The sweep counts that row as failed and continues.
1341
+ */
1342
+ onError?: (error: unknown) => void;
1343
+ }
1344
+ /**
1345
+ * Counters for one sweep. Each claimed row is counted once, as dispatched,
1346
+ * rejected or failed. `failed` includes rows settled for retry, rows whose
1347
+ * lease was lost before settlement, and rows whose processing threw;
1348
+ * `deadLettered` counts the subset of `failed` settled as `dead_lettered`.
1349
+ */
1350
+ export interface StagedInvocationDispatchResult {
1351
+ claimed: number;
1352
+ dispatched: number;
1353
+ rejected: number;
1354
+ failed: number;
1355
+ deadLettered: number;
1356
+ cancelled: number;
1170
1357
  }
1171
1358
  /** Origin of error text redacted before Host records or returns it. */
1172
1359
  export interface ErrorTextRedactionContext {
@@ -1369,6 +1556,10 @@ export interface PlatformHostOptions<TDb> {
1369
1556
  }
1370
1557
  export interface GovernedActionHost {
1371
1558
  submitAction(input: SubmitActionInput): Promise<SubmitActionResult>;
1559
+ /** Whether this Host's registry contains an action with a non-empty staged-descendant allowlist. */
1560
+ readonly hasStagedInvocationActions?: boolean;
1561
+ /** One bounded lease-fenced sweep of completed parents' staged descendants. */
1562
+ dispatchStagedInvocations?(input: StagedInvocationDispatchInput): Promise<StagedInvocationDispatchResult>;
1372
1563
  executeInvocation(actionInvocationId: string, tenantId: string, spaceId: string, options?: ExecuteInvocationOptions): Promise<ExecuteActionResult>;
1373
1564
  resumeApprovedInvocation(actionInvocationId: string, tenantId: string, spaceId: string, decision: ActionApprovalDecision): Promise<ExecuteActionResult>;
1374
1565
  recordExecutionAttestation(actionInvocationId: string, tenantId: string, spaceId: string, attestation: ExecutionAttestation): Promise<void>;
@@ -1415,9 +1606,10 @@ export interface MemoryPlatformHostTransactionProvider<TDb> {
1415
1606
  snapshot(db: TDb): TDb;
1416
1607
  restore(db: TDb, snapshot: TDb): void;
1417
1608
  }
1418
- export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1609
+ export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb>, StagedInvocationPlatformHostStore<TDb> {
1419
1610
  readonly db: TDb;
1420
1611
  readonly transactionalOutbox: boolean;
1612
+ readonly transactionalStagedInvocations: boolean;
1421
1613
  transactionWithEvents?: <TResult>(run: (transaction: PlatformHostMutationTransaction<TDb>) => Promise<TResult>) => Promise<TResult>;
1422
1614
  private adapterCommit;
1423
1615
  private transactionTail;
@@ -1429,6 +1621,7 @@ export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatform
1429
1621
  readonly executionAttestations: ExecutionAttestationRecord[];
1430
1622
  readonly externalReconciliations: ExternalReconciliationRecord[];
1431
1623
  readonly outbox: OutboxRecord[];
1624
+ readonly stagedInvocations: StagedInvocationRecord[];
1432
1625
  /**
1433
1626
  * Requeue evidence is append-only audit history, so unlike the ledger
1434
1627
  * arrays above, which tests have always inspected and seeded directly, it
@@ -1440,7 +1633,10 @@ export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatform
1440
1633
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1441
1634
  private runTransactionWithEvents;
1442
1635
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1636
+ createActionInvocationForStagedLease(input: CreateStagedActionInvocationInput): Promise<CreateStagedActionInvocationResult>;
1637
+ private applyStagedBatch;
1443
1638
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1639
+ getActionInvocationByStagedOrigin(tenantId: string, spaceId: string, origin: StagedInvocationOrigin): Promise<ActionInvocationRecord | undefined>;
1444
1640
  updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1445
1641
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1446
1642
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
@@ -1504,6 +1700,60 @@ export declare class MemoryPlatformHostStore<TDb> implements RecoverablePlatform
1504
1700
  claimActionInvocations(input: ClaimActionInvocationsInput): Promise<ActionInvocationRecord[]>;
1505
1701
  updateLeasedActionInvocation(input: UpdateLeasedActionInvocationInput): Promise<boolean>;
1506
1702
  renewActionInvocationLease(input: RenewActionInvocationLeaseInput): Promise<boolean>;
1703
+ claimStagedInvocations(input: ClaimStagedInvocationsInput): Promise<StagedInvocationRecord[]>;
1704
+ markStagedInvocationDispatched(input: {
1705
+ id: string;
1706
+ workerId: string;
1707
+ leaseToken: number;
1708
+ childInvocationId: string;
1709
+ now?: Date;
1710
+ }): Promise<boolean>;
1711
+ markStagedInvocationRejected(input: {
1712
+ id: string;
1713
+ workerId: string;
1714
+ leaseToken: number;
1715
+ error: string;
1716
+ now?: Date;
1717
+ }): Promise<boolean>;
1718
+ markStagedInvocationFailed(input: {
1719
+ id: string;
1720
+ workerId: string;
1721
+ leaseToken: number;
1722
+ error: string;
1723
+ availableAt: Date;
1724
+ deadLetter: boolean;
1725
+ childInvocationId?: string;
1726
+ now?: Date;
1727
+ }): Promise<boolean>;
1728
+ renewStagedInvocationLease(input: {
1729
+ id: string;
1730
+ workerId: string;
1731
+ leaseToken: number;
1732
+ leaseDurationMs: number;
1733
+ now?: Date;
1734
+ }): Promise<boolean>;
1735
+ /** Await-free, like the fenced create above, so a create runs wholly before or after it. */
1736
+ rotateStagedInvocationLease(input: {
1737
+ id: string;
1738
+ workerId: string;
1739
+ leaseToken: number;
1740
+ leaseDurationMs: number;
1741
+ now?: Date;
1742
+ }): Promise<number | undefined>;
1743
+ cancelStagedInvocationsForFailedParents(input?: {
1744
+ tenantId?: string;
1745
+ spaceId?: string;
1746
+ now?: Date;
1747
+ }): Promise<number>;
1748
+ listStagedInvocations(input: {
1749
+ tenantId: string;
1750
+ spaceId: string;
1751
+ parentInvocationId?: string;
1752
+ statuses?: readonly StagedInvocationStatus[];
1753
+ }): Promise<StagedInvocationRecord[]>;
1754
+ private leasedStagedInvocation;
1755
+ /** Mirrors PostgreSQL: a missing child id keeps the recorded one; `lastError` is replaced. */
1756
+ private settleStagedInvocation;
1507
1757
  listEvents(tenantId: string, spaceId: string): Promise<AssetEventEnvelope[]>;
1508
1758
  }
1509
1759
  //#endregion
@@ -1571,16 +1821,20 @@ export interface PostgresPlatformHostTransactionProvider<TDb> {
1571
1821
  run<TResult>(run: (context: PostgresPlatformHostTransactionContext<TDb>) => Promise<TResult>): Promise<TResult>;
1572
1822
  }
1573
1823
  /** Durable mutation-pipeline ledger for Databricks Lakebase or standard Postgres. */
1574
- export declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb> {
1824
+ export declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatformHostStore<TDb>, ApprovalPlatformHostStore<TDb>, GovernancePlatformHostStore<TDb>, OutboxPlatformHostStore<TDb>, OutboxRequeuePlatformHostStore<TDb>, StagedInvocationPlatformHostStore<TDb> {
1575
1825
  readonly db: TDb;
1576
1826
  private readonly sql;
1577
1827
  readonly transactionWithEvents?: AtomicMutationPlatformHostStore<TDb>["transactionWithEvents"];
1578
1828
  readonly transactionalOutbox: boolean;
1829
+ readonly transactionalStagedInvocations: boolean;
1579
1830
  constructor(db: TDb, sql: PlatformHostSqlClient, transactionProvider?: PostgresPlatformHostTransactionProvider<TDb>);
1580
1831
  ensureSchema(): Promise<void>;
1581
1832
  transaction<TResult>(run: (db: TDb) => Promise<TResult>): Promise<TResult>;
1582
1833
  createActionInvocation(input: CreateActionInvocationInput): Promise<ActionInvocationRecord>;
1834
+ createActionInvocationForStagedLease(input: CreateStagedActionInvocationInput): Promise<CreateStagedActionInvocationResult>;
1835
+ stageInvocations(records: readonly StagedInvocationRecord[]): Promise<void>;
1583
1836
  getActionInvocation(id: string, tenantId: string, spaceId: string): Promise<ActionInvocationRecord | undefined>;
1837
+ getActionInvocationByStagedOrigin(tenantId: string, spaceId: string, origin: StagedInvocationOrigin): Promise<ActionInvocationRecord | undefined>;
1584
1838
  updateActionInvocation(id: string, tenantId: string, spaceId: string, patch: ActionInvocationPatch): Promise<void>;
1585
1839
  recordHitlDecision(actionInvocationId: string, tenantId: string, spaceId: string, decision: HitlDecisionEvidence): Promise<ActionInvocationRecord>;
1586
1840
  beginApprovalDecision(input: BeginApprovalDecisionInput): Promise<ApprovalDecisionTransitionResult>;
@@ -1631,6 +1885,66 @@ export declare class PostgresPlatformHostStore<TDb> implements RecoverablePlatfo
1631
1885
  spaceId: string;
1632
1886
  outboxId?: string;
1633
1887
  }): Promise<OutboxRequeueRecord[]>;
1888
+ claimStagedInvocations(input: ClaimStagedInvocationsInput): Promise<StagedInvocationRecord[]>;
1889
+ markStagedInvocationDispatched(input: {
1890
+ id: string;
1891
+ workerId: string;
1892
+ leaseToken: number;
1893
+ childInvocationId: string;
1894
+ now?: Date;
1895
+ }): Promise<boolean>;
1896
+ markStagedInvocationRejected(input: {
1897
+ id: string;
1898
+ workerId: string;
1899
+ leaseToken: number;
1900
+ error: string;
1901
+ now?: Date;
1902
+ }): Promise<boolean>;
1903
+ markStagedInvocationFailed(input: {
1904
+ id: string;
1905
+ workerId: string;
1906
+ leaseToken: number;
1907
+ error: string;
1908
+ availableAt: Date;
1909
+ deadLetter: boolean;
1910
+ childInvocationId?: string;
1911
+ now?: Date;
1912
+ }): Promise<boolean>;
1913
+ renewStagedInvocationLease(input: {
1914
+ id: string;
1915
+ workerId: string;
1916
+ leaseToken: number;
1917
+ leaseDurationMs: number;
1918
+ now?: Date;
1919
+ }): Promise<boolean>;
1920
+ /**
1921
+ * The UPDATE needs a row lock that conflicts with the `FOR SHARE` lock the
1922
+ * fenced child insert takes on this row, so it waits for an in-flight
1923
+ * insert to commit. A fenced insert under the old token that reaches the
1924
+ * row while this rotation is uncommitted waits for it, rechecks the new row
1925
+ * version and inserts nothing (live tests "orders a token rotation after an
1926
+ * in-flight fenced create ..." and "refuses a fenced create under the old
1927
+ * token once a token rotation is ordered before it").
1928
+ */
1929
+ rotateStagedInvocationLease(input: {
1930
+ id: string;
1931
+ workerId: string;
1932
+ leaseToken: number;
1933
+ leaseDurationMs: number;
1934
+ now?: Date;
1935
+ }): Promise<number | undefined>;
1936
+ cancelStagedInvocationsForFailedParents(input?: {
1937
+ tenantId?: string;
1938
+ spaceId?: string;
1939
+ now?: Date;
1940
+ }): Promise<number>;
1941
+ listStagedInvocations(input: {
1942
+ tenantId: string;
1943
+ spaceId: string;
1944
+ parentInvocationId?: string;
1945
+ statuses?: readonly StagedInvocationStatus[];
1946
+ }): Promise<StagedInvocationRecord[]>;
1947
+ private settleStagedInvocation;
1634
1948
  nextEventSequence(tenantId: string, spaceId: string): Promise<number>;
1635
1949
  getEntityStateSource(tenantId: string, spaceId: string, entityType: string, entityId: string): Promise<{
1636
1950
  state: string;
@@ -1764,6 +2078,28 @@ export interface CreateDurableSagaParentLifecycleOptions<TDb> {
1764
2078
  */
1765
2079
  export declare function createDurableSagaParentLifecycle<TDb>(options: CreateDurableSagaParentLifecycleOptions<TDb>): HostSagaParentLifecycle;
1766
2080
  //#endregion
2081
+ //#region src/staged-invocations.d.ts
2082
+ export declare const MAX_STAGED_INVOCATIONS = 32;
2083
+ export declare const MAX_STAGED_INVOCATION_KEY_LENGTH = 128;
2084
+ export declare const MAX_STAGED_INVOCATION_BYTES: number;
2085
+ export declare const MAX_STAGED_INVOCATION_BATCH_BYTES: number;
2086
+ export declare const STAGED_INVOCATION_KEY_PATTERN: RegExp;
2087
+ interface PrepareStagedInvocationBatchInput<TDb> {
2088
+ parent: Pick<ActionInvocationRecord, "id" | "tenantId" | "spaceId" | "actionId">;
2089
+ parentAction: ActionDefinition<TDb>;
2090
+ requests: readonly StagedInvocationRequest[];
2091
+ resolveAction(actionId: ActionId): ActionDefinition<TDb> | undefined;
2092
+ redactParameters?(actionId: ActionId, parameters: Record<string, unknown>): Record<string, unknown>;
2093
+ /** Keys whose parameters already passed the redactor into a durable checkpoint. */
2094
+ redactedKeys?: readonly string[];
2095
+ now: Date;
2096
+ }
2097
+ /** Validate and normalize one immutable batch before its parent transaction commits. */
2098
+ export declare function prepareStagedInvocationBatch<TDb>(input: PrepareStagedInvocationBatchInput<TDb>): StagedInvocationRecord[];
2099
+ export declare function stagedInvocationRequestIdentity(record: StagedInvocationRecord): string;
2100
+ export declare function cloneStagedInvocationRecord(record: StagedInvocationRecord): StagedInvocationRecord;
2101
+ export declare function asStagedInvocationStore<TDb>(store: PlatformHostStore<TDb>): StagedInvocationPlatformHostStore<TDb> | undefined;
2102
+ //#endregion
1767
2103
  //#region src/tenant-isolation.d.ts
1768
2104
  export interface TenantIsolationScope {
1769
2105
  tenantId: string;
@@ -1801,7 +2137,7 @@ export interface TenantIsolationSubject<TDb = unknown> {
1801
2137
  reset?(): Promise<void> | void;
1802
2138
  }
1803
2139
  export interface TenantIsolationCheck {
1804
- 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";
2140
+ 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.staged-invocation-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";
1805
2141
  run(subject: TenantIsolationSubject): Promise<string[]>;
1806
2142
  }
1807
2143
  export interface TenantIsolationResult {
@@ -1814,15 +2150,16 @@ export interface TenantIsolationResult {
1814
2150
  }>;
1815
2151
  }
1816
2152
  /**
1817
- * The suite any deployment of the host must pass before it claims isolation.
2153
+ * The suite a deployment of the host must pass before it claims isolation.
1818
2154
  *
1819
- * Eight checks: an invocation cannot be read, executed, or completed under
2155
+ * Nine checks: an invocation cannot be read, executed, or completed under
1820
2156
  * another tenant's scope; an idempotency key is a tenant's own, so the same
1821
2157
  * key in two tenants is two invocations; a tenant's event stream carries no
1822
2158
  * other tenant's events; a worker scoped to one tenant does not claim another's
1823
- * work; an adapter checkpoint cannot be read or written under another tenant,
1824
- * space, or owning invocation; and, when the subject lends a read, a viewer in
1825
- * the other tenant sees nothing of ours.
2159
+ * work; staged listing and claiming retain tenant and space scope; an adapter
2160
+ * checkpoint cannot be read or written under another tenant, space, or owning
2161
+ * invocation; and, when the subject lends a read, a viewer in the other tenant
2162
+ * sees nothing of ours.
1826
2163
  */
1827
2164
  export declare function tenantIsolationChecks(): readonly TenantIsolationCheck[];
1828
2165
  /** Run every check, returning each result rather than throwing on the first. */