@fabricorg/platform-host 8.6.0 → 8.8.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 +12 -0
- package/README.md +63 -12
- package/dist/index.cjs +97 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +98 -46
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -275,6 +275,8 @@ export interface FinalizationCheckpoint {
|
|
|
275
275
|
export interface StagedInvocationOrigin {
|
|
276
276
|
parentInvocationId: string;
|
|
277
277
|
stageKey: string;
|
|
278
|
+
/** Host-registered principal name captured in the durable staged intent. */
|
|
279
|
+
principal?: string;
|
|
278
280
|
}
|
|
279
281
|
export interface AgentProposal {
|
|
280
282
|
confidence?: number;
|
|
@@ -757,6 +759,8 @@ export interface StagedInvocationRecord {
|
|
|
757
759
|
parentActionId: ActionId;
|
|
758
760
|
key: string;
|
|
759
761
|
actionId: ActionId;
|
|
762
|
+
/** Host-registered principal name selected by the parent action declaration. */
|
|
763
|
+
principal?: string;
|
|
760
764
|
expectedActionVersion: number;
|
|
761
765
|
parameters: Record<string, unknown>;
|
|
762
766
|
parameterDigest: string;
|
|
@@ -1498,6 +1502,11 @@ export interface PlatformHostOptions<TDb> {
|
|
|
1498
1502
|
registry?: Pick<ModuleRegistry<TDb>, "resolveAction" | "resolvePolicy" | "resolveStateMachine"> & Partial<Pick<ModuleRegistry<TDb>, "orderedModules">>;
|
|
1499
1503
|
/** Resolve vertical- or runtime-local actions without mutating the process-wide registry. */
|
|
1500
1504
|
resolveAction?: (actionId: ActionId) => ActionDefinition<TDb> | undefined;
|
|
1505
|
+
/** Host-owned identities available to parent action declarations for staged dispatch. */
|
|
1506
|
+
stagedInvocationPrincipals?: Readonly<Record<string, {
|
|
1507
|
+
actorId: string;
|
|
1508
|
+
actorType: ActorType;
|
|
1509
|
+
}>>;
|
|
1501
1510
|
adapters?: readonly AdapterImplementation[];
|
|
1502
1511
|
/**
|
|
1503
1512
|
* Supplies the circuit breaker for each adapter call. Defaults to a new
|
|
@@ -2233,11 +2242,13 @@ export declare const MAX_STAGED_INVOCATION_KEY_LENGTH = 128;
|
|
|
2233
2242
|
export declare const MAX_STAGED_INVOCATION_BYTES: number;
|
|
2234
2243
|
export declare const MAX_STAGED_INVOCATION_BATCH_BYTES: number;
|
|
2235
2244
|
export declare const STAGED_INVOCATION_KEY_PATTERN: RegExp;
|
|
2245
|
+
export declare const STAGED_INVOCATION_PRINCIPAL_PATTERN: RegExp;
|
|
2236
2246
|
interface PrepareStagedInvocationBatchInput<TDb> {
|
|
2237
2247
|
parent: Pick<ActionInvocationRecord, "id" | "tenantId" | "spaceId" | "actionId">;
|
|
2238
2248
|
parentAction: ActionDefinition<TDb>;
|
|
2239
2249
|
requests: readonly StagedInvocationRequest[];
|
|
2240
2250
|
resolveAction(actionId: ActionId): ActionDefinition<TDb> | undefined;
|
|
2251
|
+
stagedInvocationPrincipals?: Readonly<Record<string, unknown>>;
|
|
2241
2252
|
redactParameters?(actionId: ActionId, parameters: Record<string, unknown>): Record<string, unknown>;
|
|
2242
2253
|
/** Keys whose parameters already passed the redactor into a durable checkpoint. */
|
|
2243
2254
|
redactedKeys?: readonly string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -275,6 +275,8 @@ export interface FinalizationCheckpoint {
|
|
|
275
275
|
export interface StagedInvocationOrigin {
|
|
276
276
|
parentInvocationId: string;
|
|
277
277
|
stageKey: string;
|
|
278
|
+
/** Host-registered principal name captured in the durable staged intent. */
|
|
279
|
+
principal?: string;
|
|
278
280
|
}
|
|
279
281
|
export interface AgentProposal {
|
|
280
282
|
confidence?: number;
|
|
@@ -757,6 +759,8 @@ export interface StagedInvocationRecord {
|
|
|
757
759
|
parentActionId: ActionId;
|
|
758
760
|
key: string;
|
|
759
761
|
actionId: ActionId;
|
|
762
|
+
/** Host-registered principal name selected by the parent action declaration. */
|
|
763
|
+
principal?: string;
|
|
760
764
|
expectedActionVersion: number;
|
|
761
765
|
parameters: Record<string, unknown>;
|
|
762
766
|
parameterDigest: string;
|
|
@@ -1498,6 +1502,11 @@ export interface PlatformHostOptions<TDb> {
|
|
|
1498
1502
|
registry?: Pick<ModuleRegistry<TDb>, "resolveAction" | "resolvePolicy" | "resolveStateMachine"> & Partial<Pick<ModuleRegistry<TDb>, "orderedModules">>;
|
|
1499
1503
|
/** Resolve vertical- or runtime-local actions without mutating the process-wide registry. */
|
|
1500
1504
|
resolveAction?: (actionId: ActionId) => ActionDefinition<TDb> | undefined;
|
|
1505
|
+
/** Host-owned identities available to parent action declarations for staged dispatch. */
|
|
1506
|
+
stagedInvocationPrincipals?: Readonly<Record<string, {
|
|
1507
|
+
actorId: string;
|
|
1508
|
+
actorType: ActorType;
|
|
1509
|
+
}>>;
|
|
1501
1510
|
adapters?: readonly AdapterImplementation[];
|
|
1502
1511
|
/**
|
|
1503
1512
|
* Supplies the circuit breaker for each adapter call. Defaults to a new
|
|
@@ -2233,11 +2242,13 @@ export declare const MAX_STAGED_INVOCATION_KEY_LENGTH = 128;
|
|
|
2233
2242
|
export declare const MAX_STAGED_INVOCATION_BYTES: number;
|
|
2234
2243
|
export declare const MAX_STAGED_INVOCATION_BATCH_BYTES: number;
|
|
2235
2244
|
export declare const STAGED_INVOCATION_KEY_PATTERN: RegExp;
|
|
2245
|
+
export declare const STAGED_INVOCATION_PRINCIPAL_PATTERN: RegExp;
|
|
2236
2246
|
interface PrepareStagedInvocationBatchInput<TDb> {
|
|
2237
2247
|
parent: Pick<ActionInvocationRecord, "id" | "tenantId" | "spaceId" | "actionId">;
|
|
2238
2248
|
parentAction: ActionDefinition<TDb>;
|
|
2239
2249
|
requests: readonly StagedInvocationRequest[];
|
|
2240
2250
|
resolveAction(actionId: ActionId): ActionDefinition<TDb> | undefined;
|
|
2251
|
+
stagedInvocationPrincipals?: Readonly<Record<string, unknown>>;
|
|
2241
2252
|
redactParameters?(actionId: ActionId, parameters: Record<string, unknown>): Record<string, unknown>;
|
|
2242
2253
|
/** Keys whose parameters already passed the redactor into a durable checkpoint. */
|
|
2243
2254
|
redactedKeys?: readonly string[];
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { types } from "util";
|
|
2
|
-
import { AdapterCircuitBreakerRegistry, AdapterRegistry, FABRIC_GOVERNANCE_CONTRACT_VERSION, ReconciliationRequiredError, aggregatePolicyOutcomes, assertActionFinalization, assertAdapterCircuitBreakerConfig, assertAdapterOutcomeConsistency, assertAdapterStepDeadlines, assertGovernanceRuntimeEvidence, assertMutationGovernanceContext, canonicalJson, createFabricId, evaluatePolicyDefinitions, evaluateStateMachineTransition, executeWithAdapterRetry, isAdapterCircuitOpenError, isReconciliationRequiredError, isRetryableExecutionError } from "@fabricorg/platform";
|
|
2
|
+
import { AdapterCircuitBreakerRegistry, AdapterRegistry, FABRIC_GOVERNANCE_CONTRACT_VERSION, ReconciliationRequiredError, aggregatePolicyOutcomes, assertActionFinalization, assertAdapterCircuitBreakerConfig, assertAdapterOutcomeConsistency, assertAdapterStepDeadlines, assertGovernanceRuntimeEvidence, assertMutationGovernanceContext, canonicalJson, createFabricId, evaluatePolicyDefinitions, evaluateStateMachineTransition, executeWithAdapterRetry, isActorType, isAdapterCircuitOpenError, isReconciliationRequiredError, isRetryableExecutionError } from "@fabricorg/platform";
|
|
3
3
|
import { performance } from "perf_hooks";
|
|
4
4
|
import { assertAssemblyRuntimeCompatible } from "@fabricorg/assembly";
|
|
5
5
|
import { createHash } from "crypto";
|
|
@@ -1374,6 +1374,7 @@ const MAX_STAGED_INVOCATION_KEY_LENGTH = 128;
|
|
|
1374
1374
|
const MAX_STAGED_INVOCATION_BYTES = 65536;
|
|
1375
1375
|
const MAX_STAGED_INVOCATION_BATCH_BYTES = 262144;
|
|
1376
1376
|
const STAGED_INVOCATION_KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/;
|
|
1377
|
+
const STAGED_INVOCATION_PRINCIPAL_PATTERN = /^[a-z][a-z0-9._:-]{0,127}$/;
|
|
1377
1378
|
/** Validate and normalize one immutable batch before its parent transaction commits. */
|
|
1378
1379
|
function prepareStagedInvocationBatch(input) {
|
|
1379
1380
|
if (!Array.isArray(input.requests)) throw new Error("stagedInvocations must be an array.");
|
|
@@ -1393,6 +1394,8 @@ function prepareStagedInvocationBatch(input) {
|
|
|
1393
1394
|
if (!(input.parentAction.stagesInvocations ?? []).includes(request.actionId)) throw new Error(`Action "${input.parentAction.actionId}" may not stage "${String(request.actionId)}".`);
|
|
1394
1395
|
const child = input.resolveAction(request.actionId);
|
|
1395
1396
|
if (!child) throw new Error(`Staged action "${String(request.actionId)}" is not registered.`);
|
|
1397
|
+
const principal = input.parentAction.stagedInvocationPrincipals?.[child.actionId];
|
|
1398
|
+
if (principal !== void 0 && !Object.hasOwn(input.stagedInvocationPrincipals ?? {}, principal)) throw new Error(`Staged invocation principal "${principal}" is not registered with this Platform Host.`);
|
|
1396
1399
|
const parameters = finalizationJson(request.parameters);
|
|
1397
1400
|
if (!parameters || typeof parameters !== "object" || Array.isArray(parameters)) throw new Error(`stagedInvocations[${index}] parameters must be a JSON object.`);
|
|
1398
1401
|
if (!child.schema.safeParse(parameters).success) throw new Error(`stagedInvocations[${index}] parameters do not match action "${child.actionId}".`);
|
|
@@ -1407,24 +1410,27 @@ function prepareStagedInvocationBatch(input) {
|
|
|
1407
1410
|
if (byteLength(canonicalJson({
|
|
1408
1411
|
key: request.key,
|
|
1409
1412
|
actionId: child.actionId,
|
|
1410
|
-
parameters: durableParameters
|
|
1413
|
+
parameters: durableParameters,
|
|
1414
|
+
...principal !== void 0 ? { principal } : {}
|
|
1411
1415
|
})) > 65536) throw new Error(`stagedInvocations[${index}] exceeds ${MAX_STAGED_INVOCATION_BYTES} bytes.`);
|
|
1412
1416
|
return {
|
|
1413
1417
|
key: request.key,
|
|
1414
1418
|
actionId: child.actionId,
|
|
1415
1419
|
expectedActionVersion: child.version,
|
|
1416
1420
|
parameters: durableParameters,
|
|
1417
|
-
parameterDigest: digestParameters(durableParameters)
|
|
1421
|
+
parameterDigest: digestParameters(durableParameters),
|
|
1422
|
+
...principal !== void 0 ? { principal } : {}
|
|
1418
1423
|
};
|
|
1419
1424
|
});
|
|
1420
1425
|
for (const [index, request] of normalized.entries()) if (normalized.findIndex((candidate) => candidate.key === request.key) !== index) throw new Error(`stagedInvocations contains duplicate key "${request.key}".`);
|
|
1421
1426
|
normalized.sort((left, right) => compareText(left.key, right.key) || compareText(left.actionId, right.actionId));
|
|
1422
|
-
const batchIdentity = normalized.map(({ key, actionId, expectedActionVersion, parameters, parameterDigest }) => ({
|
|
1427
|
+
const batchIdentity = normalized.map(({ key, actionId, expectedActionVersion, parameters, parameterDigest, principal }) => ({
|
|
1423
1428
|
key,
|
|
1424
1429
|
actionId,
|
|
1425
1430
|
expectedActionVersion,
|
|
1426
1431
|
parameters,
|
|
1427
|
-
parameterDigest
|
|
1432
|
+
parameterDigest,
|
|
1433
|
+
...principal !== void 0 ? { principal } : {}
|
|
1428
1434
|
}));
|
|
1429
1435
|
if (byteLength(canonicalJson(batchIdentity)) > 262144) throw new Error(`stagedInvocations batch exceeds ${MAX_STAGED_INVOCATION_BATCH_BYTES} bytes.`);
|
|
1430
1436
|
const batchDigest = digestParameters({
|
|
@@ -1459,7 +1465,8 @@ function stagedInvocationRequestIdentity(record) {
|
|
|
1459
1465
|
expectedActionVersion: record.expectedActionVersion,
|
|
1460
1466
|
parameters: record.parameters,
|
|
1461
1467
|
parameterDigest: record.parameterDigest,
|
|
1462
|
-
batchDigest: record.batchDigest
|
|
1468
|
+
batchDigest: record.batchDigest,
|
|
1469
|
+
...record.principal !== void 0 ? { principal: record.principal } : {}
|
|
1463
1470
|
});
|
|
1464
1471
|
}
|
|
1465
1472
|
function cloneStagedInvocationRecord(record) {
|
|
@@ -1526,6 +1533,20 @@ const STAGED_ERROR = Object.freeze({
|
|
|
1526
1533
|
lookup: "Staged child lookup failed."
|
|
1527
1534
|
});
|
|
1528
1535
|
function createGovernedActionHost(options) {
|
|
1536
|
+
const configuredStagedPrincipals = options.stagedInvocationPrincipals;
|
|
1537
|
+
if (configuredStagedPrincipals !== void 0 && (!configuredStagedPrincipals || typeof configuredStagedPrincipals !== "object" || Array.isArray(configuredStagedPrincipals))) throw new Error("stagedInvocationPrincipals must be an object.");
|
|
1538
|
+
const stagedInvocationPrincipals = Object.freeze(Object.fromEntries(Object.entries(configuredStagedPrincipals ?? {}).map(([name, candidate]) => {
|
|
1539
|
+
if (!STAGED_INVOCATION_PRINCIPAL_PATTERN.test(name)) throw new Error(`Invalid staged invocation principal name: ${name}`);
|
|
1540
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) throw new Error(`Staged invocation principal "${name}" must be an object.`);
|
|
1541
|
+
const actorId = candidate.actorId;
|
|
1542
|
+
const actorType = candidate.actorType;
|
|
1543
|
+
if (typeof actorId !== "string" || actorId.length === 0) throw new Error(`Staged invocation principal "${name}" actorId must be a non-empty string.`);
|
|
1544
|
+
if (typeof actorType !== "string" || !isActorType(actorType)) throw new Error(`Staged invocation principal "${name}" has invalid actorType.`);
|
|
1545
|
+
return [name, Object.freeze({
|
|
1546
|
+
actorId,
|
|
1547
|
+
actorType
|
|
1548
|
+
})];
|
|
1549
|
+
})));
|
|
1529
1550
|
if (options.approvalDefaultTtlMs !== void 0 && (!Number.isSafeInteger(options.approvalDefaultTtlMs) || options.approvalDefaultTtlMs <= 0)) throw new Error("approvalDefaultTtlMs must be a positive safe integer in milliseconds.");
|
|
1530
1551
|
if (options.approvalLifecycleEvents) {
|
|
1531
1552
|
const approvalStore = asApprovalStore(options.store);
|
|
@@ -1559,6 +1580,9 @@ function createGovernedActionHost(options) {
|
|
|
1559
1580
|
const configuredActionResolver = options.resolveAction ?? options.registry?.resolveAction;
|
|
1560
1581
|
if (!configuredActionResolver) throw new Error("Platform Host requires an explicit module registry or resolveAction function.");
|
|
1561
1582
|
const actionResolver = configuredActionResolver;
|
|
1583
|
+
if (options.registry?.orderedModules) {
|
|
1584
|
+
for (const module of options.registry.orderedModules) for (const action of module.actions ?? []) for (const principal of Object.values(action.stagedInvocationPrincipals ?? {})) if (!Object.hasOwn(stagedInvocationPrincipals, principal)) throw new Error(`Staged invocation principal "${principal}" referenced by action "${action.actionId}" is not registered with this Platform Host.`);
|
|
1585
|
+
}
|
|
1562
1586
|
const stagedStore = asStagedInvocationStore(options.store);
|
|
1563
1587
|
const declaresStaging = options.registry?.orderedModules?.some((module) => (module.actions ?? []).some((action) => (action.stagesInvocations?.length ?? 0) > 0)) ?? false;
|
|
1564
1588
|
if (declaresStaging && (!stagedStore || !asAtomicMutationStore(options.store))) throw new Error("Staged descendant invocations require a store with transactionalStagedInvocations and transactionWithEvents capabilities.");
|
|
@@ -2702,6 +2726,7 @@ function createGovernedActionHost(options) {
|
|
|
2702
2726
|
parentAction: action,
|
|
2703
2727
|
requests: rawStagedInvocations,
|
|
2704
2728
|
resolveAction: actionResolver,
|
|
2729
|
+
stagedInvocationPrincipals,
|
|
2705
2730
|
redactParameters: options.redactActionParameters,
|
|
2706
2731
|
now: now()
|
|
2707
2732
|
});
|
|
@@ -3122,6 +3147,7 @@ function createGovernedActionHost(options) {
|
|
|
3122
3147
|
...invocation.causationId ? { causationId: invocation.causationId } : {},
|
|
3123
3148
|
attempt,
|
|
3124
3149
|
maxAttempts,
|
|
3150
|
+
...executionLease ? { lease: executionLease } : {},
|
|
3125
3151
|
...deadlineMs ? { deadlineMs } : {},
|
|
3126
3152
|
...adapterController ? { signal: adapterController.signal } : {}
|
|
3127
3153
|
});
|
|
@@ -3573,6 +3599,7 @@ function createGovernedActionHost(options) {
|
|
|
3573
3599
|
parentAction: action,
|
|
3574
3600
|
requests: stagedRequests,
|
|
3575
3601
|
resolveAction: actionResolver,
|
|
3602
|
+
stagedInvocationPrincipals,
|
|
3576
3603
|
redactParameters: options.redactActionParameters,
|
|
3577
3604
|
redactedKeys: handlerStagedInvocations.map((request) => request.key),
|
|
3578
3605
|
now: now()
|
|
@@ -4143,6 +4170,8 @@ function createGovernedActionHost(options) {
|
|
|
4143
4170
|
if (!parent || parent.status !== "completed") throw new Error("Staged parent is not completed.");
|
|
4144
4171
|
const child = actionResolver(record.actionId);
|
|
4145
4172
|
if (!child) throw new StagedDispatchRejectionError("Staged action is no longer registered.");
|
|
4173
|
+
const principal = record.principal !== void 0 && Object.hasOwn(stagedInvocationPrincipals, record.principal) ? stagedInvocationPrincipals[record.principal] : void 0;
|
|
4174
|
+
if (record.principal !== void 0 && !principal) throw new StagedDispatchRejectionError("Staged invocation principal is no longer registered.");
|
|
4146
4175
|
if (child.execution?.authorityMoment === "capture") throw new StagedDispatchRejectionError("Staged action now requires capture-time authority.");
|
|
4147
4176
|
if (!child.schema.safeParse(structuredClone(record.parameters)).success) throw new StagedDispatchRejectionError("Staged parameters no longer match the registered action.");
|
|
4148
4177
|
return submitActionInternal({
|
|
@@ -4150,8 +4179,8 @@ function createGovernedActionHost(options) {
|
|
|
4150
4179
|
parameters: structuredClone(record.parameters),
|
|
4151
4180
|
tenantId: parent.tenantId,
|
|
4152
4181
|
spaceId: parent.spaceId,
|
|
4153
|
-
actorId: parent.actorId,
|
|
4154
|
-
actorType: parent.actorType,
|
|
4182
|
+
actorId: principal?.actorId ?? parent.actorId,
|
|
4183
|
+
actorType: principal?.actorType ?? parent.actorType,
|
|
4155
4184
|
correlationId: parent.correlationId,
|
|
4156
4185
|
causationId: parent.id,
|
|
4157
4186
|
provenance: {
|
|
@@ -4165,7 +4194,8 @@ function createGovernedActionHost(options) {
|
|
|
4165
4194
|
id: record.id,
|
|
4166
4195
|
origin: {
|
|
4167
4196
|
parentInvocationId: parent.id,
|
|
4168
|
-
stageKey: record.key
|
|
4197
|
+
stageKey: record.key,
|
|
4198
|
+
...record.principal !== void 0 ? { principal: record.principal } : {}
|
|
4169
4199
|
},
|
|
4170
4200
|
workerId: lease.workerId,
|
|
4171
4201
|
leaseToken: lease.leaseToken,
|
|
@@ -4835,7 +4865,7 @@ var MemoryPlatformHostStore = class {
|
|
|
4835
4865
|
kind: "existing",
|
|
4836
4866
|
invocation: existing
|
|
4837
4867
|
};
|
|
4838
|
-
if (!this.stagedInvocations.find((record) => record.id === input.stageId && record.tenantId === invocation.tenantId && record.spaceId === invocation.spaceId && record.parentInvocationId === invocation.stagedOrigin.parentInvocationId && record.key === invocation.stagedOrigin.stageKey && record.actionId === invocation.actionId && record.status === "pending" && record.leaseOwner === input.workerId && record.leaseToken === input.leaseToken && record.leaseExpiresAt !== void 0 && record.leaseExpiresAt > now)) return { kind: "lease_lost" };
|
|
4868
|
+
if (!this.stagedInvocations.find((record) => record.id === input.stageId && record.tenantId === invocation.tenantId && record.spaceId === invocation.spaceId && record.parentInvocationId === invocation.stagedOrigin.parentInvocationId && record.key === invocation.stagedOrigin.stageKey && record.actionId === invocation.actionId && record.principal === invocation.stagedOrigin.principal && record.status === "pending" && record.leaseOwner === input.workerId && record.leaseToken === input.leaseToken && record.leaseExpiresAt !== void 0 && record.leaseExpiresAt > now)) return { kind: "lease_lost" };
|
|
4839
4869
|
const createdAt = /* @__PURE__ */ new Date();
|
|
4840
4870
|
const record = {
|
|
4841
4871
|
...invocation,
|
|
@@ -5683,6 +5713,16 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5683
5713
|
version: 13,
|
|
5684
5714
|
name: "agent_proposal",
|
|
5685
5715
|
sql: `ALTER TABLE fabric_platform.action_invocations ADD COLUMN IF NOT EXISTS agent_proposal jsonb;`
|
|
5716
|
+
},
|
|
5717
|
+
{
|
|
5718
|
+
version: 14,
|
|
5719
|
+
name: "staged_invocation_principals",
|
|
5720
|
+
sql: `
|
|
5721
|
+
ALTER TABLE fabric_platform.staged_invocations
|
|
5722
|
+
ADD COLUMN IF NOT EXISTS principal text;
|
|
5723
|
+
ALTER TABLE fabric_platform.action_invocations
|
|
5724
|
+
ADD COLUMN IF NOT EXISTS staged_origin_principal text;
|
|
5725
|
+
`
|
|
5686
5726
|
}
|
|
5687
5727
|
]);
|
|
5688
5728
|
}
|
|
@@ -5747,9 +5787,9 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5747
5787
|
const current = input.now ?? /* @__PURE__ */ new Date();
|
|
5748
5788
|
const admitted = invocation.admittedAt !== void 0;
|
|
5749
5789
|
const admittedColumn = admitted ? ",admitted_at" : "";
|
|
5750
|
-
const admittedValue = admitted ? ",$
|
|
5790
|
+
const admittedValue = admitted ? ",$31" : "";
|
|
5751
5791
|
const proposalColumn = invocation.agentProposal !== void 0 ? ",agent_proposal" : "";
|
|
5752
|
-
const proposalValue = invocation.agentProposal !== void 0 ? `,$${admitted ?
|
|
5792
|
+
const proposalValue = invocation.agentProposal !== void 0 ? `,$${admitted ? 32 : 31}::jsonb` : "";
|
|
5753
5793
|
const values = [
|
|
5754
5794
|
invocation.id,
|
|
5755
5795
|
invocation.tenantId,
|
|
@@ -5776,6 +5816,7 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5776
5816
|
invocation.runtimeEvidence ? JSON.stringify(invocation.runtimeEvidence) : null,
|
|
5777
5817
|
invocation.stagedOrigin.parentInvocationId,
|
|
5778
5818
|
invocation.stagedOrigin.stageKey,
|
|
5819
|
+
invocation.stagedOrigin.principal ?? null,
|
|
5779
5820
|
input.stageId,
|
|
5780
5821
|
input.workerId,
|
|
5781
5822
|
input.leaseToken,
|
|
@@ -5788,10 +5829,11 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5788
5829
|
result = await this.sql.query(`WITH fence AS (
|
|
5789
5830
|
SELECT stage.id
|
|
5790
5831
|
FROM fabric_platform.staged_invocations AS stage
|
|
5791
|
-
WHERE stage.id=$
|
|
5832
|
+
WHERE stage.id=$27 AND stage.tenant_id=$2 AND stage.space_id=$3
|
|
5792
5833
|
AND stage.parent_invocation_id=$24 AND stage.stage_key=$25 AND stage.action_id=$4
|
|
5793
|
-
AND stage.
|
|
5794
|
-
AND stage.
|
|
5834
|
+
AND stage.principal IS NOT DISTINCT FROM $26
|
|
5835
|
+
AND stage.status='pending' AND stage.lease_owner=$28 AND stage.lease_token=$29
|
|
5836
|
+
AND stage.lease_expires_at IS NOT NULL AND stage.lease_expires_at > $30
|
|
5795
5837
|
FOR SHARE
|
|
5796
5838
|
)
|
|
5797
5839
|
INSERT INTO fabric_platform.action_invocations
|
|
@@ -5799,17 +5841,19 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5799
5841
|
parameters,result,correlation_id,causation_id,idempotency_key,parameter_digest,
|
|
5800
5842
|
parameter_digest_algorithm,idempotency_actor_id,idempotency_authorization_binding_id,
|
|
5801
5843
|
invocation_provenance,authorization_binding,execution_reason,authorization_binding_id,error,
|
|
5802
|
-
runtime_evidence,staged_parent_invocation_id,staged_stage_key${admittedColumn}${proposalColumn},created_at,updated_at)
|
|
5844
|
+
runtime_evidence,staged_parent_invocation_id,staged_stage_key,staged_origin_principal${admittedColumn}${proposalColumn},created_at,updated_at)
|
|
5803
5845
|
SELECT $1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,
|
|
5804
|
-
$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25${admittedValue}${proposalValue},$
|
|
5846
|
+
$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25,$26${admittedValue}${proposalValue},$30,$30
|
|
5805
5847
|
FROM fence
|
|
5806
5848
|
ON CONFLICT (tenant_id,space_id,staged_parent_invocation_id,staged_stage_key)
|
|
5807
5849
|
WHERE staged_parent_invocation_id IS NOT NULL AND staged_stage_key IS NOT NULL
|
|
5808
5850
|
DO UPDATE SET id=fabric_platform.action_invocations.id
|
|
5809
5851
|
RETURNING *`, values);
|
|
5810
5852
|
} catch (error) {
|
|
5811
|
-
|
|
5812
|
-
if (
|
|
5853
|
+
const databaseError = error;
|
|
5854
|
+
if (invocation.agentProposal !== void 0 && databaseError?.code === "42703" && typeof databaseError.message === "string" && /\bagent_proposal\b/.test(databaseError.message)) throw new Error("Agent proposals require PostgreSQL migration 13 (agent_proposal); run ensureSchema().", { cause: error });
|
|
5855
|
+
if (databaseError?.code === "42703") throw new Error("A staged child needs PostgreSQL migration 14 (staged_invocation_principals); run ensureSchema() before dispatching staged invocations.", { cause: error });
|
|
5856
|
+
if (databaseError?.code === "42P01") throw new Error("A staged child needs PostgreSQL migration 11 (staged_descendant_invocations); run ensureSchema() before dispatching staged invocations.", { cause: error });
|
|
5813
5857
|
throw error;
|
|
5814
5858
|
}
|
|
5815
5859
|
if (result.rows[0]) {
|
|
@@ -5851,33 +5895,39 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5851
5895
|
}
|
|
5852
5896
|
for (const record of records) {
|
|
5853
5897
|
if (record.tenantId !== first.tenantId || record.spaceId !== first.spaceId || record.parentInvocationId !== first.parentInvocationId || record.batchDigest !== first.batchDigest) throw new Error(`Invalid staged invocation batch for parent ${first.parentInvocationId}.`);
|
|
5854
|
-
|
|
5855
|
-
|
|
5898
|
+
try {
|
|
5899
|
+
await this.sql.query(`INSERT INTO fabric_platform.staged_invocations
|
|
5900
|
+
(id,tenant_id,space_id,parent_invocation_id,parent_action_id,stage_key,action_id,principal,
|
|
5856
5901
|
expected_action_version,parameters,parameter_digest,batch_digest,status,child_invocation_id,
|
|
5857
5902
|
attempt_count,available_at,lease_owner,lease_expires_at,lease_token,last_error,created_at,updated_at)
|
|
5858
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5903
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22)`, [
|
|
5904
|
+
record.id,
|
|
5905
|
+
record.tenantId,
|
|
5906
|
+
record.spaceId,
|
|
5907
|
+
record.parentInvocationId,
|
|
5908
|
+
record.parentActionId,
|
|
5909
|
+
record.key,
|
|
5910
|
+
record.actionId,
|
|
5911
|
+
record.principal ?? null,
|
|
5912
|
+
record.expectedActionVersion,
|
|
5913
|
+
JSON.stringify(record.parameters),
|
|
5914
|
+
record.parameterDigest,
|
|
5915
|
+
record.batchDigest,
|
|
5916
|
+
record.status,
|
|
5917
|
+
record.childInvocationId ?? null,
|
|
5918
|
+
record.attemptCount,
|
|
5919
|
+
record.availableAt,
|
|
5920
|
+
record.leaseOwner ?? null,
|
|
5921
|
+
record.leaseExpiresAt ?? null,
|
|
5922
|
+
record.leaseToken,
|
|
5923
|
+
record.lastError ?? null,
|
|
5924
|
+
record.createdAt,
|
|
5925
|
+
record.updatedAt
|
|
5926
|
+
]);
|
|
5927
|
+
} catch (error) {
|
|
5928
|
+
if (error?.code === "42703") throw new Error("Staging an invocation needs PostgreSQL migration 14 (staged_invocation_principals); run ensureSchema() before staging invocations.", { cause: error });
|
|
5929
|
+
throw error;
|
|
5930
|
+
}
|
|
5881
5931
|
}
|
|
5882
5932
|
}
|
|
5883
5933
|
async getActionInvocation(id, tenantId, spaceId) {
|
|
@@ -6898,7 +6948,8 @@ function toActionRecord(row) {
|
|
|
6898
6948
|
...row.idempotency_authorization_binding_id ? { idempotencyAuthorizationBindingId: String(row.idempotency_authorization_binding_id) } : {},
|
|
6899
6949
|
...row.staged_parent_invocation_id && row.staged_stage_key ? { stagedOrigin: {
|
|
6900
6950
|
parentInvocationId: String(row.staged_parent_invocation_id),
|
|
6901
|
-
stageKey: String(row.staged_stage_key)
|
|
6951
|
+
stageKey: String(row.staged_stage_key),
|
|
6952
|
+
...row.staged_origin_principal ? { principal: String(row.staged_origin_principal) } : {}
|
|
6902
6953
|
} } : {},
|
|
6903
6954
|
...row.invocation_provenance ? { provenance: row.invocation_provenance } : {},
|
|
6904
6955
|
...row.authorization_binding ? { authorizationBinding: row.authorization_binding } : {},
|
|
@@ -6944,6 +6995,7 @@ function toStagedInvocationRecord(row) {
|
|
|
6944
6995
|
parentActionId: String(row.parent_action_id),
|
|
6945
6996
|
key: String(row.stage_key),
|
|
6946
6997
|
actionId: String(row.action_id),
|
|
6998
|
+
...row.principal ? { principal: String(row.principal) } : {},
|
|
6947
6999
|
expectedActionVersion: Number(row.expected_action_version),
|
|
6948
7000
|
parameters: row.parameters,
|
|
6949
7001
|
parameterDigest: String(row.parameter_digest),
|
|
@@ -8425,6 +8477,6 @@ async function runEventAppendChecks(subject) {
|
|
|
8425
8477
|
};
|
|
8426
8478
|
}
|
|
8427
8479
|
//#endregion
|
|
8428
|
-
export { APPROVAL_DECIDED_EVENT, APPROVAL_EXPIRED_EVENT, APPROVAL_REQUESTED_EVENT, ActionAdmissionError, ExternalCompletionError, IdempotencyConflictError, MAX_APPROVAL_EVIDENCE_BYTES, MAX_STAGED_INVOCATIONS, MAX_STAGED_INVOCATION_BATCH_BYTES, MAX_STAGED_INVOCATION_BYTES, MAX_STAGED_INVOCATION_KEY_LENGTH, MemoryPlatformHostStore, PARAMETER_DIGEST_ALGORITHM, PLATFORM_HOST_CONTRACT_VERSION, PLATFORM_HOST_HEALTH_CONTRACT_VERSION, PLATFORM_HOST_METRIC_NAMES, PostgresPlatformHostStore, STAGED_INVOCATION_KEY_PATTERN, SubmissionRefusalError, applyPostgresMigrations, asStagedInvocationStore, canonicalJson, cloneOutboxRecord, cloneStagedInvocationRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, eventAppendChecks, getPlatformHostHealthSnapshot, outboxActorDisclosure, prepareStagedInvocationBatch, runEventAppendChecks, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, runTenantIsolationChecks, stagedInvocationRequestIdentity, tenantIsolationChecks, toEnterpriseEventEnvelope };
|
|
8480
|
+
export { APPROVAL_DECIDED_EVENT, APPROVAL_EXPIRED_EVENT, APPROVAL_REQUESTED_EVENT, ActionAdmissionError, ExternalCompletionError, IdempotencyConflictError, MAX_APPROVAL_EVIDENCE_BYTES, MAX_STAGED_INVOCATIONS, MAX_STAGED_INVOCATION_BATCH_BYTES, MAX_STAGED_INVOCATION_BYTES, MAX_STAGED_INVOCATION_KEY_LENGTH, MemoryPlatformHostStore, PARAMETER_DIGEST_ALGORITHM, PLATFORM_HOST_CONTRACT_VERSION, PLATFORM_HOST_HEALTH_CONTRACT_VERSION, PLATFORM_HOST_METRIC_NAMES, PostgresPlatformHostStore, STAGED_INVOCATION_KEY_PATTERN, STAGED_INVOCATION_PRINCIPAL_PATTERN, SubmissionRefusalError, applyPostgresMigrations, asStagedInvocationStore, canonicalJson, cloneOutboxRecord, cloneStagedInvocationRecord, createDurableSagaParentLifecycle, createGovernedActionHost, createStoreBackedActionDispatcher, digestParameters, emitPlatformHostTelemetry, eventAppendChecks, getPlatformHostHealthSnapshot, outboxActorDisclosure, prepareStagedInvocationBatch, runEventAppendChecks, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, runTenantIsolationChecks, stagedInvocationRequestIdentity, tenantIsolationChecks, toEnterpriseEventEnvelope };
|
|
8429
8481
|
|
|
8430
8482
|
//# sourceMappingURL=index.js.map
|