@nexart/ai-execution 0.5.0 → 0.7.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/dist/index.cjs CHANGED
@@ -38,25 +38,36 @@ __export(src_exports, {
38
38
  attestIfNeeded: () => attestIfNeeded,
39
39
  certifyAndAttestDecision: () => certifyAndAttestDecision,
40
40
  certifyDecision: () => certifyDecision,
41
+ certifyDecisionFromProviderCall: () => certifyDecisionFromProviderCall,
41
42
  computeInputHash: () => computeInputHash,
42
43
  computeOutputHash: () => computeOutputHash,
44
+ createClient: () => createClient,
43
45
  createSnapshot: () => createSnapshot,
44
46
  exportCer: () => exportCer,
45
47
  fetchNodeKeys: () => fetchNodeKeys,
46
48
  getAttestationReceipt: () => getAttestationReceipt,
47
49
  hasAttestation: () => hasAttestation,
48
50
  hashCanonicalJson: () => hashCanonicalJson,
51
+ hashToolOutput: () => hashToolOutput,
49
52
  hashUtf8: () => hashUtf8,
50
53
  importCer: () => importCer,
54
+ makeToolEvent: () => makeToolEvent,
55
+ mapToAiefReason: () => mapToAiefReason,
56
+ redactBeforeSeal: () => redactBeforeSeal,
51
57
  sanitizeForAttestation: () => sanitizeForAttestation,
58
+ sanitizeForStamp: () => sanitizeForStamp,
59
+ sanitizeForStorage: () => sanitizeForStorage,
52
60
  sealCer: () => sealCer,
53
61
  selectNodeKey: () => selectNodeKey,
54
62
  sha256Hex: () => sha256Hex,
55
63
  toCanonicalJson: () => toCanonicalJson,
64
+ validateProfile: () => validateProfile,
56
65
  verify: () => verifyCer,
66
+ verifyAief: () => verifyAief,
57
67
  verifyBundleAttestation: () => verifyBundleAttestation,
58
68
  verifyCer: () => verifyCer,
59
69
  verifyNodeReceiptSignature: () => verifyNodeReceiptSignature,
70
+ verifyRunSummary: () => verifyRunSummary,
60
71
  verifySnapshot: () => verifySnapshot,
61
72
  wrapProvider: () => wrapProvider
62
73
  });
@@ -76,7 +87,13 @@ var CerVerifyCode = {
76
87
  ATTESTATION_MISSING: "ATTESTATION_MISSING",
77
88
  ATTESTATION_KEY_NOT_FOUND: "ATTESTATION_KEY_NOT_FOUND",
78
89
  ATTESTATION_INVALID_SIGNATURE: "ATTESTATION_INVALID_SIGNATURE",
79
- ATTESTATION_KEY_FORMAT_UNSUPPORTED: "ATTESTATION_KEY_FORMAT_UNSUPPORTED"
90
+ ATTESTATION_KEY_FORMAT_UNSUPPORTED: "ATTESTATION_KEY_FORMAT_UNSUPPORTED",
91
+ // v0.7.0 — Level 4 + AIEF interop codes
92
+ CHAIN_BREAK_DETECTED: "CHAIN_BREAK_DETECTED",
93
+ INCOMPLETE_ARTIFACT: "INCOMPLETE_ARTIFACT",
94
+ VERIFICATION_MATERIAL_UNAVAILABLE: "VERIFICATION_MATERIAL_UNAVAILABLE",
95
+ TOOL_EVIDENCE_MISSING: "TOOL_EVIDENCE_MISSING",
96
+ TOOL_OUTPUT_HASH_MISMATCH: "TOOL_OUTPUT_HASH_MISMATCH"
80
97
  };
81
98
 
82
99
  // src/errors.ts
@@ -172,7 +189,7 @@ function computeOutputHash(output) {
172
189
  }
173
190
 
174
191
  // src/snapshot.ts
175
- var PACKAGE_VERSION = "0.5.0";
192
+ var PACKAGE_VERSION = "0.7.0";
176
193
  function validateParameters(params) {
177
194
  const errors = [];
178
195
  if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
@@ -225,6 +242,9 @@ function createSnapshot(params) {
225
242
  if (params.workflowId !== void 0) snapshot.workflowId = params.workflowId ?? null;
226
243
  if (params.conversationId !== void 0) snapshot.conversationId = params.conversationId ?? null;
227
244
  if (params.prevStepHash !== void 0) snapshot.prevStepHash = params.prevStepHash ?? null;
245
+ if (params.toolCalls !== void 0 && params.toolCalls.length > 0) {
246
+ snapshot.toolCalls = params.toolCalls;
247
+ }
228
248
  return snapshot;
229
249
  }
230
250
  function verifySnapshot(snapshot) {
@@ -332,6 +352,9 @@ function sealCer(snapshot, options) {
332
352
  if (options?.meta) {
333
353
  bundle.meta = options.meta;
334
354
  }
355
+ if (options?.declaration) {
356
+ bundle.declaration = options.declaration;
357
+ }
335
358
  return bundle;
336
359
  }
337
360
  function verifyCer(bundle) {
@@ -523,9 +546,45 @@ function deepRemoveUndefined(value) {
523
546
  }
524
547
  return value;
525
548
  }
549
+ function redactPath(obj, path, replacement) {
550
+ const parts = path.split(".");
551
+ const clone = { ...obj };
552
+ let cursor = clone;
553
+ for (let i = 0; i < parts.length - 1; i++) {
554
+ const key = parts[i];
555
+ if (typeof cursor[key] !== "object" || cursor[key] === null) return clone;
556
+ cursor[key] = { ...cursor[key] };
557
+ cursor = cursor[key];
558
+ }
559
+ const last = parts[parts.length - 1];
560
+ if (last in cursor) cursor[last] = replacement;
561
+ return clone;
562
+ }
526
563
  function sanitizeForAttestation(bundle) {
527
564
  return deepRemoveUndefined(bundle);
528
565
  }
566
+ function sanitizeForStorage(bundle, options) {
567
+ let cleaned = deepRemoveUndefined(bundle);
568
+ if (options?.redactPaths && options.redactPaths.length > 0) {
569
+ const replacement = options.redactWith ?? "[REDACTED]";
570
+ let obj = cleaned;
571
+ for (const path of options.redactPaths) {
572
+ obj = redactPath(obj, path, replacement);
573
+ }
574
+ cleaned = obj;
575
+ }
576
+ return cleaned;
577
+ }
578
+ function sanitizeForStamp(bundle) {
579
+ const core = {
580
+ bundleType: bundle.bundleType,
581
+ certificateHash: bundle.certificateHash,
582
+ createdAt: bundle.createdAt,
583
+ version: bundle.version,
584
+ snapshot: bundle.snapshot
585
+ };
586
+ return deepRemoveUndefined(core);
587
+ }
529
588
  function hasAttestation(bundle) {
530
589
  if (typeof bundle !== "object" || bundle === null) return false;
531
590
  const b = bundle;
@@ -844,10 +903,10 @@ var M = (a, b = P) => {
844
903
  return r >= 0n ? r : b + r;
845
904
  };
846
905
  var modN = (a) => M(a, N);
847
- var invert = (num, md) => {
848
- if (num === 0n || md <= 0n)
849
- err("no inverse n=" + num + " mod=" + md);
850
- let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
906
+ var invert = (num2, md) => {
907
+ if (num2 === 0n || md <= 0n)
908
+ err("no inverse n=" + num2 + " mod=" + md);
909
+ let a = M(num2, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
851
910
  while (a !== 0n) {
852
911
  const q = b / a, r = b % a;
853
912
  const m = x - u * q, n = y - v * q;
@@ -1064,7 +1123,7 @@ var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
1064
1123
  var I = new Point(0n, 1n, 1n, 0n);
1065
1124
  Point.BASE = G;
1066
1125
  Point.ZERO = I;
1067
- var numTo32bLE = (num) => hexToBytes(padh(assertRange(num, 0n, B256), L2)).reverse();
1126
+ var numTo32bLE = (num2) => hexToBytes(padh(assertRange(num2, 0n, B256), L2)).reverse();
1068
1127
  var bytesToNumLE = (b) => big("0x" + bytesToHex(u8fr(abytes(b)).reverse()));
1069
1128
  var pow2 = (x, power) => {
1070
1129
  let r = x;
@@ -1237,10 +1296,10 @@ function clean(...arrays) {
1237
1296
  function createView(arr) {
1238
1297
  return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
1239
1298
  }
1240
- function utf8ToBytes(str) {
1241
- if (typeof str !== "string")
1299
+ function utf8ToBytes(str2) {
1300
+ if (typeof str2 !== "string")
1242
1301
  throw new Error("string expected");
1243
- return new Uint8Array(new TextEncoder().encode(str));
1302
+ return new Uint8Array(new TextEncoder().encode(str2));
1244
1303
  }
1245
1304
  function toBytes(data) {
1246
1305
  if (typeof data === "string")
@@ -1846,6 +1905,586 @@ async function verifyBundleAttestation(bundle, options) {
1846
1905
  if (contextLines.length === 0) return sigResult;
1847
1906
  return sigResult.ok ? { ok: true, code: CerVerifyCode.OK, details: contextLines } : { ...sigResult, details: [...contextLines, ...sigResult.details ?? []] };
1848
1907
  }
1908
+
1909
+ // src/certifyFromProvider.ts
1910
+ var crypto5 = __toESM(require("crypto"), 1);
1911
+
1912
+ // src/providerExtract.ts
1913
+ function str(v) {
1914
+ return typeof v === "string" && v.length > 0 ? v : null;
1915
+ }
1916
+ function num(v, fallback) {
1917
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
1918
+ }
1919
+ function numOrNull(v) {
1920
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
1921
+ }
1922
+ function extractChoicesOutput(response) {
1923
+ const choices = response.choices;
1924
+ if (!Array.isArray(choices) || choices.length === 0) return null;
1925
+ const first = choices[0];
1926
+ if (!first || typeof first !== "object") return null;
1927
+ const msg = first.message;
1928
+ if (!msg || typeof msg !== "object") return null;
1929
+ if (typeof msg.content === "string") return msg.content;
1930
+ if (Array.isArray(msg.content)) {
1931
+ const texts = msg.content.filter((p) => typeof p === "object" && p !== null).map((p) => str(p.text)).filter((t) => t !== null);
1932
+ return texts.length > 0 ? texts.join("\n") : null;
1933
+ }
1934
+ return null;
1935
+ }
1936
+ function extractAnthropicOutput(response) {
1937
+ const content = response.content;
1938
+ if (!Array.isArray(content) || content.length === 0) return null;
1939
+ const first = content[0];
1940
+ if (!first || typeof first !== "object") return null;
1941
+ return str(first.text);
1942
+ }
1943
+ function extractGeminiOutput(response) {
1944
+ const candidates = response.candidates;
1945
+ if (!Array.isArray(candidates) || candidates.length === 0) return null;
1946
+ const first = candidates[0];
1947
+ if (!first || typeof first !== "object") return null;
1948
+ const contentObj = first.content;
1949
+ if (!contentObj || typeof contentObj !== "object") return null;
1950
+ const parts = contentObj.parts;
1951
+ if (!Array.isArray(parts) || parts.length === 0) return null;
1952
+ const part = parts[0];
1953
+ if (!part || typeof part !== "object") return null;
1954
+ return str(part.text);
1955
+ }
1956
+ function extractGenericOutput(response) {
1957
+ return str(response.text) ?? str(response.output_text) ?? (typeof response.output === "string" ? response.output : null) ?? str(response.result) ?? null;
1958
+ }
1959
+ function extractOutput(response) {
1960
+ return extractChoicesOutput(response) ?? extractAnthropicOutput(response) ?? extractGeminiOutput(response) ?? extractGenericOutput(response);
1961
+ }
1962
+ function extractInput(request) {
1963
+ if (Array.isArray(request.messages) && request.messages.length > 0) {
1964
+ return { messages: request.messages };
1965
+ }
1966
+ if (Array.isArray(request.contents) && request.contents.length > 0) {
1967
+ return { contents: request.contents };
1968
+ }
1969
+ if (typeof request.prompt === "string") return request.prompt;
1970
+ if (typeof request.input === "string") return request.input;
1971
+ if (typeof request.input === "object" && request.input !== null) {
1972
+ return request.input;
1973
+ }
1974
+ return null;
1975
+ }
1976
+ function derivePrompt(request) {
1977
+ if (typeof request.prompt === "string") return request.prompt;
1978
+ if (Array.isArray(request.messages)) {
1979
+ const msgs = request.messages;
1980
+ for (let i = msgs.length - 1; i >= 0; i--) {
1981
+ const msg = msgs[i];
1982
+ if (msg.role === "user" || msg.role === "human") {
1983
+ const content = msg.content;
1984
+ if (typeof content === "string") return content;
1985
+ if (Array.isArray(content)) {
1986
+ const text = content.filter((p) => typeof p === "object" && p !== null).map((p) => str(p.text)).filter((t) => t !== null).join("\n");
1987
+ if (text) return text;
1988
+ }
1989
+ }
1990
+ }
1991
+ }
1992
+ if (Array.isArray(request.contents)) {
1993
+ const contents = request.contents;
1994
+ for (let i = contents.length - 1; i >= 0; i--) {
1995
+ const c = contents[i];
1996
+ if (c.role === "user") {
1997
+ const parts = c.parts;
1998
+ if (Array.isArray(parts)) {
1999
+ const text = parts.map((p) => str(p.text)).filter((t) => t !== null).join("\n");
2000
+ if (text) return text;
2001
+ }
2002
+ }
2003
+ }
2004
+ }
2005
+ return null;
2006
+ }
2007
+ function extractParams(request) {
2008
+ const cfg = typeof request.generationConfig === "object" && request.generationConfig !== null ? request.generationConfig : request;
2009
+ return {
2010
+ temperature: num(cfg.temperature, 1),
2011
+ maxTokens: num(cfg.max_tokens ?? cfg.maxTokens ?? cfg.maxOutputTokens ?? cfg.max_output_tokens, 1024),
2012
+ topP: numOrNull(cfg.top_p ?? cfg.topP),
2013
+ seed: numOrNull(cfg.seed)
2014
+ };
2015
+ }
2016
+ function extractModel(providerHint, request, response, override) {
2017
+ const raw = override ?? str(request.model) ?? str(request.modelId) ?? // Bedrock
2018
+ str(response.model) ?? str(response.modelId) ?? null;
2019
+ if (!raw) return null;
2020
+ const parts = raw.split("/");
2021
+ const modelName = parts[parts.length - 1];
2022
+ const modelVersion = str(response.model_version ?? response.modelVersion) ?? null;
2023
+ return { model: modelName, modelVersion };
2024
+ }
2025
+ function tryUnwrapBedrock(request) {
2026
+ const modelId = str(request.modelId);
2027
+ if (!modelId) return null;
2028
+ let body = {};
2029
+ if (typeof request.body === "string") {
2030
+ try {
2031
+ body = JSON.parse(request.body);
2032
+ } catch {
2033
+ body = {};
2034
+ }
2035
+ } else if (typeof request.body === "object" && request.body !== null) {
2036
+ body = request.body;
2037
+ }
2038
+ return { req: { ...body, modelId }, modelId };
2039
+ }
2040
+ function extractFromProviderCall(provider, modelOverride, rawRequest, rawResponse) {
2041
+ let request = rawRequest;
2042
+ if (provider === "bedrock" || str(rawRequest.modelId)) {
2043
+ const unwrapped = tryUnwrapBedrock(rawRequest);
2044
+ if (unwrapped) request = unwrapped.req;
2045
+ }
2046
+ const modelResult = extractModel(provider, request, rawResponse, modelOverride);
2047
+ if (!modelResult) {
2048
+ return {
2049
+ ok: false,
2050
+ reason: "Could not determine model name. Provide it via the `model` field, or ensure request.model / request.modelId is present."
2051
+ };
2052
+ }
2053
+ const input = extractInput(request);
2054
+ if (input === null) {
2055
+ return {
2056
+ ok: false,
2057
+ reason: "Could not extract input. Expected request.messages (OpenAI/Anthropic/Mistral), request.contents (Gemini), or request.prompt/request.input (generic)."
2058
+ };
2059
+ }
2060
+ const prompt = derivePrompt(request) ?? (typeof input === "string" ? input : "[structured input]");
2061
+ const output = extractOutput(rawResponse);
2062
+ if (output === null) {
2063
+ return {
2064
+ ok: false,
2065
+ reason: "Could not extract output text. Expected response.choices[0].message.content (OpenAI/Mistral), response.content[0].text (Anthropic), response.candidates[0].content.parts[0].text (Gemini), or response.text / response.output_text (generic)."
2066
+ };
2067
+ }
2068
+ const parameters = extractParams(request);
2069
+ return {
2070
+ ok: true,
2071
+ data: {
2072
+ model: modelResult.model,
2073
+ modelVersion: modelResult.modelVersion,
2074
+ prompt,
2075
+ input,
2076
+ output,
2077
+ parameters
2078
+ }
2079
+ };
2080
+ }
2081
+
2082
+ // src/certifyFromProvider.ts
2083
+ function certifyDecisionFromProviderCall(params) {
2084
+ const extracted = extractFromProviderCall(
2085
+ params.provider,
2086
+ params.model,
2087
+ params.request,
2088
+ params.response
2089
+ );
2090
+ if (!extracted.ok) {
2091
+ return { ok: false, code: CerVerifyCode.SCHEMA_ERROR, reason: extracted.reason };
2092
+ }
2093
+ const { model, modelVersion, prompt, input, output, parameters } = extracted.data;
2094
+ try {
2095
+ const snapshot = createSnapshot({
2096
+ executionId: params.executionId ?? crypto5.randomUUID(),
2097
+ timestamp: params.timestamp,
2098
+ provider: params.provider,
2099
+ model,
2100
+ modelVersion,
2101
+ prompt,
2102
+ input,
2103
+ parameters,
2104
+ output,
2105
+ appId: params.appId ?? null,
2106
+ workflowId: params.workflowId ?? null,
2107
+ conversationId: params.conversationId ?? null
2108
+ });
2109
+ const bundle = sealCer(snapshot, { meta: params.meta, createdAt: params.createdAt });
2110
+ return { ok: true, bundle };
2111
+ } catch (err2) {
2112
+ return {
2113
+ ok: false,
2114
+ code: CerVerifyCode.SCHEMA_ERROR,
2115
+ reason: err2 instanceof Error ? err2.message : String(err2)
2116
+ };
2117
+ }
2118
+ }
2119
+
2120
+ // src/client.ts
2121
+ async function resolveApiKey(key) {
2122
+ if (typeof key === "function") return key();
2123
+ return key ?? "";
2124
+ }
2125
+ function mergeDefaultMeta(defaults, meta) {
2126
+ const base = {};
2127
+ if (defaults.tags && defaults.tags.length > 0) base.tags = defaults.tags;
2128
+ if (defaults.source) base.source = defaults.source;
2129
+ if (!meta && Object.keys(base).length === 0) return void 0;
2130
+ return { ...base, ...meta };
2131
+ }
2132
+ function createClient(defaults = {}) {
2133
+ return {
2134
+ certifyDecision(params) {
2135
+ return certifyDecision({
2136
+ appId: defaults.appId ?? null,
2137
+ workflowId: defaults.workflowId ?? null,
2138
+ ...params,
2139
+ meta: mergeDefaultMeta(defaults, params.meta)
2140
+ });
2141
+ },
2142
+ async certifyAndAttestDecision(params, options) {
2143
+ const nodeUrl = options?.nodeUrl ?? defaults.nodeUrl;
2144
+ if (!nodeUrl) {
2145
+ throw new Error("certifyAndAttestDecision requires nodeUrl (set in defaults or options)");
2146
+ }
2147
+ const apiKey = options?.apiKey ?? await resolveApiKey(defaults.apiKey);
2148
+ const mergedParams = {
2149
+ appId: defaults.appId ?? null,
2150
+ workflowId: defaults.workflowId ?? null,
2151
+ ...params,
2152
+ meta: mergeDefaultMeta(defaults, params.meta)
2153
+ };
2154
+ return certifyAndAttestDecision(mergedParams, {
2155
+ nodeUrl,
2156
+ apiKey,
2157
+ timeoutMs: options?.timeoutMs
2158
+ });
2159
+ },
2160
+ verify(bundle) {
2161
+ return verifyCer(bundle);
2162
+ },
2163
+ async verifyBundleAttestation(bundle, options) {
2164
+ const nodeUrl = options?.nodeUrl ?? defaults.nodeUrl;
2165
+ if (!nodeUrl) {
2166
+ throw new Error("verifyBundleAttestation requires nodeUrl (set in defaults or options)");
2167
+ }
2168
+ return verifyBundleAttestation(bundle, { nodeUrl, kid: options?.kid });
2169
+ }
2170
+ };
2171
+ }
2172
+
2173
+ // src/aief.ts
2174
+ var AIEF_REASON_MAP = {
2175
+ [CerVerifyCode.OK]: "ok",
2176
+ [CerVerifyCode.CERTIFICATE_HASH_MISMATCH]: "integrityProofMismatch",
2177
+ [CerVerifyCode.SNAPSHOT_HASH_MISMATCH]: "integrityProofMismatch",
2178
+ [CerVerifyCode.INPUT_HASH_MISMATCH]: "integrityProofMismatch",
2179
+ [CerVerifyCode.OUTPUT_HASH_MISMATCH]: "integrityProofMismatch",
2180
+ [CerVerifyCode.TOOL_OUTPUT_HASH_MISMATCH]: "integrityProofMismatch",
2181
+ [CerVerifyCode.SCHEMA_ERROR]: "unsupportedSchema",
2182
+ [CerVerifyCode.CANONICALIZATION_ERROR]: "malformedArtifact",
2183
+ [CerVerifyCode.INVALID_SHA256_FORMAT]: "malformedArtifact",
2184
+ [CerVerifyCode.UNKNOWN_ERROR]: "malformedArtifact",
2185
+ [CerVerifyCode.INCOMPLETE_ARTIFACT]: "incompleteArtifact",
2186
+ [CerVerifyCode.CHAIN_BREAK_DETECTED]: "chainBreakDetected",
2187
+ [CerVerifyCode.VERIFICATION_MATERIAL_UNAVAILABLE]: "verificationMaterialUnavailable",
2188
+ [CerVerifyCode.TOOL_EVIDENCE_MISSING]: "incompleteArtifact",
2189
+ [CerVerifyCode.ATTESTATION_INVALID_SIGNATURE]: "signatureInvalid",
2190
+ [CerVerifyCode.ATTESTATION_MISSING]: "verificationMaterialUnavailable",
2191
+ [CerVerifyCode.ATTESTATION_KEY_NOT_FOUND]: "verificationMaterialUnavailable",
2192
+ [CerVerifyCode.ATTESTATION_KEY_FORMAT_UNSUPPORTED]: "verificationMaterialUnavailable"
2193
+ };
2194
+ var INTEGRITY_FAILURE_CODES = /* @__PURE__ */ new Set([
2195
+ CerVerifyCode.CERTIFICATE_HASH_MISMATCH,
2196
+ CerVerifyCode.SNAPSHOT_HASH_MISMATCH,
2197
+ CerVerifyCode.INPUT_HASH_MISMATCH,
2198
+ CerVerifyCode.OUTPUT_HASH_MISMATCH,
2199
+ CerVerifyCode.TOOL_OUTPUT_HASH_MISMATCH
2200
+ ]);
2201
+ var SCHEMA_FAILURE_CODES = /* @__PURE__ */ new Set([
2202
+ CerVerifyCode.SCHEMA_ERROR,
2203
+ CerVerifyCode.CANONICALIZATION_ERROR,
2204
+ CerVerifyCode.INVALID_SHA256_FORMAT,
2205
+ CerVerifyCode.UNKNOWN_ERROR,
2206
+ CerVerifyCode.INCOMPLETE_ARTIFACT
2207
+ ]);
2208
+ function mapToAiefReason(code) {
2209
+ return AIEF_REASON_MAP[code] ?? "malformedArtifact";
2210
+ }
2211
+ function verifyAief(bundle) {
2212
+ const inner = verifyCer(bundle);
2213
+ if (inner.ok) {
2214
+ return {
2215
+ result: "PASS",
2216
+ reason: null,
2217
+ checks: {
2218
+ schemaSupported: true,
2219
+ integrityValid: true,
2220
+ protectedSetValid: true,
2221
+ chainValid: true
2222
+ }
2223
+ };
2224
+ }
2225
+ const aiefReason = mapToAiefReason(inner.code);
2226
+ const isIntegrityFailure = INTEGRITY_FAILURE_CODES.has(inner.code);
2227
+ const isSchemaFailure = SCHEMA_FAILURE_CODES.has(inner.code);
2228
+ const isChainFailure = inner.code === CerVerifyCode.CHAIN_BREAK_DETECTED;
2229
+ const result = {
2230
+ result: "FAIL",
2231
+ reason: aiefReason,
2232
+ checks: {
2233
+ schemaSupported: !isSchemaFailure,
2234
+ integrityValid: !isIntegrityFailure,
2235
+ protectedSetValid: !isIntegrityFailure,
2236
+ chainValid: !isChainFailure
2237
+ }
2238
+ };
2239
+ if (inner.details && inner.details.length > 0) {
2240
+ result.notes = inner.details;
2241
+ } else if (inner.errors.length > 0) {
2242
+ result.notes = inner.errors;
2243
+ }
2244
+ return result;
2245
+ }
2246
+
2247
+ // src/tools.ts
2248
+ function hashToolOutput(value) {
2249
+ if (typeof value === "string") {
2250
+ return hashUtf8(value);
2251
+ }
2252
+ return hashCanonicalJson(value);
2253
+ }
2254
+ function makeToolEvent(params) {
2255
+ const at = params.at ?? (/* @__PURE__ */ new Date()).toISOString();
2256
+ const outputHash = hashToolOutput(params.output);
2257
+ const event = {
2258
+ toolId: params.toolId,
2259
+ at,
2260
+ outputHash
2261
+ };
2262
+ if (params.input !== void 0) {
2263
+ event.inputHash = hashToolOutput(params.input);
2264
+ }
2265
+ if (params.evidenceRef !== void 0) {
2266
+ event.evidenceRef = params.evidenceRef;
2267
+ }
2268
+ if (params.error !== void 0) {
2269
+ event.error = params.error;
2270
+ }
2271
+ return event;
2272
+ }
2273
+
2274
+ // src/chain.ts
2275
+ function verifyRunSummary(summary, bundles, opts) {
2276
+ if (bundles.length !== summary.stepCount) {
2277
+ return {
2278
+ ok: false,
2279
+ code: CerVerifyCode.INCOMPLETE_ARTIFACT,
2280
+ errors: [
2281
+ `Step count mismatch: summary declares ${summary.stepCount} step(s), received ${bundles.length}`
2282
+ ],
2283
+ details: ["Possible step deletion or insertion"]
2284
+ };
2285
+ }
2286
+ if (bundles.length === 0) {
2287
+ return { ok: true, code: CerVerifyCode.OK, errors: [] };
2288
+ }
2289
+ let prevHash = null;
2290
+ for (let i = 0; i < bundles.length; i++) {
2291
+ const bundle = bundles[i];
2292
+ const summaryStep = summary.steps[i];
2293
+ if (!summaryStep) {
2294
+ return {
2295
+ ok: false,
2296
+ code: CerVerifyCode.INCOMPLETE_ARTIFACT,
2297
+ errors: [`Missing summary entry for step index ${i}`],
2298
+ breakAt: i
2299
+ };
2300
+ }
2301
+ if (!opts?.skipBundleVerification) {
2302
+ const bundleResult = verifyCer(bundle);
2303
+ if (!bundleResult.ok) {
2304
+ return {
2305
+ ok: false,
2306
+ code: bundleResult.code,
2307
+ errors: [`Step ${i}: individual bundle verification failed: ${bundleResult.errors.join("; ")}`],
2308
+ details: bundleResult.details,
2309
+ breakAt: i
2310
+ };
2311
+ }
2312
+ }
2313
+ const stepIndex = bundle.snapshot?.stepIndex;
2314
+ if (stepIndex !== i) {
2315
+ return {
2316
+ ok: false,
2317
+ code: CerVerifyCode.CHAIN_BREAK_DETECTED,
2318
+ errors: [`Step ${i}: expected stepIndex ${i}, got ${String(stepIndex)}`],
2319
+ details: ["stepIndex mismatch indicates insertion or reordering"],
2320
+ breakAt: i
2321
+ };
2322
+ }
2323
+ const snapshotPrevHash = bundle.snapshot?.prevStepHash ?? null;
2324
+ if (i === 0) {
2325
+ if (snapshotPrevHash !== null) {
2326
+ return {
2327
+ ok: false,
2328
+ code: CerVerifyCode.CHAIN_BREAK_DETECTED,
2329
+ errors: [`Step 0: expected prevStepHash null, got "${snapshotPrevHash}"`],
2330
+ details: ["First step must have prevStepHash null"],
2331
+ breakAt: 0,
2332
+ expectedPrev: "null",
2333
+ observedPrev: snapshotPrevHash
2334
+ };
2335
+ }
2336
+ } else {
2337
+ if (snapshotPrevHash !== prevHash) {
2338
+ return {
2339
+ ok: false,
2340
+ code: CerVerifyCode.CHAIN_BREAK_DETECTED,
2341
+ errors: [`Step ${i}: prevStepHash mismatch \u2014 chain break detected`],
2342
+ details: [
2343
+ `Expected prevStepHash "${prevHash ?? "null"}", got "${snapshotPrevHash ?? "null"}"`
2344
+ ],
2345
+ breakAt: i,
2346
+ expectedPrev: prevHash ?? void 0,
2347
+ observedPrev: snapshotPrevHash ?? void 0
2348
+ };
2349
+ }
2350
+ }
2351
+ if (bundle.certificateHash !== summaryStep.certificateHash) {
2352
+ return {
2353
+ ok: false,
2354
+ code: CerVerifyCode.CHAIN_BREAK_DETECTED,
2355
+ errors: [`Step ${i}: certificateHash does not match summary record`],
2356
+ details: [
2357
+ `Summary has "${summaryStep.certificateHash}", bundle has "${bundle.certificateHash}"`
2358
+ ],
2359
+ breakAt: i
2360
+ };
2361
+ }
2362
+ prevHash = bundle.certificateHash;
2363
+ }
2364
+ const lastBundle = bundles[bundles.length - 1];
2365
+ if (summary.finalStepHash !== lastBundle.certificateHash) {
2366
+ return {
2367
+ ok: false,
2368
+ code: CerVerifyCode.CHAIN_BREAK_DETECTED,
2369
+ errors: ["summary.finalStepHash does not match last step certificateHash"],
2370
+ details: [
2371
+ `Expected "${summary.finalStepHash ?? "null"}", got "${lastBundle.certificateHash}"`
2372
+ ],
2373
+ breakAt: bundles.length - 1,
2374
+ expectedPrev: summary.finalStepHash ?? void 0,
2375
+ observedPrev: lastBundle.certificateHash
2376
+ };
2377
+ }
2378
+ return { ok: true, code: CerVerifyCode.OK, errors: [] };
2379
+ }
2380
+
2381
+ // src/redact.ts
2382
+ function hashValue(value) {
2383
+ if (typeof value === "string") return hashUtf8(value);
2384
+ return hashCanonicalJson(value);
2385
+ }
2386
+ function getNestedValue(obj, path) {
2387
+ const parts = path.split(".");
2388
+ let cursor = obj;
2389
+ for (const part of parts) {
2390
+ if (typeof cursor !== "object" || cursor === null) return void 0;
2391
+ cursor = cursor[part];
2392
+ }
2393
+ return cursor;
2394
+ }
2395
+ function setNestedPath(obj, path, value) {
2396
+ const parts = path.split(".");
2397
+ const clone = { ...obj };
2398
+ let cursor = clone;
2399
+ for (let i = 0; i < parts.length - 1; i++) {
2400
+ const key = parts[i];
2401
+ const child = cursor[key];
2402
+ if (typeof child !== "object" || child === null) return clone;
2403
+ cursor[key] = { ...child };
2404
+ cursor = cursor[key];
2405
+ }
2406
+ const last = parts[parts.length - 1];
2407
+ if (last in cursor) {
2408
+ cursor[last] = value;
2409
+ }
2410
+ return clone;
2411
+ }
2412
+ function redactBeforeSeal(snapshot, policy) {
2413
+ let result = { ...snapshot };
2414
+ for (const path of policy.paths) {
2415
+ const original = getNestedValue(result, path);
2416
+ if (original === void 0) continue;
2417
+ const envelope = {
2418
+ _redacted: true,
2419
+ hash: hashValue(original)
2420
+ };
2421
+ result = setNestedPath(result, path, envelope);
2422
+ if (path === "input") {
2423
+ result["inputHash"] = computeInputHash(envelope);
2424
+ } else if (path === "output") {
2425
+ result["outputHash"] = computeOutputHash(envelope);
2426
+ }
2427
+ }
2428
+ return result;
2429
+ }
2430
+
2431
+ // src/profile.ts
2432
+ var SHA256_PATTERN2 = /^sha256:[0-9a-f]{64}$/;
2433
+ function validateToolEvent(event, index) {
2434
+ const errs = [];
2435
+ if (!event.toolId || typeof event.toolId !== "string") {
2436
+ errs.push(`toolCalls[${index}].toolId must be a non-empty string`);
2437
+ }
2438
+ if (!event.at || typeof event.at !== "string") {
2439
+ errs.push(`toolCalls[${index}].at must be a non-empty ISO 8601 string`);
2440
+ }
2441
+ if (!event.outputHash || !SHA256_PATTERN2.test(event.outputHash)) {
2442
+ errs.push(`toolCalls[${index}].outputHash must be in sha256:<64hex> format, got "${event.outputHash ?? ""}"`);
2443
+ }
2444
+ if (event.inputHash !== void 0 && !SHA256_PATTERN2.test(event.inputHash)) {
2445
+ errs.push(`toolCalls[${index}].inputHash must be in sha256:<64hex> format when present`);
2446
+ }
2447
+ return errs;
2448
+ }
2449
+ function validateL2(snapshot, label) {
2450
+ const errs = [];
2451
+ if (!snapshot.executionId) errs.push(`executionId is required for ${label}`);
2452
+ if (!snapshot.timestamp) errs.push(`timestamp is required for ${label}`);
2453
+ if (!snapshot.provider) errs.push(`provider is required for ${label}`);
2454
+ if (!snapshot.model) errs.push(`model is required for ${label}`);
2455
+ if (snapshot.input === void 0 || snapshot.input === null) errs.push(`input is required for ${label}`);
2456
+ if (snapshot.output === void 0 || snapshot.output === null) errs.push(`output is required for ${label}`);
2457
+ if (!snapshot.inputHash) errs.push(`inputHash is required for ${label}`);
2458
+ if (!snapshot.outputHash) errs.push(`outputHash is required for ${label}`);
2459
+ return errs;
2460
+ }
2461
+ function resolveSnapshot(target) {
2462
+ if ("snapshot" in target && target.snapshot) {
2463
+ return target.snapshot;
2464
+ }
2465
+ return target;
2466
+ }
2467
+ function validateProfile(target, profile) {
2468
+ if (profile === "flexible") {
2469
+ return { ok: true, errors: [] };
2470
+ }
2471
+ const snapshot = resolveSnapshot(target);
2472
+ const errors = [];
2473
+ if (profile === "AIEF_L2" || profile === "AIEF_L3" || profile === "AIEF_L4") {
2474
+ errors.push(...validateL2(snapshot, profile));
2475
+ }
2476
+ if (profile === "AIEF_L4") {
2477
+ if (snapshot.toolCalls && snapshot.toolCalls.length > 0) {
2478
+ for (let i = 0; i < snapshot.toolCalls.length; i++) {
2479
+ errors.push(...validateToolEvent(snapshot.toolCalls[i], i));
2480
+ }
2481
+ }
2482
+ if (snapshot.stepIndex !== null && snapshot.stepIndex !== void 0 && snapshot.stepIndex > 0 && !snapshot.prevStepHash) {
2483
+ errors.push("prevStepHash is required when stepIndex > 0 in AIEF_L4 profile");
2484
+ }
2485
+ }
2486
+ return { ok: errors.length === 0, errors };
2487
+ }
1849
2488
  // Annotate the CommonJS export names for ESM import in node:
1850
2489
  0 && (module.exports = {
1851
2490
  CerAttestationError,
@@ -1856,25 +2495,36 @@ async function verifyBundleAttestation(bundle, options) {
1856
2495
  attestIfNeeded,
1857
2496
  certifyAndAttestDecision,
1858
2497
  certifyDecision,
2498
+ certifyDecisionFromProviderCall,
1859
2499
  computeInputHash,
1860
2500
  computeOutputHash,
2501
+ createClient,
1861
2502
  createSnapshot,
1862
2503
  exportCer,
1863
2504
  fetchNodeKeys,
1864
2505
  getAttestationReceipt,
1865
2506
  hasAttestation,
1866
2507
  hashCanonicalJson,
2508
+ hashToolOutput,
1867
2509
  hashUtf8,
1868
2510
  importCer,
2511
+ makeToolEvent,
2512
+ mapToAiefReason,
2513
+ redactBeforeSeal,
1869
2514
  sanitizeForAttestation,
2515
+ sanitizeForStamp,
2516
+ sanitizeForStorage,
1870
2517
  sealCer,
1871
2518
  selectNodeKey,
1872
2519
  sha256Hex,
1873
2520
  toCanonicalJson,
2521
+ validateProfile,
1874
2522
  verify,
2523
+ verifyAief,
1875
2524
  verifyBundleAttestation,
1876
2525
  verifyCer,
1877
2526
  verifyNodeReceiptSignature,
2527
+ verifyRunSummary,
1878
2528
  verifySnapshot,
1879
2529
  wrapProvider
1880
2530
  });