witnora 0.18.13 → 0.18.14
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
CHANGED
|
@@ -705,10 +705,10 @@ export async function createConfiguredWorkflowHarness(input) {
|
|
|
705
705
|
readOutcome: async ({ resourceId, actions, receipts }) => input.managed.readLocalSandboxRuntimeWatchOutcome({
|
|
706
706
|
path: join(input.directory, "data", "runtime-sandbox", "fixture", "audit.jsonl"),
|
|
707
707
|
resourceId,
|
|
708
|
-
actions: actions.map((action) =>
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
})
|
|
708
|
+
actions: actions.map((action) => {
|
|
709
|
+
const executionSessionId = receipts.find((receipt) => receipt.actionId === action.id)?.receipt?.core?.executionSessionId;
|
|
710
|
+
return { id: action.id, ...(executionSessionId ? { executionSessionId } : {}) };
|
|
711
|
+
}),
|
|
712
712
|
}),
|
|
713
713
|
})
|
|
714
714
|
: undefined;
|
|
@@ -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}`);
|