@nexart/ai-execution 0.6.0 → 0.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/README.md +294 -10
- package/dist/index.cjs +401 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +303 -3
- package/dist/index.d.ts +303 -3
- package/dist/index.mjs +392 -2
- package/dist/index.mjs.map +1 -1
- package/dist/providers/anthropic.cjs +7 -1
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.mjs +7 -1
- package/dist/providers/anthropic.mjs.map +1 -1
- package/dist/providers/openai.cjs +7 -1
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.mjs +7 -1
- package/dist/providers/openai.mjs.map +1 -1
- package/dist/providers/wrap.cjs +7 -1
- package/dist/providers/wrap.cjs.map +1 -1
- package/dist/providers/wrap.d.cts +1 -1
- package/dist/providers/wrap.d.ts +1 -1
- package/dist/providers/wrap.mjs +7 -1
- package/dist/providers/wrap.mjs.map +1 -1
- package/dist/{types-Cgb52dTx.d.cts → types-CcqCDPrD.d.cts} +68 -1
- package/dist/{types-Cgb52dTx.d.ts → types-CcqCDPrD.d.ts} +68 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ __export(src_exports, {
|
|
|
37
37
|
attest: () => attest,
|
|
38
38
|
attestIfNeeded: () => attestIfNeeded,
|
|
39
39
|
certifyAndAttestDecision: () => certifyAndAttestDecision,
|
|
40
|
+
certifyAndAttestRun: () => certifyAndAttestRun,
|
|
40
41
|
certifyDecision: () => certifyDecision,
|
|
41
42
|
certifyDecisionFromProviderCall: () => certifyDecisionFromProviderCall,
|
|
42
43
|
computeInputHash: () => computeInputHash,
|
|
@@ -44,12 +45,17 @@ __export(src_exports, {
|
|
|
44
45
|
createClient: () => createClient,
|
|
45
46
|
createSnapshot: () => createSnapshot,
|
|
46
47
|
exportCer: () => exportCer,
|
|
48
|
+
exportVerifiableRedacted: () => exportVerifiableRedacted,
|
|
47
49
|
fetchNodeKeys: () => fetchNodeKeys,
|
|
48
50
|
getAttestationReceipt: () => getAttestationReceipt,
|
|
49
51
|
hasAttestation: () => hasAttestation,
|
|
50
52
|
hashCanonicalJson: () => hashCanonicalJson,
|
|
53
|
+
hashToolOutput: () => hashToolOutput,
|
|
51
54
|
hashUtf8: () => hashUtf8,
|
|
52
55
|
importCer: () => importCer,
|
|
56
|
+
makeToolEvent: () => makeToolEvent,
|
|
57
|
+
mapToAiefReason: () => mapToAiefReason,
|
|
58
|
+
redactBeforeSeal: () => redactBeforeSeal,
|
|
53
59
|
sanitizeForAttestation: () => sanitizeForAttestation,
|
|
54
60
|
sanitizeForStamp: () => sanitizeForStamp,
|
|
55
61
|
sanitizeForStorage: () => sanitizeForStorage,
|
|
@@ -57,10 +63,13 @@ __export(src_exports, {
|
|
|
57
63
|
selectNodeKey: () => selectNodeKey,
|
|
58
64
|
sha256Hex: () => sha256Hex,
|
|
59
65
|
toCanonicalJson: () => toCanonicalJson,
|
|
66
|
+
validateProfile: () => validateProfile,
|
|
60
67
|
verify: () => verifyCer,
|
|
68
|
+
verifyAief: () => verifyAief,
|
|
61
69
|
verifyBundleAttestation: () => verifyBundleAttestation,
|
|
62
70
|
verifyCer: () => verifyCer,
|
|
63
71
|
verifyNodeReceiptSignature: () => verifyNodeReceiptSignature,
|
|
72
|
+
verifyRunSummary: () => verifyRunSummary,
|
|
64
73
|
verifySnapshot: () => verifySnapshot,
|
|
65
74
|
wrapProvider: () => wrapProvider
|
|
66
75
|
});
|
|
@@ -80,7 +89,13 @@ var CerVerifyCode = {
|
|
|
80
89
|
ATTESTATION_MISSING: "ATTESTATION_MISSING",
|
|
81
90
|
ATTESTATION_KEY_NOT_FOUND: "ATTESTATION_KEY_NOT_FOUND",
|
|
82
91
|
ATTESTATION_INVALID_SIGNATURE: "ATTESTATION_INVALID_SIGNATURE",
|
|
83
|
-
ATTESTATION_KEY_FORMAT_UNSUPPORTED: "ATTESTATION_KEY_FORMAT_UNSUPPORTED"
|
|
92
|
+
ATTESTATION_KEY_FORMAT_UNSUPPORTED: "ATTESTATION_KEY_FORMAT_UNSUPPORTED",
|
|
93
|
+
// v0.7.0 — Level 4 + AIEF interop codes
|
|
94
|
+
CHAIN_BREAK_DETECTED: "CHAIN_BREAK_DETECTED",
|
|
95
|
+
INCOMPLETE_ARTIFACT: "INCOMPLETE_ARTIFACT",
|
|
96
|
+
VERIFICATION_MATERIAL_UNAVAILABLE: "VERIFICATION_MATERIAL_UNAVAILABLE",
|
|
97
|
+
TOOL_EVIDENCE_MISSING: "TOOL_EVIDENCE_MISSING",
|
|
98
|
+
TOOL_OUTPUT_HASH_MISMATCH: "TOOL_OUTPUT_HASH_MISMATCH"
|
|
84
99
|
};
|
|
85
100
|
|
|
86
101
|
// src/errors.ts
|
|
@@ -176,7 +191,7 @@ function computeOutputHash(output) {
|
|
|
176
191
|
}
|
|
177
192
|
|
|
178
193
|
// src/snapshot.ts
|
|
179
|
-
var PACKAGE_VERSION = "0.
|
|
194
|
+
var PACKAGE_VERSION = "0.8.0";
|
|
180
195
|
function validateParameters(params) {
|
|
181
196
|
const errors = [];
|
|
182
197
|
if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
|
|
@@ -229,6 +244,9 @@ function createSnapshot(params) {
|
|
|
229
244
|
if (params.workflowId !== void 0) snapshot.workflowId = params.workflowId ?? null;
|
|
230
245
|
if (params.conversationId !== void 0) snapshot.conversationId = params.conversationId ?? null;
|
|
231
246
|
if (params.prevStepHash !== void 0) snapshot.prevStepHash = params.prevStepHash ?? null;
|
|
247
|
+
if (params.toolCalls !== void 0 && params.toolCalls.length > 0) {
|
|
248
|
+
snapshot.toolCalls = params.toolCalls;
|
|
249
|
+
}
|
|
232
250
|
return snapshot;
|
|
233
251
|
}
|
|
234
252
|
function verifySnapshot(snapshot) {
|
|
@@ -336,6 +354,9 @@ function sealCer(snapshot, options) {
|
|
|
336
354
|
if (options?.meta) {
|
|
337
355
|
bundle.meta = options.meta;
|
|
338
356
|
}
|
|
357
|
+
if (options?.declaration) {
|
|
358
|
+
bundle.declaration = options.declaration;
|
|
359
|
+
}
|
|
339
360
|
return bundle;
|
|
340
361
|
}
|
|
341
362
|
function verifyCer(bundle) {
|
|
@@ -2150,6 +2171,375 @@ function createClient(defaults = {}) {
|
|
|
2150
2171
|
}
|
|
2151
2172
|
};
|
|
2152
2173
|
}
|
|
2174
|
+
|
|
2175
|
+
// src/aief.ts
|
|
2176
|
+
var AIEF_REASON_MAP = {
|
|
2177
|
+
[CerVerifyCode.OK]: "ok",
|
|
2178
|
+
[CerVerifyCode.CERTIFICATE_HASH_MISMATCH]: "integrityProofMismatch",
|
|
2179
|
+
[CerVerifyCode.SNAPSHOT_HASH_MISMATCH]: "integrityProofMismatch",
|
|
2180
|
+
[CerVerifyCode.INPUT_HASH_MISMATCH]: "integrityProofMismatch",
|
|
2181
|
+
[CerVerifyCode.OUTPUT_HASH_MISMATCH]: "integrityProofMismatch",
|
|
2182
|
+
[CerVerifyCode.TOOL_OUTPUT_HASH_MISMATCH]: "integrityProofMismatch",
|
|
2183
|
+
[CerVerifyCode.SCHEMA_ERROR]: "unsupportedSchema",
|
|
2184
|
+
[CerVerifyCode.CANONICALIZATION_ERROR]: "malformedArtifact",
|
|
2185
|
+
[CerVerifyCode.INVALID_SHA256_FORMAT]: "malformedArtifact",
|
|
2186
|
+
[CerVerifyCode.UNKNOWN_ERROR]: "malformedArtifact",
|
|
2187
|
+
[CerVerifyCode.INCOMPLETE_ARTIFACT]: "incompleteArtifact",
|
|
2188
|
+
[CerVerifyCode.CHAIN_BREAK_DETECTED]: "chainBreakDetected",
|
|
2189
|
+
[CerVerifyCode.VERIFICATION_MATERIAL_UNAVAILABLE]: "verificationMaterialUnavailable",
|
|
2190
|
+
[CerVerifyCode.TOOL_EVIDENCE_MISSING]: "incompleteArtifact",
|
|
2191
|
+
[CerVerifyCode.ATTESTATION_INVALID_SIGNATURE]: "signatureInvalid",
|
|
2192
|
+
[CerVerifyCode.ATTESTATION_MISSING]: "verificationMaterialUnavailable",
|
|
2193
|
+
[CerVerifyCode.ATTESTATION_KEY_NOT_FOUND]: "verificationMaterialUnavailable",
|
|
2194
|
+
[CerVerifyCode.ATTESTATION_KEY_FORMAT_UNSUPPORTED]: "verificationMaterialUnavailable"
|
|
2195
|
+
};
|
|
2196
|
+
var INTEGRITY_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
2197
|
+
CerVerifyCode.CERTIFICATE_HASH_MISMATCH,
|
|
2198
|
+
CerVerifyCode.SNAPSHOT_HASH_MISMATCH,
|
|
2199
|
+
CerVerifyCode.INPUT_HASH_MISMATCH,
|
|
2200
|
+
CerVerifyCode.OUTPUT_HASH_MISMATCH,
|
|
2201
|
+
CerVerifyCode.TOOL_OUTPUT_HASH_MISMATCH
|
|
2202
|
+
]);
|
|
2203
|
+
var SCHEMA_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
2204
|
+
CerVerifyCode.SCHEMA_ERROR,
|
|
2205
|
+
CerVerifyCode.CANONICALIZATION_ERROR,
|
|
2206
|
+
CerVerifyCode.INVALID_SHA256_FORMAT,
|
|
2207
|
+
CerVerifyCode.UNKNOWN_ERROR,
|
|
2208
|
+
CerVerifyCode.INCOMPLETE_ARTIFACT
|
|
2209
|
+
]);
|
|
2210
|
+
function mapToAiefReason(code) {
|
|
2211
|
+
return AIEF_REASON_MAP[code] ?? "malformedArtifact";
|
|
2212
|
+
}
|
|
2213
|
+
function verifyAief(bundle) {
|
|
2214
|
+
const inner = verifyCer(bundle);
|
|
2215
|
+
if (inner.ok) {
|
|
2216
|
+
return {
|
|
2217
|
+
result: "PASS",
|
|
2218
|
+
reason: null,
|
|
2219
|
+
checks: {
|
|
2220
|
+
schemaSupported: true,
|
|
2221
|
+
integrityValid: true,
|
|
2222
|
+
protectedSetValid: true,
|
|
2223
|
+
chainValid: true
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
const aiefReason = mapToAiefReason(inner.code);
|
|
2228
|
+
const isIntegrityFailure = INTEGRITY_FAILURE_CODES.has(inner.code);
|
|
2229
|
+
const isSchemaFailure = SCHEMA_FAILURE_CODES.has(inner.code);
|
|
2230
|
+
const isChainFailure = inner.code === CerVerifyCode.CHAIN_BREAK_DETECTED;
|
|
2231
|
+
const result = {
|
|
2232
|
+
result: "FAIL",
|
|
2233
|
+
reason: aiefReason,
|
|
2234
|
+
checks: {
|
|
2235
|
+
schemaSupported: !isSchemaFailure,
|
|
2236
|
+
integrityValid: !isIntegrityFailure,
|
|
2237
|
+
protectedSetValid: !isIntegrityFailure,
|
|
2238
|
+
chainValid: !isChainFailure
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
if (inner.details && inner.details.length > 0) {
|
|
2242
|
+
result.notes = inner.details;
|
|
2243
|
+
} else if (inner.errors.length > 0) {
|
|
2244
|
+
result.notes = inner.errors;
|
|
2245
|
+
}
|
|
2246
|
+
return result;
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
// src/tools.ts
|
|
2250
|
+
function hashToolOutput(value) {
|
|
2251
|
+
if (typeof value === "string") {
|
|
2252
|
+
return hashUtf8(value);
|
|
2253
|
+
}
|
|
2254
|
+
return hashCanonicalJson(value);
|
|
2255
|
+
}
|
|
2256
|
+
function makeToolEvent(params) {
|
|
2257
|
+
const at = params.at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2258
|
+
const outputHash = hashToolOutput(params.output);
|
|
2259
|
+
const event = {
|
|
2260
|
+
toolId: params.toolId,
|
|
2261
|
+
at,
|
|
2262
|
+
outputHash
|
|
2263
|
+
};
|
|
2264
|
+
if (params.input !== void 0) {
|
|
2265
|
+
event.inputHash = hashToolOutput(params.input);
|
|
2266
|
+
}
|
|
2267
|
+
if (params.evidenceRef !== void 0) {
|
|
2268
|
+
event.evidenceRef = params.evidenceRef;
|
|
2269
|
+
}
|
|
2270
|
+
if (params.error !== void 0) {
|
|
2271
|
+
event.error = params.error;
|
|
2272
|
+
}
|
|
2273
|
+
return event;
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
// src/chain.ts
|
|
2277
|
+
function verifyRunSummary(summary, bundles, opts) {
|
|
2278
|
+
if (bundles.length !== summary.stepCount) {
|
|
2279
|
+
return {
|
|
2280
|
+
ok: false,
|
|
2281
|
+
code: CerVerifyCode.INCOMPLETE_ARTIFACT,
|
|
2282
|
+
errors: [
|
|
2283
|
+
`Step count mismatch: summary declares ${summary.stepCount} step(s), received ${bundles.length}`
|
|
2284
|
+
],
|
|
2285
|
+
details: ["Possible step deletion or insertion"]
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
if (bundles.length === 0) {
|
|
2289
|
+
return { ok: true, code: CerVerifyCode.OK, errors: [] };
|
|
2290
|
+
}
|
|
2291
|
+
let prevHash = null;
|
|
2292
|
+
for (let i = 0; i < bundles.length; i++) {
|
|
2293
|
+
const bundle = bundles[i];
|
|
2294
|
+
const summaryStep = summary.steps[i];
|
|
2295
|
+
if (!summaryStep) {
|
|
2296
|
+
return {
|
|
2297
|
+
ok: false,
|
|
2298
|
+
code: CerVerifyCode.INCOMPLETE_ARTIFACT,
|
|
2299
|
+
errors: [`Missing summary entry for step index ${i}`],
|
|
2300
|
+
breakAt: i
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
if (!opts?.skipBundleVerification) {
|
|
2304
|
+
const bundleResult = verifyCer(bundle);
|
|
2305
|
+
if (!bundleResult.ok) {
|
|
2306
|
+
return {
|
|
2307
|
+
ok: false,
|
|
2308
|
+
code: bundleResult.code,
|
|
2309
|
+
errors: [`Step ${i}: individual bundle verification failed: ${bundleResult.errors.join("; ")}`],
|
|
2310
|
+
details: bundleResult.details,
|
|
2311
|
+
breakAt: i
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
const stepIndex = bundle.snapshot?.stepIndex;
|
|
2316
|
+
if (stepIndex !== i) {
|
|
2317
|
+
return {
|
|
2318
|
+
ok: false,
|
|
2319
|
+
code: CerVerifyCode.CHAIN_BREAK_DETECTED,
|
|
2320
|
+
errors: [`Step ${i}: expected stepIndex ${i}, got ${String(stepIndex)}`],
|
|
2321
|
+
details: ["stepIndex mismatch indicates insertion or reordering"],
|
|
2322
|
+
breakAt: i
|
|
2323
|
+
};
|
|
2324
|
+
}
|
|
2325
|
+
const snapshotPrevHash = bundle.snapshot?.prevStepHash ?? null;
|
|
2326
|
+
if (i === 0) {
|
|
2327
|
+
if (snapshotPrevHash !== null) {
|
|
2328
|
+
return {
|
|
2329
|
+
ok: false,
|
|
2330
|
+
code: CerVerifyCode.CHAIN_BREAK_DETECTED,
|
|
2331
|
+
errors: [`Step 0: expected prevStepHash null, got "${snapshotPrevHash}"`],
|
|
2332
|
+
details: ["First step must have prevStepHash null"],
|
|
2333
|
+
breakAt: 0,
|
|
2334
|
+
expectedPrev: "null",
|
|
2335
|
+
observedPrev: snapshotPrevHash
|
|
2336
|
+
};
|
|
2337
|
+
}
|
|
2338
|
+
} else {
|
|
2339
|
+
if (snapshotPrevHash !== prevHash) {
|
|
2340
|
+
return {
|
|
2341
|
+
ok: false,
|
|
2342
|
+
code: CerVerifyCode.CHAIN_BREAK_DETECTED,
|
|
2343
|
+
errors: [`Step ${i}: prevStepHash mismatch \u2014 chain break detected`],
|
|
2344
|
+
details: [
|
|
2345
|
+
`Expected prevStepHash "${prevHash ?? "null"}", got "${snapshotPrevHash ?? "null"}"`
|
|
2346
|
+
],
|
|
2347
|
+
breakAt: i,
|
|
2348
|
+
expectedPrev: prevHash ?? void 0,
|
|
2349
|
+
observedPrev: snapshotPrevHash ?? void 0
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
if (bundle.certificateHash !== summaryStep.certificateHash) {
|
|
2354
|
+
return {
|
|
2355
|
+
ok: false,
|
|
2356
|
+
code: CerVerifyCode.CHAIN_BREAK_DETECTED,
|
|
2357
|
+
errors: [`Step ${i}: certificateHash does not match summary record`],
|
|
2358
|
+
details: [
|
|
2359
|
+
`Summary has "${summaryStep.certificateHash}", bundle has "${bundle.certificateHash}"`
|
|
2360
|
+
],
|
|
2361
|
+
breakAt: i
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
prevHash = bundle.certificateHash;
|
|
2365
|
+
}
|
|
2366
|
+
const lastBundle = bundles[bundles.length - 1];
|
|
2367
|
+
if (summary.finalStepHash !== lastBundle.certificateHash) {
|
|
2368
|
+
return {
|
|
2369
|
+
ok: false,
|
|
2370
|
+
code: CerVerifyCode.CHAIN_BREAK_DETECTED,
|
|
2371
|
+
errors: ["summary.finalStepHash does not match last step certificateHash"],
|
|
2372
|
+
details: [
|
|
2373
|
+
`Expected "${summary.finalStepHash ?? "null"}", got "${lastBundle.certificateHash}"`
|
|
2374
|
+
],
|
|
2375
|
+
breakAt: bundles.length - 1,
|
|
2376
|
+
expectedPrev: summary.finalStepHash ?? void 0,
|
|
2377
|
+
observedPrev: lastBundle.certificateHash
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
return { ok: true, code: CerVerifyCode.OK, errors: [] };
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
// src/redact.ts
|
|
2384
|
+
function hashValue(value) {
|
|
2385
|
+
if (typeof value === "string") return hashUtf8(value);
|
|
2386
|
+
return hashCanonicalJson(value);
|
|
2387
|
+
}
|
|
2388
|
+
function getNestedValue(obj, path) {
|
|
2389
|
+
const parts = path.split(".");
|
|
2390
|
+
let cursor = obj;
|
|
2391
|
+
for (const part of parts) {
|
|
2392
|
+
if (typeof cursor !== "object" || cursor === null) return void 0;
|
|
2393
|
+
cursor = cursor[part];
|
|
2394
|
+
}
|
|
2395
|
+
return cursor;
|
|
2396
|
+
}
|
|
2397
|
+
function setNestedPath(obj, path, value) {
|
|
2398
|
+
const parts = path.split(".");
|
|
2399
|
+
const clone = { ...obj };
|
|
2400
|
+
let cursor = clone;
|
|
2401
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
2402
|
+
const key = parts[i];
|
|
2403
|
+
const child = cursor[key];
|
|
2404
|
+
if (typeof child !== "object" || child === null) return clone;
|
|
2405
|
+
cursor[key] = { ...child };
|
|
2406
|
+
cursor = cursor[key];
|
|
2407
|
+
}
|
|
2408
|
+
const last = parts[parts.length - 1];
|
|
2409
|
+
if (last in cursor) {
|
|
2410
|
+
cursor[last] = value;
|
|
2411
|
+
}
|
|
2412
|
+
return clone;
|
|
2413
|
+
}
|
|
2414
|
+
function redactBeforeSeal(snapshot, policy) {
|
|
2415
|
+
let result = { ...snapshot };
|
|
2416
|
+
for (const path of policy.paths) {
|
|
2417
|
+
const original = getNestedValue(result, path);
|
|
2418
|
+
if (original === void 0) continue;
|
|
2419
|
+
const envelope = {
|
|
2420
|
+
_redacted: true,
|
|
2421
|
+
hash: hashValue(original)
|
|
2422
|
+
};
|
|
2423
|
+
result = setNestedPath(result, path, envelope);
|
|
2424
|
+
if (path === "input") {
|
|
2425
|
+
result["inputHash"] = computeInputHash(envelope);
|
|
2426
|
+
} else if (path === "output") {
|
|
2427
|
+
result["outputHash"] = computeOutputHash(envelope);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
return result;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
// src/profile.ts
|
|
2434
|
+
var SHA256_PATTERN2 = /^sha256:[0-9a-f]{64}$/;
|
|
2435
|
+
function validateToolEvent(event, index) {
|
|
2436
|
+
const errs = [];
|
|
2437
|
+
if (!event.toolId || typeof event.toolId !== "string") {
|
|
2438
|
+
errs.push(`toolCalls[${index}].toolId must be a non-empty string`);
|
|
2439
|
+
}
|
|
2440
|
+
if (!event.at || typeof event.at !== "string") {
|
|
2441
|
+
errs.push(`toolCalls[${index}].at must be a non-empty ISO 8601 string`);
|
|
2442
|
+
}
|
|
2443
|
+
if (!event.outputHash || !SHA256_PATTERN2.test(event.outputHash)) {
|
|
2444
|
+
errs.push(`toolCalls[${index}].outputHash must be in sha256:<64hex> format, got "${event.outputHash ?? ""}"`);
|
|
2445
|
+
}
|
|
2446
|
+
if (event.inputHash !== void 0 && !SHA256_PATTERN2.test(event.inputHash)) {
|
|
2447
|
+
errs.push(`toolCalls[${index}].inputHash must be in sha256:<64hex> format when present`);
|
|
2448
|
+
}
|
|
2449
|
+
return errs;
|
|
2450
|
+
}
|
|
2451
|
+
function validateL2(snapshot, label) {
|
|
2452
|
+
const errs = [];
|
|
2453
|
+
if (!snapshot.executionId) errs.push(`executionId is required for ${label}`);
|
|
2454
|
+
if (!snapshot.timestamp) errs.push(`timestamp is required for ${label}`);
|
|
2455
|
+
if (!snapshot.provider) errs.push(`provider is required for ${label}`);
|
|
2456
|
+
if (!snapshot.model) errs.push(`model is required for ${label}`);
|
|
2457
|
+
if (snapshot.input === void 0 || snapshot.input === null) errs.push(`input is required for ${label}`);
|
|
2458
|
+
if (snapshot.output === void 0 || snapshot.output === null) errs.push(`output is required for ${label}`);
|
|
2459
|
+
if (!snapshot.inputHash) errs.push(`inputHash is required for ${label}`);
|
|
2460
|
+
if (!snapshot.outputHash) errs.push(`outputHash is required for ${label}`);
|
|
2461
|
+
return errs;
|
|
2462
|
+
}
|
|
2463
|
+
function resolveSnapshot(target) {
|
|
2464
|
+
if ("snapshot" in target && target.snapshot) {
|
|
2465
|
+
return target.snapshot;
|
|
2466
|
+
}
|
|
2467
|
+
return target;
|
|
2468
|
+
}
|
|
2469
|
+
function validateProfile(target, profile) {
|
|
2470
|
+
if (profile === "flexible") {
|
|
2471
|
+
return { ok: true, errors: [] };
|
|
2472
|
+
}
|
|
2473
|
+
const snapshot = resolveSnapshot(target);
|
|
2474
|
+
const errors = [];
|
|
2475
|
+
if (profile === "AIEF_L2" || profile === "AIEF_L3" || profile === "AIEF_L4") {
|
|
2476
|
+
errors.push(...validateL2(snapshot, profile));
|
|
2477
|
+
}
|
|
2478
|
+
if (profile === "AIEF_L4") {
|
|
2479
|
+
if (snapshot.toolCalls && snapshot.toolCalls.length > 0) {
|
|
2480
|
+
for (let i = 0; i < snapshot.toolCalls.length; i++) {
|
|
2481
|
+
errors.push(...validateToolEvent(snapshot.toolCalls[i], i));
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (snapshot.stepIndex !== null && snapshot.stepIndex !== void 0 && snapshot.stepIndex > 0 && !snapshot.prevStepHash) {
|
|
2485
|
+
errors.push("prevStepHash is required when stepIndex > 0 in AIEF_L4 profile");
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
return { ok: errors.length === 0, errors };
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
// src/exportRedacted.ts
|
|
2492
|
+
function exportVerifiableRedacted(bundle, policy, options) {
|
|
2493
|
+
const createdAt = options?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2494
|
+
const redactedSnapshot = redactBeforeSeal(bundle.snapshot, policy);
|
|
2495
|
+
const provenance = {
|
|
2496
|
+
originalCertificateHash: bundle.certificateHash,
|
|
2497
|
+
redactionPolicy: { paths: [...policy.paths] },
|
|
2498
|
+
redactedAt: createdAt
|
|
2499
|
+
};
|
|
2500
|
+
const mergedMeta = {
|
|
2501
|
+
...bundle.meta,
|
|
2502
|
+
provenance
|
|
2503
|
+
};
|
|
2504
|
+
const newBundle = sealCer(redactedSnapshot, {
|
|
2505
|
+
createdAt,
|
|
2506
|
+
meta: mergedMeta,
|
|
2507
|
+
declaration: bundle.declaration
|
|
2508
|
+
});
|
|
2509
|
+
return {
|
|
2510
|
+
bundle: newBundle,
|
|
2511
|
+
originalCertificateHash: bundle.certificateHash
|
|
2512
|
+
};
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
// src/runHelper.ts
|
|
2516
|
+
async function certifyAndAttestRun(steps, options) {
|
|
2517
|
+
const run = new RunBuilder({
|
|
2518
|
+
runId: options?.runId,
|
|
2519
|
+
workflowId: options?.workflowId,
|
|
2520
|
+
conversationId: options?.conversationId,
|
|
2521
|
+
appId: options?.appId
|
|
2522
|
+
});
|
|
2523
|
+
const stepBundles = [];
|
|
2524
|
+
const receipts = [];
|
|
2525
|
+
for (const stepParams of steps) {
|
|
2526
|
+
const bundle = run.step(stepParams);
|
|
2527
|
+
stepBundles.push(bundle);
|
|
2528
|
+
if (options?.attestStep) {
|
|
2529
|
+
const receipt = await options.attestStep(bundle);
|
|
2530
|
+
receipts.push(receipt);
|
|
2531
|
+
} else {
|
|
2532
|
+
receipts.push(null);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
const runSummary = run.finalize();
|
|
2536
|
+
return {
|
|
2537
|
+
runSummary,
|
|
2538
|
+
stepBundles,
|
|
2539
|
+
receipts,
|
|
2540
|
+
finalStepHash: runSummary.finalStepHash
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2153
2543
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2154
2544
|
0 && (module.exports = {
|
|
2155
2545
|
CerAttestationError,
|
|
@@ -2159,6 +2549,7 @@ function createClient(defaults = {}) {
|
|
|
2159
2549
|
attest,
|
|
2160
2550
|
attestIfNeeded,
|
|
2161
2551
|
certifyAndAttestDecision,
|
|
2552
|
+
certifyAndAttestRun,
|
|
2162
2553
|
certifyDecision,
|
|
2163
2554
|
certifyDecisionFromProviderCall,
|
|
2164
2555
|
computeInputHash,
|
|
@@ -2166,12 +2557,17 @@ function createClient(defaults = {}) {
|
|
|
2166
2557
|
createClient,
|
|
2167
2558
|
createSnapshot,
|
|
2168
2559
|
exportCer,
|
|
2560
|
+
exportVerifiableRedacted,
|
|
2169
2561
|
fetchNodeKeys,
|
|
2170
2562
|
getAttestationReceipt,
|
|
2171
2563
|
hasAttestation,
|
|
2172
2564
|
hashCanonicalJson,
|
|
2565
|
+
hashToolOutput,
|
|
2173
2566
|
hashUtf8,
|
|
2174
2567
|
importCer,
|
|
2568
|
+
makeToolEvent,
|
|
2569
|
+
mapToAiefReason,
|
|
2570
|
+
redactBeforeSeal,
|
|
2175
2571
|
sanitizeForAttestation,
|
|
2176
2572
|
sanitizeForStamp,
|
|
2177
2573
|
sanitizeForStorage,
|
|
@@ -2179,10 +2575,13 @@ function createClient(defaults = {}) {
|
|
|
2179
2575
|
selectNodeKey,
|
|
2180
2576
|
sha256Hex,
|
|
2181
2577
|
toCanonicalJson,
|
|
2578
|
+
validateProfile,
|
|
2182
2579
|
verify,
|
|
2580
|
+
verifyAief,
|
|
2183
2581
|
verifyBundleAttestation,
|
|
2184
2582
|
verifyCer,
|
|
2185
2583
|
verifyNodeReceiptSignature,
|
|
2584
|
+
verifyRunSummary,
|
|
2186
2585
|
verifySnapshot,
|
|
2187
2586
|
wrapProvider
|
|
2188
2587
|
});
|