@fabricorg/platform-host 8.5.0 → 8.6.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 +10 -0
- package/README.md +37 -0
- package/dist/index.cjs +86 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +86 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @fabricorg/platform-host
|
|
2
2
|
|
|
3
|
+
## 8.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 019ba30: Add the agent proposal submission envelope and Host HITL evaluator context with durable invocation identity. Snapshot proposals before awaiting authorization; validate strict approval evidence and support `redactAgentProposal` beside parameter redaction, after admission where declared. Persist and evaluate the redacted envelope, including on recovery and approval resume.
|
|
8
|
+
|
|
9
|
+
Idempotency compares redacted proposals and adds the `agent_proposal` conflict reason, including presence changes and legacy records. Consumers with exhaustive conflict-reason switches must handle the new value.
|
|
10
|
+
|
|
11
|
+
Run `ensureSchema()` to apply PostgreSQL migration 13 (`agent_proposal`) before submitting the first proposal. Inserts without proposals omit the new column. Staged and saga children do not inherit their parent's envelope.
|
|
12
|
+
|
|
3
13
|
## 8.5.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1712,3 +1712,40 @@ This capability lives on `OutboxRequeuePlatformHostStore`, which extends `Outbox
|
|
|
1712
1712
|
`MemoryPlatformHostStore` and `PostgresPlatformHostStore` implement it, and a custom outbox store
|
|
1713
1713
|
without it makes the operation throw. PostgreSQL adds migration 5, the
|
|
1714
1714
|
`fabric_platform.event_outbox_requeues` table, which `ensureSchema()` creates.
|
|
1715
|
+
|
|
1716
|
+
### Agent proposals and Host evaluator context
|
|
1717
|
+
|
|
1718
|
+
Agent callers can submit `SubmitActionInput.agentProposal` separately from action parameters:
|
|
1719
|
+
`{ confidence, riskTier, agentSessionId, agentRunId, reason, evidence }`. Confidence must be
|
|
1720
|
+
finite; risk tier is `low`, `medium`, or `high`. Session/run IDs must contain non-whitespace
|
|
1721
|
+
text and fit within 256 UTF-16 code units; reason may be empty and is limited to 4096 code
|
|
1722
|
+
units. Evidence uses the approval-decision strict JSON object validation and
|
|
1723
|
+
`MAX_APPROVAL_EVIDENCE_BYTES` (16 KiB). Invalid proposals and proposals from other actor
|
|
1724
|
+
types reject submission before invocation creation through the existing Error rejection path.
|
|
1725
|
+
|
|
1726
|
+
For the submission snapshot, Host reads `agentProposal` once and deeply copies it before
|
|
1727
|
+
its first await, including for actions without `admitSubmission`. The sibling
|
|
1728
|
+
`redactAgentProposal(actionId, proposal)` hook runs beside `redactActionParameters`: after
|
|
1729
|
+
admission for actions declaring `admitSubmission`, otherwise before composition resolution.
|
|
1730
|
+
Its result is validated and copied again. A thrown hook or invalid output rejects submission
|
|
1731
|
+
without creating an invocation, like a thrown parameter-redaction hook. Applications should
|
|
1732
|
+
remove secrets and unnecessary sensitive evidence through this hook before durable storage.
|
|
1733
|
+
|
|
1734
|
+
The redacted proposal is stored on `ActionInvocationRecord` and compared canonically on
|
|
1735
|
+
idempotent re-submission. Differences, including absence versus presence, add the
|
|
1736
|
+
`agent_proposal` conflict reason under the configured `enforce` or `audit-only` mode,
|
|
1737
|
+
including legacy records without parameter digests. Exhaustive conflict-reason switches
|
|
1738
|
+
must handle this new value.
|
|
1739
|
+
|
|
1740
|
+
`hitlEvaluator` receives `HostHitlEvaluatorContext`, extending the portable context with
|
|
1741
|
+
`actionInvocationId` and the durable `invocation` read before evaluation. Proposal fields
|
|
1742
|
+
supply confidence, risk tier, session ID, and run ID individually, falling back to parameters
|
|
1743
|
+
for absent fields. Reason and evidence are available through `invocation.agentProposal`.
|
|
1744
|
+
Approval authorization and resumed execution authorization receive that durable proposal too.
|
|
1745
|
+
Staged and saga children do not inherit a parent's proposal. Approval lifecycle event payloads
|
|
1746
|
+
and Host telemetry do not include the envelope.
|
|
1747
|
+
|
|
1748
|
+
Apply PostgreSQL migration 13 (`agent_proposal`) with `ensureSchema()` before the first
|
|
1749
|
+
proposal submission. Inserts without proposals omit the new column, following the
|
|
1750
|
+
`admitted_at` rollout pattern. Existing migration SQL is unchanged; readers accept legacy
|
|
1751
|
+
rows without a proposal. See `src/postgres-store.ts` (`ensureSchema`, `toActionRecord`).
|
package/dist/index.cjs
CHANGED
|
@@ -297,6 +297,52 @@ async function appendLifecycleEvent(transaction, factory, invocation, kind) {
|
|
|
297
297
|
}, metadata);
|
|
298
298
|
}
|
|
299
299
|
//#endregion
|
|
300
|
+
//#region src/agent-proposal.ts
|
|
301
|
+
/** Validate without invoking getters or retaining caller-owned evidence. */
|
|
302
|
+
function snapshotAgentProposal(value) {
|
|
303
|
+
const invalid = () => {
|
|
304
|
+
throw new Error("Invalid agent proposal.");
|
|
305
|
+
};
|
|
306
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || util.types.isProxy(value)) return invalid();
|
|
307
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return invalid();
|
|
308
|
+
const allowed = [
|
|
309
|
+
"confidence",
|
|
310
|
+
"riskTier",
|
|
311
|
+
"agentSessionId",
|
|
312
|
+
"agentRunId",
|
|
313
|
+
"reason",
|
|
314
|
+
"evidence"
|
|
315
|
+
];
|
|
316
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
317
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
318
|
+
if (typeof key !== "string" || !allowed.includes(key) || !descriptor.enumerable || !Object.hasOwn(descriptor, "value")) return invalid();
|
|
319
|
+
}
|
|
320
|
+
if (value.confidence !== void 0 && (typeof value.confidence !== "number" || !Number.isFinite(value.confidence))) return invalid();
|
|
321
|
+
if (value.riskTier !== void 0 && ![
|
|
322
|
+
"low",
|
|
323
|
+
"medium",
|
|
324
|
+
"high"
|
|
325
|
+
].includes(value.riskTier)) return invalid();
|
|
326
|
+
for (const key of [
|
|
327
|
+
"agentSessionId",
|
|
328
|
+
"agentRunId",
|
|
329
|
+
"reason"
|
|
330
|
+
]) {
|
|
331
|
+
const field = value[key];
|
|
332
|
+
if (field !== void 0 && (typeof field !== "string" || field.length > (key === "reason" ? 4096 : 256) || key !== "reason" && field.trim().length === 0)) return invalid();
|
|
333
|
+
}
|
|
334
|
+
const evidence = snapshotApprovalDecision({
|
|
335
|
+
approved: true,
|
|
336
|
+
approverId: "proposal",
|
|
337
|
+
approverType: "agent",
|
|
338
|
+
...value.evidence !== void 0 ? { evidence: value.evidence } : {}
|
|
339
|
+
}).evidence;
|
|
340
|
+
return {
|
|
341
|
+
...value,
|
|
342
|
+
...evidence !== void 0 ? { evidence } : {}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
//#endregion
|
|
300
346
|
//#region src/command-identity.ts
|
|
301
347
|
const PARAMETER_DIGEST_ALGORITHM = "fabric-canonical-json-sha256-v1";
|
|
302
348
|
function digestParameters(parameters) {
|
|
@@ -1002,7 +1048,11 @@ function snapshotSubmission(input) {
|
|
|
1002
1048
|
const executionReason = scalar("executionReason");
|
|
1003
1049
|
const idempotencyKey = scalar("idempotencyKey");
|
|
1004
1050
|
const authorizationBindingId = scalar("authorizationBindingId");
|
|
1051
|
+
const proposal = input.agentProposal;
|
|
1052
|
+
if (proposal !== void 0 && actorType !== "agent") throw new Error("Agent proposal requires an agent actor.");
|
|
1053
|
+
const agentProposal = proposal === void 0 ? void 0 : snapshotAgentProposal(proposal);
|
|
1005
1054
|
const live = {
|
|
1055
|
+
...agentProposal !== void 0 ? { agentProposal } : {},
|
|
1006
1056
|
actionId,
|
|
1007
1057
|
tenantId,
|
|
1008
1058
|
spaceId,
|
|
@@ -1071,6 +1121,7 @@ function privateSubmission(snapshot) {
|
|
|
1071
1121
|
const provenance = provenanceRead ? copyProvenance(provenanceRead) : void 0;
|
|
1072
1122
|
const authorizationBinding = bindingRead ? copyBinding(bindingRead) : void 0;
|
|
1073
1123
|
return Object.freeze({
|
|
1124
|
+
...snapshot.agentProposal !== void 0 ? { agentProposal: snapshot.agentProposal } : {},
|
|
1074
1125
|
actionId: snapshot.actionId,
|
|
1075
1126
|
tenantId: snapshot.tenantId,
|
|
1076
1127
|
spaceId: snapshot.spaceId,
|
|
@@ -1167,6 +1218,7 @@ function parametersCopy(snapshot) {
|
|
|
1167
1218
|
*/
|
|
1168
1219
|
function liveSubmissionView(snapshot, input) {
|
|
1169
1220
|
const view = {
|
|
1221
|
+
...snapshot.agentProposal !== void 0 ? { agentProposal: snapshotAgentProposal(snapshot.agentProposal) } : {},
|
|
1170
1222
|
actionId: snapshot.actionId,
|
|
1171
1223
|
tenantId: snapshot.tenantId,
|
|
1172
1224
|
spaceId: snapshot.spaceId,
|
|
@@ -1208,6 +1260,7 @@ function submissionView(snapshot) {
|
|
|
1208
1260
|
const provenance = fresh(snapshot.provenance);
|
|
1209
1261
|
const authorizationBinding = fresh(snapshot.authorizationBinding);
|
|
1210
1262
|
return {
|
|
1263
|
+
...snapshot.agentProposal !== void 0 ? { agentProposal: snapshotAgentProposal(snapshot.agentProposal) } : {},
|
|
1211
1264
|
actionId: snapshot.actionId,
|
|
1212
1265
|
parameters: parametersCopy(snapshot),
|
|
1213
1266
|
tenantId: snapshot.tenantId,
|
|
@@ -1544,7 +1597,8 @@ function createGovernedActionHost(options) {
|
|
|
1544
1597
|
if (submission.authorizationBinding) validateAuthorizationBinding(submission, parameterDigest, action.execution?.authorityMoment, now());
|
|
1545
1598
|
return {
|
|
1546
1599
|
durableParameters,
|
|
1547
|
-
parameterDigest
|
|
1600
|
+
parameterDigest,
|
|
1601
|
+
agentProposal: submission.agentProposal === void 0 ? void 0 : snapshotAgentProposal(options.redactAgentProposal ? options.redactAgentProposal(submission.actionId, submission.agentProposal) : submission.agentProposal)
|
|
1548
1602
|
};
|
|
1549
1603
|
};
|
|
1550
1604
|
const early = declaresAdmission ? void 0 : prepare();
|
|
@@ -1559,9 +1613,10 @@ function createGovernedActionHost(options) {
|
|
|
1559
1613
|
};
|
|
1560
1614
|
(0, _fabricorg_platform.assertGovernanceRuntimeEvidence)(runtimeEvidence);
|
|
1561
1615
|
const admission = declaresAdmission ? await admitSubmission(action, submission) : void 0;
|
|
1562
|
-
const { durableParameters, parameterDigest } = early ?? prepare();
|
|
1616
|
+
const { durableParameters, parameterDigest, agentProposal } = early ?? prepare();
|
|
1563
1617
|
const invocationInput = {
|
|
1564
1618
|
id: actionInvocationId,
|
|
1619
|
+
...agentProposal !== void 0 ? { agentProposal } : {},
|
|
1565
1620
|
tenantId: submission.tenantId,
|
|
1566
1621
|
spaceId: submission.spaceId,
|
|
1567
1622
|
actionId: submission.actionId,
|
|
@@ -1615,6 +1670,7 @@ function createGovernedActionHost(options) {
|
|
|
1615
1670
|
});
|
|
1616
1671
|
if (durableInvocation.id !== actionInvocationId && submission.idempotencyKey) {
|
|
1617
1672
|
const conflict = idempotencyConflict(durableInvocation, {
|
|
1673
|
+
agentProposal,
|
|
1618
1674
|
actorId: submission.actorId,
|
|
1619
1675
|
authorizationBindingId: submission.authorizationBindingId,
|
|
1620
1676
|
actionVersion: action.version,
|
|
@@ -2336,21 +2392,24 @@ function createGovernedActionHost(options) {
|
|
|
2336
2392
|
}
|
|
2337
2393
|
if (invocation.actorType === "agent" && options.hitlEvaluator) {
|
|
2338
2394
|
const hitlParameters = isRecord(parsed.data) ? parsed.data : invocation.parameters;
|
|
2395
|
+
const proposal = invocation.agentProposal;
|
|
2339
2396
|
const approvalStore = asApprovalStore(options.store);
|
|
2340
2397
|
if (!approvalStore) return hostOperation(() => failExecution(invocation, "failed", "The configured HITL evaluator requires a store with approval persistence support."));
|
|
2341
2398
|
let evaluatedApprovalExpiresAt;
|
|
2342
2399
|
if (!invocation.hitlRoute) {
|
|
2343
2400
|
const decision = await options.hitlEvaluator({
|
|
2401
|
+
actionInvocationId: invocation.id,
|
|
2402
|
+
invocation,
|
|
2344
2403
|
actionId: action.actionId,
|
|
2345
2404
|
actorId: invocation.actorId,
|
|
2346
2405
|
actorType: invocation.actorType,
|
|
2347
2406
|
tenantId,
|
|
2348
2407
|
spaceId,
|
|
2349
2408
|
parameters: hitlParameters,
|
|
2350
|
-
...numberValue(hitlParameters.confidence) !== void 0 ? { confidence: numberValue(hitlParameters.confidence) } : {},
|
|
2351
|
-
...isRiskTier(hitlParameters.riskTier) ? { riskTier: hitlParameters.riskTier } : {},
|
|
2352
|
-
...stringValue(hitlParameters.agentSessionId) ? { agentSessionId: stringValue(hitlParameters.agentSessionId) } : {},
|
|
2353
|
-
...stringValue(hitlParameters.agentRunId) ? { agentRunId: stringValue(hitlParameters.agentRunId) } : {}
|
|
2409
|
+
...(proposal?.confidence ?? numberValue(hitlParameters.confidence)) !== void 0 ? { confidence: proposal?.confidence ?? numberValue(hitlParameters.confidence) } : {},
|
|
2410
|
+
...isRiskTier(proposal?.riskTier ?? hitlParameters.riskTier) ? { riskTier: proposal?.riskTier ?? hitlParameters.riskTier } : {},
|
|
2411
|
+
...proposal?.agentSessionId ?? stringValue(hitlParameters.agentSessionId) ? { agentSessionId: proposal?.agentSessionId ?? stringValue(hitlParameters.agentSessionId) } : {},
|
|
2412
|
+
...proposal?.agentRunId ?? stringValue(hitlParameters.agentRunId) ? { agentRunId: proposal?.agentRunId ?? stringValue(hitlParameters.agentRunId) } : {}
|
|
2354
2413
|
});
|
|
2355
2414
|
if (decision.approvalExpiresAt !== void 0 && !validApprovalDate(decision.approvalExpiresAt)) return hostOperation(() => failExecution(invocation, "failed", "approvalExpiresAt must be a valid Date."));
|
|
2356
2415
|
evaluatedApprovalExpiresAt = decision.approvalExpiresAt === void 0 ? void 0 : new Date(decision.approvalExpiresAt);
|
|
@@ -4314,6 +4373,7 @@ function validateAuthorizationBinding(input, parameterDigest, authorityMoment, c
|
|
|
4314
4373
|
}
|
|
4315
4374
|
function idempotencyConflict(existing, incoming) {
|
|
4316
4375
|
const reasons = [];
|
|
4376
|
+
if ((0, _fabricorg_platform.canonicalJson)(existing.agentProposal ?? null) !== (0, _fabricorg_platform.canonicalJson)(incoming.agentProposal ?? null)) reasons.push("agent_proposal");
|
|
4317
4377
|
if ((existing.idempotencyActorId ?? existing.actorId) !== incoming.actorId) reasons.push("actor");
|
|
4318
4378
|
if ((existing.idempotencyAuthorizationBindingId ?? existing.authorizationBindingId) !== incoming.authorizationBindingId) reasons.push("authority_binding");
|
|
4319
4379
|
if (existing.actionVersion !== incoming.actionVersion) reasons.push("action_version");
|
|
@@ -5619,6 +5679,11 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5619
5679
|
ON fabric_platform.action_invocations (approval_expires_at, id)
|
|
5620
5680
|
WHERE status='waiting_for_approval' AND approval_expires_at IS NOT NULL;
|
|
5621
5681
|
`
|
|
5682
|
+
},
|
|
5683
|
+
{
|
|
5684
|
+
version: 13,
|
|
5685
|
+
name: "agent_proposal",
|
|
5686
|
+
sql: `ALTER TABLE fabric_platform.action_invocations ADD COLUMN IF NOT EXISTS agent_proposal jsonb;`
|
|
5622
5687
|
}
|
|
5623
5688
|
]);
|
|
5624
5689
|
}
|
|
@@ -5630,6 +5695,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5630
5695
|
const admitted = input.admittedAt !== void 0;
|
|
5631
5696
|
const admittedColumn = admitted ? "admitted_at," : "";
|
|
5632
5697
|
const admittedValue = admitted ? "$25," : "";
|
|
5698
|
+
const proposalColumn = input.agentProposal !== void 0 ? "agent_proposal," : "";
|
|
5699
|
+
const proposalValue = input.agentProposal !== void 0 ? `$${admitted ? 26 : 25}::jsonb,` : "";
|
|
5633
5700
|
let result;
|
|
5634
5701
|
try {
|
|
5635
5702
|
result = await this.sql.query(`INSERT INTO fabric_platform.action_invocations
|
|
@@ -5637,8 +5704,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5637
5704
|
parameters,result,correlation_id,causation_id,idempotency_key,
|
|
5638
5705
|
parameter_digest,parameter_digest_algorithm,idempotency_actor_id,
|
|
5639
5706
|
idempotency_authorization_binding_id,invocation_provenance,authorization_binding,execution_reason,
|
|
5640
|
-
authorization_binding_id,error,runtime_evidence,${admittedColumn}created_at,updated_at)
|
|
5641
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,${admittedValue}$24,$24)
|
|
5707
|
+
authorization_binding_id,error,runtime_evidence,${admittedColumn}${proposalColumn}created_at,updated_at)
|
|
5708
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,${admittedValue}${proposalValue}$24,$24)
|
|
5642
5709
|
ON CONFLICT (tenant_id,space_id,action_id,idempotency_key)
|
|
5643
5710
|
WHERE idempotency_key IS NOT NULL DO UPDATE SET id=fabric_platform.action_invocations.id
|
|
5644
5711
|
RETURNING *`, [
|
|
@@ -5666,9 +5733,11 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5666
5733
|
input.error ?? null,
|
|
5667
5734
|
input.runtimeEvidence ? JSON.stringify(input.runtimeEvidence) : null,
|
|
5668
5735
|
now,
|
|
5669
|
-
...admitted ? [input.admittedAt] : []
|
|
5736
|
+
...admitted ? [input.admittedAt] : [],
|
|
5737
|
+
...input.agentProposal !== void 0 ? [JSON.stringify(input.agentProposal)] : []
|
|
5670
5738
|
]);
|
|
5671
5739
|
} catch (error) {
|
|
5740
|
+
if (input.agentProposal !== void 0 && error?.code === "42703") throw new Error("Agent proposals require PostgreSQL migration 13 (agent_proposal); run ensureSchema().", { cause: error });
|
|
5672
5741
|
if (admitted && error?.code === "42703") throw new Error("An admitted invocation needs the action_invocations.admitted_at column; run ensureSchema() to apply PostgreSQL migration 6 (invocation_admission) before submitting actions that declare admitSubmission.", { cause: error });
|
|
5673
5742
|
throw error;
|
|
5674
5743
|
}
|
|
@@ -5680,6 +5749,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5680
5749
|
const admitted = invocation.admittedAt !== void 0;
|
|
5681
5750
|
const admittedColumn = admitted ? ",admitted_at" : "";
|
|
5682
5751
|
const admittedValue = admitted ? ",$30" : "";
|
|
5752
|
+
const proposalColumn = invocation.agentProposal !== void 0 ? ",agent_proposal" : "";
|
|
5753
|
+
const proposalValue = invocation.agentProposal !== void 0 ? `,$${admitted ? 31 : 30}::jsonb` : "";
|
|
5683
5754
|
const values = [
|
|
5684
5755
|
invocation.id,
|
|
5685
5756
|
invocation.tenantId,
|
|
@@ -5710,7 +5781,8 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5710
5781
|
input.workerId,
|
|
5711
5782
|
input.leaseToken,
|
|
5712
5783
|
current,
|
|
5713
|
-
...admitted ? [invocation.admittedAt] : []
|
|
5784
|
+
...admitted ? [invocation.admittedAt] : [],
|
|
5785
|
+
...invocation.agentProposal !== void 0 ? [JSON.stringify(invocation.agentProposal)] : []
|
|
5714
5786
|
];
|
|
5715
5787
|
let result;
|
|
5716
5788
|
try {
|
|
@@ -5728,15 +5800,16 @@ var PostgresPlatformHostStore = class PostgresPlatformHostStore {
|
|
|
5728
5800
|
parameters,result,correlation_id,causation_id,idempotency_key,parameter_digest,
|
|
5729
5801
|
parameter_digest_algorithm,idempotency_actor_id,idempotency_authorization_binding_id,
|
|
5730
5802
|
invocation_provenance,authorization_binding,execution_reason,authorization_binding_id,error,
|
|
5731
|
-
runtime_evidence,staged_parent_invocation_id,staged_stage_key${admittedColumn},created_at,updated_at)
|
|
5803
|
+
runtime_evidence,staged_parent_invocation_id,staged_stage_key${admittedColumn}${proposalColumn},created_at,updated_at)
|
|
5732
5804
|
SELECT $1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10::jsonb,$11,$12,$13,$14,$15,$16,$17,
|
|
5733
|
-
$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25${admittedValue},$29,$29
|
|
5805
|
+
$18::jsonb,$19::jsonb,$20,$21,$22,$23::jsonb,$24,$25${admittedValue}${proposalValue},$29,$29
|
|
5734
5806
|
FROM fence
|
|
5735
5807
|
ON CONFLICT (tenant_id,space_id,staged_parent_invocation_id,staged_stage_key)
|
|
5736
5808
|
WHERE staged_parent_invocation_id IS NOT NULL AND staged_stage_key IS NOT NULL
|
|
5737
5809
|
DO UPDATE SET id=fabric_platform.action_invocations.id
|
|
5738
5810
|
RETURNING *`, values);
|
|
5739
5811
|
} catch (error) {
|
|
5812
|
+
if (invocation.agentProposal !== void 0 && error?.code === "42703") throw new Error("Agent proposals require PostgreSQL migration 13 (agent_proposal); run ensureSchema().", { cause: error });
|
|
5740
5813
|
if (error?.code === "42703" || error?.code === "42P01") throw new Error("A staged child needs PostgreSQL migration 11 (staged_descendant_invocations); run ensureSchema() before dispatching staged invocations.", { cause: error });
|
|
5741
5814
|
throw error;
|
|
5742
5815
|
}
|
|
@@ -6856,6 +6929,7 @@ function toActionRecord(row) {
|
|
|
6856
6929
|
...row.mutation_footprint ? { mutationFootprint: row.mutation_footprint } : {},
|
|
6857
6930
|
...row.execution_principal ? { executionPrincipal: row.execution_principal } : {},
|
|
6858
6931
|
...row.runtime_evidence ? { runtimeEvidence: row.runtime_evidence } : {},
|
|
6932
|
+
...row.agent_proposal != null ? { agentProposal: row.agent_proposal } : {},
|
|
6859
6933
|
...row.admitted_at ? { admittedAt: new Date(row.admitted_at) } : {},
|
|
6860
6934
|
...row.error ? { error: String(row.error) } : {},
|
|
6861
6935
|
createdAt: new Date(row.created_at),
|