@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/CHANGELOG.md +33 -0
- package/README.md +134 -4
- package/dist/index.cjs +1193 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +348 -11
- package/dist/index.d.ts +348 -11
- package/dist/index.js +1185 -24
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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
|
|
2153
|
+
* The suite a deployment of the host must pass before it claims isolation.
|
|
1818
2154
|
*
|
|
1819
|
-
*
|
|
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;
|
|
1824
|
-
*
|
|
1825
|
-
* the
|
|
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. */
|