witnora 0.18.13 → 0.18.15
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/gateway.js +12 -9
- package/dist/internal/control-client/collector-gateway.d.ts.map +1 -1
- package/dist/internal/control-client/collector-gateway.js +2 -1
- package/dist/vendor/onegent-runtime/failure-runtime-watch.d.ts +8 -2
- package/dist/vendor/onegent-runtime/failure-runtime-watch.d.ts.map +1 -1
- package/dist/vendor/onegent-runtime/failure-runtime-watch.js +86 -16
- package/package.json +1 -1
package/dist/gateway.js
CHANGED
|
@@ -136,7 +136,9 @@ export async function upgradeCustomerGatewayRuntime(options) {
|
|
|
136
136
|
const current = parseConfig(configRaw);
|
|
137
137
|
if (current.projectId !== options.authorization.projectId || current.server !== options.authorization.server)
|
|
138
138
|
throw new Error("Existing Gateway project/server binding does not match this authorized Runtime upgrade.");
|
|
139
|
-
const
|
|
139
|
+
const exactCurrentClient = clientRaw === gatewayClient(current);
|
|
140
|
+
const generatedClient = exactCurrentClient
|
|
141
|
+
|| (current.agentIdentity?.externalId !== current.connectionName && clientRaw === gatewayClient(current, current.connectionName))
|
|
140
142
|
|| (!current.runtimeWorker && (clientRaw === recordedGatewayClient(current)
|
|
141
143
|
|| clientRaw === recordedGatewayClient({ ...current, agentIdentity: undefined })));
|
|
142
144
|
if (!generatedClient || readmeRaw !== gatewayReadme(current))
|
|
@@ -162,7 +164,8 @@ export async function upgradeCustomerGatewayRuntime(options) {
|
|
|
162
164
|
|| createHash("sha256").update(probeBytes).digest("hex") !== current.runtimeWorker.probeModuleSha256) {
|
|
163
165
|
throw new Error("Existing generated Runtime modules were modified; refusing to overwrite them.");
|
|
164
166
|
}
|
|
165
|
-
if (
|
|
167
|
+
if (exactCurrentClient
|
|
168
|
+
&& sameRuntimeGeneration(current.runtimeWorker, next.runtimeWorker)
|
|
166
169
|
&& JSON.stringify(current.agentIdentity) === JSON.stringify(next.agentIdentity)) {
|
|
167
170
|
return { config: current, generatedFiles: [], changed: false, rollback: async () => undefined };
|
|
168
171
|
}
|
|
@@ -549,7 +552,7 @@ export async function runCustomerGateway(options) {
|
|
|
549
552
|
keyRing,
|
|
550
553
|
gatewayToken: secrets.gatewayToken,
|
|
551
554
|
storageDirectory: dataDirectory,
|
|
552
|
-
agentExternalId: config.connectionName,
|
|
555
|
+
agentExternalId: config.agentIdentity?.externalId ?? config.connectionName,
|
|
553
556
|
host: process.env.WITNORA_GATEWAY_HOST?.trim() || config.host,
|
|
554
557
|
port: gatewayPort(process.env.WITNORA_GATEWAY_PORT, config.port),
|
|
555
558
|
environment: "customer-owned",
|
|
@@ -705,10 +708,10 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
705
708
|
readOutcome: async ({ resourceId, actions, receipts }) => input.managed.readLocalSandboxRuntimeWatchOutcome({
|
|
706
709
|
path: join(input.directory, "data", "runtime-sandbox", "fixture", "audit.jsonl"),
|
|
707
710
|
resourceId,
|
|
708
|
-
actions: actions.map((action) =>
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
})
|
|
711
|
+
actions: actions.map((action) => {
|
|
712
|
+
const executionSessionId = receipts.find((receipt) => receipt.actionId === action.id)?.receipt?.core?.executionSessionId;
|
|
713
|
+
return { id: action.id, ...(executionSessionId ? { executionSessionId } : {}) };
|
|
714
|
+
}),
|
|
712
715
|
}),
|
|
713
716
|
})
|
|
714
717
|
: undefined;
|
|
@@ -1680,11 +1683,11 @@ function localSandboxOrigin(value) {
|
|
|
1680
1683
|
return false;
|
|
1681
1684
|
}
|
|
1682
1685
|
}
|
|
1683
|
-
function gatewayClient(config) {
|
|
1686
|
+
function gatewayClient(config, localSandboxAgentId = config.agentIdentity?.externalId ?? config.connectionName) {
|
|
1684
1687
|
const requestHelper = `async function actionRequest(path, init = {}) {\n const headers = new Headers(init.headers);\n headers.set("authorization", \`Bearer \${await token()}\`);\n if (init.body) headers.set("content-type", "application/json");\n const response = await fetch(\`\${baseUrl}\${path}\`, { ...init, headers });\n const result = await response.json().catch(() => ({}));\n if (!response.ok) throw new Error(result.error ?? \`Witnora Gateway returned HTTP \${response.status}.\`);\n return result;\n}\n`;
|
|
1685
1688
|
const actionMethods = ` proposeAction(proposal, idempotencyKey = proposal?.externalId) {\n if (typeof idempotencyKey !== "string" || !idempotencyKey) throw new Error("Witnora action proposal requires an idempotency key or externalId.");\n return actionRequest("/v1/actions", { method: "POST", body: JSON.stringify({ proposal, idempotencyKey }) });\n },\n getAction(actionId) {\n if (!/^[A-Za-z0-9._:-]+$/.test(actionId)) throw new Error("Witnora actionId contains unsupported characters.");\n return actionRequest(\`/v1/actions/\${encodeURIComponent(actionId)}\`);\n },\n issueExecutionGrant(actionId, grant, idempotencyKey = \`grant:\${actionId}\`) {\n if (!/^[A-Za-z0-9._:-]+$/.test(actionId)) throw new Error("Witnora actionId contains unsupported characters.");\n return actionRequest(\`/v1/actions/\${encodeURIComponent(actionId)}/execution-grant\`, { method: "POST", body: JSON.stringify({ grant, idempotencyKey }) });\n },\n`;
|
|
1686
1689
|
const localSandboxMethod = config.runtimeWorker?.adapterId === LOCAL_SANDBOX_ADAPTER_ID && config.runtimeWorker.mandateId && config.runtimeWorker.sandboxPrincipalId
|
|
1687
|
-
? ` async proposeLocalSandboxUpdate({ resourceId, status = "UPDATED", externalId = \`runtime-sandbox-\${crypto.randomUUID()}\`, agentBuildId = "witnora-local-sandbox-task@1.0.0" }) {\n if (!/^[A-Za-z0-9._:-]+$/.test(resourceId)) throw new Error("Local sandbox resourceId contains unsupported characters.");\n const approvedParameters = { resourceId, status };\n const digest = Buffer.from(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(agentBuildId))).toString("hex");\n const proposal = {\n externalId, agentId: "${
|
|
1690
|
+
? ` async proposeLocalSandboxUpdate({ resourceId, status = "UPDATED", externalId = \`runtime-sandbox-\${crypto.randomUUID()}\`, agentBuildId = "witnora-local-sandbox-task@1.0.0" }) {\n if (!/^[A-Za-z0-9._:-]+$/.test(resourceId)) throw new Error("Local sandbox resourceId contains unsupported characters.");\n const approvedParameters = { resourceId, status };\n const digest = Buffer.from(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(agentBuildId))).toString("hex");\n const proposal = {\n externalId, agentId: "${localSandboxAgentId}", principal: { id: "${config.runtimeWorker.sandboxPrincipalId}", version: "sandbox-v1" },\n actionType: "UPDATE", targetSystem: "WitnoraLocalSandbox", requestedPermissions: [], sensitive: true, expectedState: approvedParameters,\n mandateId: "${config.runtimeWorker.mandateId}", requireMandate: true,\n executionIntent: { adapterId: "${LOCAL_SANDBOX_ADAPTER_ID}", adapterVersionConstraint: "^${LOCAL_SANDBOX_ADAPTER_VERSION}", allowedOrigins: ["${config.runtimeWorker.sandboxOrigin}"], approvedParameters, outcomePredicate: { type: "state_subset", expected: approvedParameters }, agentBuildId, agentBuildDigest: digest, allowedOperation: "UPDATE", allowedResource: \`mock-state/\${resourceId}\` },\n };\n return this.proposeAction(proposal, externalId);\n },\n`
|
|
1688
1691
|
: "";
|
|
1689
1692
|
const realPathSandboxMethod = config.runtimeWorker?.adapterId === LOCAL_SANDBOX_ADAPTER_ID && config.runtimeWorker.mandateId && config.runtimeWorker.sandboxPrincipalId
|
|
1690
1693
|
? ` async proposeRealPathSandboxSimulation({ integrationId, resourceId, status = "SUBMITTED", externalId = \`real-path-sandbox-\${crypto.randomUUID()}\`, agentBuildId = "witnora-real-path-sandbox@1.0.0" }) {\n if (!/^[A-Za-z0-9._:-]+$/.test(integrationId) || !/^[A-Za-z0-9._:-]+$/.test(resourceId)) throw new Error("Real-path integrationId and resourceId must be identifiers.");\n const harness = JSON.parse(await readFile(new URL("./workflow-harness.json", import.meta.url), "utf8"));\n const matches = Array.isArray(harness.realPathActivations) ? harness.realPathActivations.filter((item) => item?.integrationId === integrationId) : [];\n if (matches.length !== 1) throw new Error("Real-path sandbox simulation requires one exact active Harness integration.");\n const activation = matches[0];\n if (activation.environment !== "sandbox" || !Array.isArray(activation.actionPathIds) || activation.actionPathIds.length !== 1) throw new Error("Real-path sandbox simulation requires one exact sandbox action path.");\n const approvedParameters = { resourceId, status };\n const digest = Buffer.from(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(agentBuildId))).toString("hex");\n const proposal = {\n externalId, agentId: activation.agentId, principal: { id: "${config.runtimeWorker.sandboxPrincipalId}", version: "sandbox-v1" },\n actionType: "UPDATE", targetSystem: "WitnoraLocalSandbox", requestedPermissions: [], sensitive: true, expectedState: approvedParameters,\n businessTaskBinding: { taskContractId: activation.taskContractId, taskContractDigestSha256: activation.taskContractDigestSha256, actionPathId: activation.actionPathIds[0], environment: "sandbox", realPathIntegrationId: activation.integrationId, realPathIntegrationDigestSha256: activation.integrationDigestSha256 },\n mandateId: "${config.runtimeWorker.mandateId}", requireMandate: true,\n executionIntent: { adapterId: "${LOCAL_SANDBOX_ADAPTER_ID}", adapterVersionConstraint: "^${LOCAL_SANDBOX_ADAPTER_VERSION}", allowedOrigins: ["${config.runtimeWorker.sandboxOrigin}"], approvedParameters, outcomePredicate: { type: "state_subset", expected: approvedParameters }, agentBuildId, agentBuildDigest: digest, allowedOperation: "UPDATE", allowedResource: \`mock-state/\${resourceId}\` },\n };\n return this.proposeAction(proposal, externalId);\n },\n`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-gateway.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/collector-gateway.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"collector-gateway.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/collector-gateway.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,qBAAqB,EAGrB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACjJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClH,SAAS,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,yBAAyB,CAAC;QAAC,gBAAgB,CAAC,EAAE,yBAAyB,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnP,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7F,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3G,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACjI;AAED,MAAM,WAAW,oCAAoC;IACnD,MAAM,EAAE,wBAAwB,CAAC;IACjC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE;QACb,KAAK,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxF,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,cAAc,CAAC,EAAE;YAAE,cAAc,EAAE,oBAAoB,CAAC;YAAC,OAAO,EAAE,uBAAuB,CAAC;YAAC,YAAY,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KAC3I,CAAC;IACF,gBAAgB,CAAC,EAAE;QAAE,MAAM,IAAI,OAAO,CAAC,yBAAyB,GAAG,SAAS,CAAC,CAAA;KAAE,CAAC;IAChF,cAAc,CAAC,EAAE,uBAAuB,CAAC;IACzC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5G;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,MAAM,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,kDAAkD,CAAC;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;IAC7C,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAClK;AAkBD,wBAAsB,kCAAkC,CAAC,OAAO,EAAE,oCAAoC,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAoO9I"}
|
|
@@ -116,8 +116,9 @@ export async function startCustomerOwnedCollectorGateway(options) {
|
|
|
116
116
|
}
|
|
117
117
|
const hostedProposal = runtimeBinding ? { ...proposal, localRuntimeBinding: runtimeBinding } : proposal;
|
|
118
118
|
const action = await options.client.proposeAction(hostedProposal, identifier(body.idempotencyKey, "idempotencyKey"));
|
|
119
|
-
if (options.actionWorker)
|
|
119
|
+
if (options.actionWorker && action.externalId === proposal.externalId) {
|
|
120
120
|
await options.actionWorker.track({ actionId: identifier(action.id, "actionId"), proposal });
|
|
121
|
+
}
|
|
121
122
|
return json(response, 202, action);
|
|
122
123
|
}
|
|
123
124
|
const actionRoute = url.pathname.match(/^\/v1\/actions\/([A-Za-z0-9._:-]+)$/);
|
|
@@ -4,14 +4,17 @@ export interface FailureRuntimeWatchCase {
|
|
|
4
4
|
id: string;
|
|
5
5
|
projectId: string;
|
|
6
6
|
status: "FIX_VERIFIED" | "RUNTIME_PROTECTED" | "REGRESSION_DETECTED" | string;
|
|
7
|
+
updatedAt?: string;
|
|
7
8
|
definition: HostedFailureDefinition;
|
|
8
9
|
discovery?: {
|
|
9
10
|
discoveryKey?: string;
|
|
10
11
|
};
|
|
11
12
|
candidate?: {
|
|
12
13
|
agentVersion: string;
|
|
14
|
+
recordedAt?: string;
|
|
13
15
|
};
|
|
14
16
|
runtimeWatch?: {
|
|
17
|
+
activatedAt?: string;
|
|
15
18
|
receiptIds?: string[];
|
|
16
19
|
latest?: {
|
|
17
20
|
receiptIds?: string[];
|
|
@@ -21,6 +24,8 @@ export interface FailureRuntimeWatchCase {
|
|
|
21
24
|
export interface FailureRuntimeWatchAction {
|
|
22
25
|
id: string;
|
|
23
26
|
status: string;
|
|
27
|
+
updatedAt?: string;
|
|
28
|
+
verificationSuccess?: boolean;
|
|
24
29
|
expectedState?: Record<string, unknown>;
|
|
25
30
|
businessTaskBinding?: {
|
|
26
31
|
taskContractId?: string;
|
|
@@ -41,6 +46,7 @@ export interface FailureRuntimeWatchReceipt {
|
|
|
41
46
|
executionSessionId?: string;
|
|
42
47
|
};
|
|
43
48
|
};
|
|
49
|
+
discoveryBoundary?: "SIGNED_VERIFIED_ACTION";
|
|
44
50
|
}
|
|
45
51
|
export interface FailureRuntimeWatchOutcome {
|
|
46
52
|
classification: "HEALTHY" | "REGRESSION" | "INSUFFICIENT_EVIDENCE" | "CONNECTION_UNAVAILABLE" | "SCHEMA_DIGEST_DRIFT";
|
|
@@ -67,7 +73,7 @@ export interface FailureRuntimeWatchStatusInput {
|
|
|
67
73
|
export interface FailureRuntimeWatchHostedClient {
|
|
68
74
|
listFailureCases(): Promise<FailureRuntimeWatchCase[]>;
|
|
69
75
|
listActions(): Promise<FailureRuntimeWatchAction[]>;
|
|
70
|
-
listReceipts(): Promise<FailureRuntimeWatchReceipt[]>;
|
|
76
|
+
listReceipts(actions?: FailureRuntimeWatchAction[]): Promise<FailureRuntimeWatchReceipt[]>;
|
|
71
77
|
uploadObservation(input: HostedFailureExperimentInput & {
|
|
72
78
|
observedAt: string;
|
|
73
79
|
}): Promise<unknown>;
|
|
@@ -131,7 +137,7 @@ export declare function readLocalSandboxRuntimeWatchOutcome(input: {
|
|
|
131
137
|
resourceId: string;
|
|
132
138
|
actions: Array<{
|
|
133
139
|
id: string;
|
|
134
|
-
executionSessionId
|
|
140
|
+
executionSessionId?: string;
|
|
135
141
|
}>;
|
|
136
142
|
now?: () => Date;
|
|
137
143
|
}): Promise<FailureRuntimeWatchOutcome>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure-runtime-watch.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/failure-runtime-watch.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2B,KAAK,uBAAuB,EAAE,KAAK,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE1I,MAAM,MAAM,yBAAyB,GACjC,SAAS,GACT,YAAY,GACZ,uBAAuB,GACvB,wBAAwB,CAAC;AAE7B,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,MAAM,CAAC;IAC9E,UAAU,EAAE,uBAAuB,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,SAAS,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"failure-runtime-watch.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/failure-runtime-watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,10 +8,25 @@ export function createFailureRuntimeWatchHostedClient(options) {
|
|
|
8
8
|
const apiKey = required(options.apiKey, "apiKey");
|
|
9
9
|
const requestFetch = options.fetch ?? fetch;
|
|
10
10
|
const projectUrl = `${baseUrl}/v1/projects/${encodeURIComponent(projectId)}`;
|
|
11
|
+
const receiptCache = new Map();
|
|
11
12
|
return {
|
|
12
13
|
listFailureCases: async () => list(await hostedJson(requestFetch, `${projectUrl}/failure-cases`, apiKey), "failureCases"),
|
|
13
14
|
listActions: async () => list(await hostedJson(requestFetch, `${projectUrl}/actions`, apiKey), "actions"),
|
|
14
|
-
listReceipts: async () =>
|
|
15
|
+
listReceipts: async (actions = []) => {
|
|
16
|
+
const eligible = actions.filter((action) => action.status === "VERIFIED"
|
|
17
|
+
&& action.verificationSuccess === true
|
|
18
|
+
&& action.businessTaskBinding?.environment === "sandbox");
|
|
19
|
+
const discovered = await Promise.all(eligible.map(async (action) => {
|
|
20
|
+
const cached = receiptCache.get(action.id);
|
|
21
|
+
if (cached && cached.actionUpdatedAt === action.updatedAt)
|
|
22
|
+
return cached.receipts;
|
|
23
|
+
const detail = await hostedJson(requestFetch, `${projectUrl}/actions/${encodeURIComponent(required(action.id, "actionId"))}`, apiKey);
|
|
24
|
+
const receipts = signedVerifiedActionReceipt(detail);
|
|
25
|
+
receiptCache.set(action.id, { actionUpdatedAt: action.updatedAt, receipts });
|
|
26
|
+
return receipts;
|
|
27
|
+
}));
|
|
28
|
+
return discovered.flat();
|
|
29
|
+
},
|
|
15
30
|
uploadObservation: async (input) => uploadFailureExperiment(input, { baseUrl, projectId, apiKey, fetch: requestFetch }),
|
|
16
31
|
updateStatus: async (failureCaseId, input) => hostedJson(requestFetch, `${projectUrl}/failure-cases/${encodeURIComponent(required(failureCaseId, "failureCaseId"))}/runtime-watch-status`, apiKey, { method: "POST", body: JSON.stringify(input) }),
|
|
17
32
|
};
|
|
@@ -92,7 +107,17 @@ export class ManagedFailureRuntimeWatch {
|
|
|
92
107
|
let actions;
|
|
93
108
|
let receipts;
|
|
94
109
|
try {
|
|
95
|
-
|
|
110
|
+
actions = await this.#client.listActions();
|
|
111
|
+
const candidateBindings = new Set(candidates.map((failureCase) => bindingKey(failureCase.definition)));
|
|
112
|
+
receipts = await this.#client.listReceipts(actions.filter((action) => {
|
|
113
|
+
const binding = action.businessTaskBinding;
|
|
114
|
+
return Boolean(binding?.taskContractId && binding.actionPathId && binding.environment
|
|
115
|
+
&& candidateBindings.has(bindingKey({
|
|
116
|
+
taskContractId: binding.taskContractId,
|
|
117
|
+
actionPathId: binding.actionPathId,
|
|
118
|
+
environment: binding.environment,
|
|
119
|
+
})));
|
|
120
|
+
}));
|
|
96
121
|
}
|
|
97
122
|
catch {
|
|
98
123
|
const detail = "Runtime Watch could not load new Action and Receipt metadata from Witnora.";
|
|
@@ -132,7 +157,8 @@ export class ManagedFailureRuntimeWatch {
|
|
|
132
157
|
for (const failureCase of eligible) {
|
|
133
158
|
const checkedAt = this.#now().toISOString();
|
|
134
159
|
const nextCheckAt = new Date(Date.parse(checkedAt) + this.#intervalMs).toISOString();
|
|
135
|
-
const
|
|
160
|
+
const storedCheckpoint = await this.#checkpoints.load(failureCase.id);
|
|
161
|
+
const checkpoint = storedCheckpoint ?? {
|
|
136
162
|
processedReceiptIds: failureCase.runtimeWatch?.receiptIds ?? failureCase.runtimeWatch?.latest?.receiptIds ?? [],
|
|
137
163
|
updatedAt: checkedAt,
|
|
138
164
|
};
|
|
@@ -144,6 +170,8 @@ export class ManagedFailureRuntimeWatch {
|
|
|
144
170
|
lastCheckedAt: checkedAt,
|
|
145
171
|
nextCheckAt,
|
|
146
172
|
});
|
|
173
|
+
if (!storedCheckpoint)
|
|
174
|
+
await this.#checkpoints.save(failureCase.id, checkpoint);
|
|
147
175
|
continue;
|
|
148
176
|
}
|
|
149
177
|
const resourceId = pending[0].resourceId;
|
|
@@ -236,9 +264,9 @@ export async function readLocalSandboxRuntimeWatchOutcome(input) {
|
|
|
236
264
|
}
|
|
237
265
|
throw error;
|
|
238
266
|
}
|
|
239
|
-
const expected = new Map(input.actions.map((action) => [
|
|
240
|
-
if (expected.size !== input.actions.length || !input.resourceId || [...expected.values()].some((action) => !action.id
|
|
241
|
-
return deferred("INSUFFICIENT_EVIDENCE", attempts, observedAt(), "The covered Action
|
|
267
|
+
const expected = new Map(input.actions.map((action) => [action.id, action]));
|
|
268
|
+
if (expected.size !== input.actions.length || !input.resourceId || [...expected.values()].some((action) => !action.id)) {
|
|
269
|
+
return deferred("INSUFFICIENT_EVIDENCE", attempts, observedAt(), "The covered Action bindings are incomplete.");
|
|
242
270
|
}
|
|
243
271
|
const commits = new Map();
|
|
244
272
|
for (const line of source.split(/\r?\n/u)) {
|
|
@@ -257,16 +285,21 @@ export async function readLocalSandboxRuntimeWatchOutcome(input) {
|
|
|
257
285
|
if (!record) {
|
|
258
286
|
return deferred("SCHEMA_DIGEST_DRIFT", attempts, observedAt(), "A committed local sandbox result is missing an allowlisted field.");
|
|
259
287
|
}
|
|
260
|
-
const
|
|
261
|
-
if (record.resourceId !== input.resourceId || !
|
|
288
|
+
const expectedAction = expected.get(record.actionId);
|
|
289
|
+
if (record.resourceId !== input.resourceId || !expectedAction)
|
|
290
|
+
continue;
|
|
291
|
+
if (expectedAction.executionSessionId && expectedAction.executionSessionId !== record.executionSessionId)
|
|
262
292
|
continue;
|
|
263
293
|
const digest = createHash("sha256").update(JSON.stringify(record.observedState)).digest("hex");
|
|
264
294
|
if (digest !== record.stateSha256) {
|
|
265
295
|
return deferred("SCHEMA_DIGEST_DRIFT", attempts, observedAt(), "A covered local sandbox result failed its state digest check.");
|
|
266
296
|
}
|
|
267
|
-
const existing = commits.get(
|
|
297
|
+
const existing = commits.get(record.actionId);
|
|
298
|
+
if (existing && existing.executionSessionId !== record.executionSessionId) {
|
|
299
|
+
return deferred("INSUFFICIENT_EVIDENCE", attempts, observedAt(), "A covered Action has more than one execution-session result.");
|
|
300
|
+
}
|
|
268
301
|
if (!existing || record.at > existing.at)
|
|
269
|
-
commits.set(
|
|
302
|
+
commits.set(record.actionId, { at: record.at, executionSessionId: record.executionSessionId });
|
|
270
303
|
}
|
|
271
304
|
if (commits.size !== expected.size) {
|
|
272
305
|
return deferred("INSUFFICIENT_EVIDENCE", attempts, observedAt(), "Not every covered Action has a digest-verified committed result.");
|
|
@@ -309,9 +342,14 @@ function isRecord(value) {
|
|
|
309
342
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
310
343
|
}
|
|
311
344
|
function coveredOutcomes(failureCase, actions, receipts) {
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
345
|
+
const watchStartedAt = timestamp(failureCase.runtimeWatch?.activatedAt
|
|
346
|
+
?? failureCase.candidate?.recordedAt
|
|
347
|
+
?? failureCase.updatedAt);
|
|
348
|
+
const receiptsByAction = new Map(receipts.filter((receipt) => {
|
|
349
|
+
const receiptCreatedAt = timestamp(receipt.createdAt);
|
|
350
|
+
return eligibleReceipt(receipt)
|
|
351
|
+
&& (!watchStartedAt || (receiptCreatedAt !== undefined && receiptCreatedAt >= watchStartedAt));
|
|
352
|
+
})
|
|
315
353
|
.map((receipt) => [receipt.actionId, receipt]));
|
|
316
354
|
return actions.flatMap((action) => {
|
|
317
355
|
const binding = action.businessTaskBinding;
|
|
@@ -326,9 +364,7 @@ function coveredOutcomes(failureCase, actions, receipts) {
|
|
|
326
364
|
}).sort((left, right) => left.receipt.createdAt.localeCompare(right.receipt.createdAt));
|
|
327
365
|
}
|
|
328
366
|
function coveredBindingKeys(actions, receipts) {
|
|
329
|
-
const coveredActionIds = new Set(receipts.filter(
|
|
330
|
-
&& receipt.receipt.core.enforcementLevel === "ENFORCED"
|
|
331
|
-
&& (receipt.receipt.core.evidenceStrength === "OUTCOME_VERIFIED" || receipt.receipt.core.evidenceStrength === "INDEPENDENTLY_REVIEWED"))
|
|
367
|
+
const coveredActionIds = new Set(receipts.filter(eligibleReceipt)
|
|
332
368
|
.map((receipt) => receipt.actionId));
|
|
333
369
|
return new Set(actions.flatMap((action) => {
|
|
334
370
|
const binding = action.businessTaskBinding;
|
|
@@ -348,6 +384,40 @@ function unique(values) { return [...new Set(values)]; }
|
|
|
348
384
|
function bindingKey(value) {
|
|
349
385
|
return `${value.taskContractId}\0${value.actionPathId}\0${value.environment}`;
|
|
350
386
|
}
|
|
387
|
+
function eligibleReceipt(receipt) {
|
|
388
|
+
return receipt.discoveryBoundary === "SIGNED_VERIFIED_ACTION"
|
|
389
|
+
|| (receipt.currentStatus === "ACTIVE"
|
|
390
|
+
&& receipt.receipt.core.enforcementLevel === "ENFORCED"
|
|
391
|
+
&& (receipt.receipt.core.evidenceStrength === "OUTCOME_VERIFIED"
|
|
392
|
+
|| receipt.receipt.core.evidenceStrength === "INDEPENDENTLY_REVIEWED"));
|
|
393
|
+
}
|
|
394
|
+
function signedVerifiedActionReceipt(value) {
|
|
395
|
+
const receiptId = value.receiptId;
|
|
396
|
+
const actionId = value.id;
|
|
397
|
+
const signatureCount = value.receiptSignatureCount;
|
|
398
|
+
const createdAt = typeof value.updatedAt === "string" ? value.updatedAt : value.createdAt;
|
|
399
|
+
if (value.status !== "VERIFIED"
|
|
400
|
+
|| value.verificationSuccess !== true
|
|
401
|
+
|| typeof receiptId !== "string" || !receiptId
|
|
402
|
+
|| typeof actionId !== "string" || !actionId
|
|
403
|
+
|| !Number.isSafeInteger(signatureCount) || signatureCount < 1
|
|
404
|
+
|| typeof createdAt !== "string" || Number.isNaN(Date.parse(createdAt)))
|
|
405
|
+
return [];
|
|
406
|
+
return [{
|
|
407
|
+
id: receiptId,
|
|
408
|
+
actionId,
|
|
409
|
+
currentStatus: "DISCOVERED",
|
|
410
|
+
createdAt: new Date(createdAt).toISOString(),
|
|
411
|
+
receipt: { core: {} },
|
|
412
|
+
discoveryBoundary: "SIGNED_VERIFIED_ACTION",
|
|
413
|
+
}];
|
|
414
|
+
}
|
|
415
|
+
function timestamp(value) {
|
|
416
|
+
if (!value)
|
|
417
|
+
return undefined;
|
|
418
|
+
const parsed = Date.parse(value);
|
|
419
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
420
|
+
}
|
|
351
421
|
async function hostedJson(requestFetch, url, apiKey, init = {}) {
|
|
352
422
|
const headers = new Headers(init.headers);
|
|
353
423
|
headers.set("authorization", `Bearer ${apiKey}`);
|