@nexart/ai-execution 0.2.0 → 0.4.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 +100 -330
- package/dist/index.cjs +607 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +55 -11
- package/dist/index.mjs +550 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/anthropic.cjs +258 -0
- package/dist/providers/anthropic.cjs.map +1 -0
- package/dist/providers/anthropic.d.cts +24 -0
- package/dist/providers/anthropic.d.ts +7 -5
- package/dist/providers/anthropic.mjs +221 -0
- package/dist/providers/anthropic.mjs.map +1 -0
- package/dist/providers/openai.cjs +259 -0
- package/dist/providers/openai.cjs.map +1 -0
- package/dist/providers/openai.d.cts +24 -0
- package/dist/providers/openai.d.ts +7 -5
- package/dist/providers/openai.mjs +222 -0
- package/dist/providers/openai.mjs.map +1 -0
- package/dist/providers/wrap.cjs +221 -0
- package/dist/providers/wrap.cjs.map +1 -0
- package/dist/providers/wrap.d.cts +9 -0
- package/dist/providers/wrap.d.ts +5 -3
- package/dist/providers/wrap.mjs +186 -0
- package/dist/providers/wrap.mjs.map +1 -0
- package/dist/{types.d.ts → types-DF29BsH5.d.cts} +18 -16
- package/dist/types-DF29BsH5.d.ts +155 -0
- package/package.json +18 -9
- package/dist/__tests__/fixtures.test.d.ts +0 -2
- package/dist/__tests__/fixtures.test.d.ts.map +0 -1
- package/dist/__tests__/fixtures.test.js +0 -37
- package/dist/__tests__/fixtures.test.js.map +0 -1
- package/dist/__tests__/v020.test.d.ts +0 -2
- package/dist/__tests__/v020.test.d.ts.map +0 -1
- package/dist/__tests__/v020.test.js +0 -408
- package/dist/__tests__/v020.test.js.map +0 -1
- package/dist/__tests__/vectors.test.d.ts +0 -2
- package/dist/__tests__/vectors.test.d.ts.map +0 -1
- package/dist/__tests__/vectors.test.js +0 -261
- package/dist/__tests__/vectors.test.js.map +0 -1
- package/dist/archive.d.ts +0 -4
- package/dist/archive.d.ts.map +0 -1
- package/dist/archive.js +0 -28
- package/dist/archive.js.map +0 -1
- package/dist/attest.d.ts +0 -3
- package/dist/attest.d.ts.map +0 -1
- package/dist/attest.js +0 -42
- package/dist/attest.js.map +0 -1
- package/dist/canonicalJson.d.ts +0 -2
- package/dist/canonicalJson.d.ts.map +0 -1
- package/dist/canonicalJson.js +0 -38
- package/dist/canonicalJson.js.map +0 -1
- package/dist/cer.d.ts +0 -7
- package/dist/cer.d.ts.map +0 -1
- package/dist/cer.js +0 -61
- package/dist/cer.js.map +0 -1
- package/dist/certify.d.ts +0 -3
- package/dist/certify.d.ts.map +0 -1
- package/dist/certify.js +0 -27
- package/dist/certify.js.map +0 -1
- package/dist/errors.d.ts +0 -10
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -19
- package/dist/errors.js.map +0 -1
- package/dist/hash.d.ts +0 -6
- package/dist/hash.d.ts.map +0 -1
- package/dist/hash.js +0 -32
- package/dist/hash.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -11
- package/dist/index.js.map +0 -1
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js +0 -61
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/providers/openai.js +0 -62
- package/dist/providers/openai.js.map +0 -1
- package/dist/providers/wrap.d.ts.map +0 -1
- package/dist/providers/wrap.js +0 -28
- package/dist/providers/wrap.js.map +0 -1
- package/dist/run.d.ts +0 -14
- package/dist/run.d.ts.map +0 -1
- package/dist/run.js +0 -62
- package/dist/run.js.map +0 -1
- package/dist/snapshot.d.ts +0 -4
- package/dist/snapshot.d.ts.map +0 -1
- package/dist/snapshot.js +0 -113
- package/dist/snapshot.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
CerAttestationError: () => CerAttestationError,
|
|
34
|
+
CerVerificationError: () => CerVerificationError,
|
|
35
|
+
RunBuilder: () => RunBuilder,
|
|
36
|
+
attest: () => attest,
|
|
37
|
+
certifyDecision: () => certifyDecision,
|
|
38
|
+
computeInputHash: () => computeInputHash,
|
|
39
|
+
computeOutputHash: () => computeOutputHash,
|
|
40
|
+
createSnapshot: () => createSnapshot,
|
|
41
|
+
exportCer: () => exportCer,
|
|
42
|
+
hasAttestation: () => hasAttestation,
|
|
43
|
+
hashCanonicalJson: () => hashCanonicalJson,
|
|
44
|
+
hashUtf8: () => hashUtf8,
|
|
45
|
+
importCer: () => importCer,
|
|
46
|
+
sanitizeForAttestation: () => sanitizeForAttestation,
|
|
47
|
+
sealCer: () => sealCer,
|
|
48
|
+
sha256Hex: () => sha256Hex,
|
|
49
|
+
toCanonicalJson: () => toCanonicalJson,
|
|
50
|
+
verify: () => verifyCer,
|
|
51
|
+
verifyCer: () => verifyCer,
|
|
52
|
+
verifySnapshot: () => verifySnapshot,
|
|
53
|
+
wrapProvider: () => wrapProvider
|
|
54
|
+
});
|
|
55
|
+
module.exports = __toCommonJS(src_exports);
|
|
56
|
+
|
|
57
|
+
// src/errors.ts
|
|
58
|
+
var CerVerificationError = class extends Error {
|
|
59
|
+
errors;
|
|
60
|
+
constructor(errors) {
|
|
61
|
+
super(`CER verification failed: ${errors.join("; ")}`);
|
|
62
|
+
this.name = "CerVerificationError";
|
|
63
|
+
this.errors = errors;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var CerAttestationError = class extends Error {
|
|
67
|
+
statusCode;
|
|
68
|
+
responseBody;
|
|
69
|
+
details;
|
|
70
|
+
constructor(message, statusCode, responseBody, details) {
|
|
71
|
+
super(message);
|
|
72
|
+
this.name = "CerAttestationError";
|
|
73
|
+
this.statusCode = statusCode;
|
|
74
|
+
this.responseBody = responseBody;
|
|
75
|
+
this.details = details;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/canonicalJson.ts
|
|
80
|
+
function toCanonicalJson(value) {
|
|
81
|
+
return canonicalize(value);
|
|
82
|
+
}
|
|
83
|
+
function canonicalize(value) {
|
|
84
|
+
if (value === null) {
|
|
85
|
+
return "null";
|
|
86
|
+
}
|
|
87
|
+
if (typeof value === "boolean") {
|
|
88
|
+
return value ? "true" : "false";
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "number") {
|
|
91
|
+
if (!Number.isFinite(value)) {
|
|
92
|
+
throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);
|
|
93
|
+
}
|
|
94
|
+
return JSON.stringify(value);
|
|
95
|
+
}
|
|
96
|
+
if (typeof value === "string") {
|
|
97
|
+
return JSON.stringify(value);
|
|
98
|
+
}
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
const items = value.map((item) => canonicalize(item));
|
|
101
|
+
return "[" + items.join(",") + "]";
|
|
102
|
+
}
|
|
103
|
+
if (typeof value === "object") {
|
|
104
|
+
const obj = value;
|
|
105
|
+
const keys = Object.keys(obj).sort();
|
|
106
|
+
const entries = keys.map((key) => {
|
|
107
|
+
const val = obj[key];
|
|
108
|
+
if (val === void 0) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return JSON.stringify(key) + ":" + canonicalize(val);
|
|
112
|
+
}).filter((e) => e !== null);
|
|
113
|
+
return "{" + entries.join(",") + "}";
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/hash.ts
|
|
119
|
+
var crypto = __toESM(require("crypto"), 1);
|
|
120
|
+
function sha256Hex(data) {
|
|
121
|
+
const hash = crypto.createHash("sha256");
|
|
122
|
+
if (typeof data === "string") {
|
|
123
|
+
hash.update(data, "utf-8");
|
|
124
|
+
} else {
|
|
125
|
+
hash.update(data);
|
|
126
|
+
}
|
|
127
|
+
return hash.digest("hex");
|
|
128
|
+
}
|
|
129
|
+
function hashUtf8(value) {
|
|
130
|
+
return `sha256:${sha256Hex(value)}`;
|
|
131
|
+
}
|
|
132
|
+
function hashCanonicalJson(value) {
|
|
133
|
+
const canonical = toCanonicalJson(value);
|
|
134
|
+
return `sha256:${sha256Hex(canonical)}`;
|
|
135
|
+
}
|
|
136
|
+
function computeInputHash(input) {
|
|
137
|
+
if (typeof input === "string") {
|
|
138
|
+
return hashUtf8(input);
|
|
139
|
+
}
|
|
140
|
+
return hashCanonicalJson(input);
|
|
141
|
+
}
|
|
142
|
+
function computeOutputHash(output) {
|
|
143
|
+
if (typeof output === "string") {
|
|
144
|
+
return hashUtf8(output);
|
|
145
|
+
}
|
|
146
|
+
return hashCanonicalJson(output);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/snapshot.ts
|
|
150
|
+
var PACKAGE_VERSION = "0.4.0";
|
|
151
|
+
function validateParameters(params) {
|
|
152
|
+
const errors = [];
|
|
153
|
+
if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
|
|
154
|
+
errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);
|
|
155
|
+
}
|
|
156
|
+
if (typeof params.maxTokens !== "number" || !Number.isFinite(params.maxTokens)) {
|
|
157
|
+
errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);
|
|
158
|
+
}
|
|
159
|
+
if (params.topP !== null && (typeof params.topP !== "number" || !Number.isFinite(params.topP))) {
|
|
160
|
+
errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);
|
|
161
|
+
}
|
|
162
|
+
if (params.seed !== null && (typeof params.seed !== "number" || !Number.isFinite(params.seed))) {
|
|
163
|
+
errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);
|
|
164
|
+
}
|
|
165
|
+
return errors;
|
|
166
|
+
}
|
|
167
|
+
function createSnapshot(params) {
|
|
168
|
+
const paramErrors = validateParameters(params.parameters);
|
|
169
|
+
if (paramErrors.length > 0) {
|
|
170
|
+
throw new Error(`Invalid parameters: ${paramErrors.join("; ")}`);
|
|
171
|
+
}
|
|
172
|
+
const inputHash = computeInputHash(params.input);
|
|
173
|
+
const outputHash = computeOutputHash(params.output);
|
|
174
|
+
const snapshot = {
|
|
175
|
+
type: "ai.execution.v1",
|
|
176
|
+
protocolVersion: "1.2.0",
|
|
177
|
+
executionSurface: "ai",
|
|
178
|
+
executionId: params.executionId,
|
|
179
|
+
timestamp: params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
180
|
+
provider: params.provider,
|
|
181
|
+
model: params.model,
|
|
182
|
+
modelVersion: params.modelVersion ?? null,
|
|
183
|
+
prompt: params.prompt,
|
|
184
|
+
input: params.input,
|
|
185
|
+
inputHash,
|
|
186
|
+
parameters: {
|
|
187
|
+
temperature: params.parameters.temperature,
|
|
188
|
+
maxTokens: params.parameters.maxTokens,
|
|
189
|
+
topP: params.parameters.topP ?? null,
|
|
190
|
+
seed: params.parameters.seed ?? null
|
|
191
|
+
},
|
|
192
|
+
output: params.output,
|
|
193
|
+
outputHash,
|
|
194
|
+
sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,
|
|
195
|
+
appId: params.appId ?? null
|
|
196
|
+
};
|
|
197
|
+
if (params.runId !== void 0) snapshot.runId = params.runId ?? null;
|
|
198
|
+
if (params.stepId !== void 0) snapshot.stepId = params.stepId ?? null;
|
|
199
|
+
if (params.stepIndex !== void 0) snapshot.stepIndex = params.stepIndex ?? null;
|
|
200
|
+
if (params.workflowId !== void 0) snapshot.workflowId = params.workflowId ?? null;
|
|
201
|
+
if (params.conversationId !== void 0) snapshot.conversationId = params.conversationId ?? null;
|
|
202
|
+
if (params.prevStepHash !== void 0) snapshot.prevStepHash = params.prevStepHash ?? null;
|
|
203
|
+
return snapshot;
|
|
204
|
+
}
|
|
205
|
+
function verifySnapshot(snapshot) {
|
|
206
|
+
const errors = [];
|
|
207
|
+
if (snapshot.type !== "ai.execution.v1") {
|
|
208
|
+
errors.push(`Expected type "ai.execution.v1", got "${snapshot.type}"`);
|
|
209
|
+
}
|
|
210
|
+
if (snapshot.protocolVersion !== "1.2.0") {
|
|
211
|
+
errors.push(`Expected protocolVersion "1.2.0", got "${snapshot.protocolVersion}"`);
|
|
212
|
+
}
|
|
213
|
+
if (snapshot.executionSurface !== "ai") {
|
|
214
|
+
errors.push(`Expected executionSurface "ai", got "${snapshot.executionSurface}"`);
|
|
215
|
+
}
|
|
216
|
+
if (!snapshot.executionId || typeof snapshot.executionId !== "string") {
|
|
217
|
+
errors.push("executionId must be a non-empty string");
|
|
218
|
+
}
|
|
219
|
+
if (!snapshot.timestamp || typeof snapshot.timestamp !== "string") {
|
|
220
|
+
errors.push("timestamp must be a non-empty string");
|
|
221
|
+
}
|
|
222
|
+
if (!snapshot.provider || typeof snapshot.provider !== "string") {
|
|
223
|
+
errors.push("provider must be a non-empty string");
|
|
224
|
+
}
|
|
225
|
+
if (!snapshot.model || typeof snapshot.model !== "string") {
|
|
226
|
+
errors.push("model must be a non-empty string");
|
|
227
|
+
}
|
|
228
|
+
if (!snapshot.prompt || typeof snapshot.prompt !== "string") {
|
|
229
|
+
errors.push("prompt must be a non-empty string");
|
|
230
|
+
}
|
|
231
|
+
if (snapshot.input === void 0 || snapshot.input === null) {
|
|
232
|
+
errors.push("input must be a string or object");
|
|
233
|
+
}
|
|
234
|
+
if (snapshot.output === void 0 || snapshot.output === null) {
|
|
235
|
+
errors.push("output must be a string or object");
|
|
236
|
+
}
|
|
237
|
+
const paramErrors = validateParameters(snapshot.parameters);
|
|
238
|
+
errors.push(...paramErrors);
|
|
239
|
+
if (!snapshot.inputHash || !snapshot.inputHash.startsWith("sha256:")) {
|
|
240
|
+
errors.push(`inputHash must start with "sha256:", got "${snapshot.inputHash}"`);
|
|
241
|
+
}
|
|
242
|
+
if (!snapshot.outputHash || !snapshot.outputHash.startsWith("sha256:")) {
|
|
243
|
+
errors.push(`outputHash must start with "sha256:", got "${snapshot.outputHash}"`);
|
|
244
|
+
}
|
|
245
|
+
const expectedInputHash = computeInputHash(snapshot.input);
|
|
246
|
+
if (snapshot.inputHash !== expectedInputHash) {
|
|
247
|
+
errors.push(`inputHash mismatch: expected ${expectedInputHash}, got ${snapshot.inputHash}`);
|
|
248
|
+
}
|
|
249
|
+
const expectedOutputHash = computeOutputHash(snapshot.output);
|
|
250
|
+
if (snapshot.outputHash !== expectedOutputHash) {
|
|
251
|
+
errors.push(`outputHash mismatch: expected ${expectedOutputHash}, got ${snapshot.outputHash}`);
|
|
252
|
+
}
|
|
253
|
+
return { ok: errors.length === 0, errors };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/cer.ts
|
|
257
|
+
function computeCertificateHash(payload) {
|
|
258
|
+
const canonical = toCanonicalJson(payload);
|
|
259
|
+
return `sha256:${sha256Hex(canonical)}`;
|
|
260
|
+
}
|
|
261
|
+
function sealCer(snapshot, options) {
|
|
262
|
+
const createdAt = options?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
263
|
+
const payload = {
|
|
264
|
+
bundleType: "cer.ai.execution.v1",
|
|
265
|
+
createdAt,
|
|
266
|
+
snapshot,
|
|
267
|
+
version: "0.1"
|
|
268
|
+
};
|
|
269
|
+
const certificateHash = computeCertificateHash(payload);
|
|
270
|
+
const bundle = {
|
|
271
|
+
bundleType: "cer.ai.execution.v1",
|
|
272
|
+
certificateHash,
|
|
273
|
+
createdAt,
|
|
274
|
+
version: "0.1",
|
|
275
|
+
snapshot
|
|
276
|
+
};
|
|
277
|
+
if (options?.meta) {
|
|
278
|
+
bundle.meta = options.meta;
|
|
279
|
+
}
|
|
280
|
+
return bundle;
|
|
281
|
+
}
|
|
282
|
+
function verifyCer(bundle) {
|
|
283
|
+
const errors = [];
|
|
284
|
+
if (bundle.bundleType !== "cer.ai.execution.v1") {
|
|
285
|
+
errors.push(`Expected bundleType "cer.ai.execution.v1", got "${bundle.bundleType}"`);
|
|
286
|
+
}
|
|
287
|
+
if (bundle.version !== "0.1") {
|
|
288
|
+
errors.push(`Expected version "0.1", got "${bundle.version}"`);
|
|
289
|
+
}
|
|
290
|
+
if (!bundle.createdAt || typeof bundle.createdAt !== "string") {
|
|
291
|
+
errors.push("createdAt must be a non-empty string");
|
|
292
|
+
}
|
|
293
|
+
if (!bundle.certificateHash || !bundle.certificateHash.startsWith("sha256:")) {
|
|
294
|
+
errors.push(`certificateHash must start with "sha256:", got "${bundle.certificateHash}"`);
|
|
295
|
+
}
|
|
296
|
+
if (!bundle.snapshot) {
|
|
297
|
+
errors.push("snapshot is required");
|
|
298
|
+
return { ok: false, errors };
|
|
299
|
+
}
|
|
300
|
+
const snapshotResult = verifySnapshot(bundle.snapshot);
|
|
301
|
+
errors.push(...snapshotResult.errors);
|
|
302
|
+
const payload = {
|
|
303
|
+
bundleType: "cer.ai.execution.v1",
|
|
304
|
+
createdAt: bundle.createdAt,
|
|
305
|
+
snapshot: bundle.snapshot,
|
|
306
|
+
version: "0.1"
|
|
307
|
+
};
|
|
308
|
+
const expectedHash = computeCertificateHash(payload);
|
|
309
|
+
if (bundle.certificateHash !== expectedHash) {
|
|
310
|
+
errors.push(`certificateHash mismatch: expected ${expectedHash}, got ${bundle.certificateHash}`);
|
|
311
|
+
}
|
|
312
|
+
return { ok: errors.length === 0, errors };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// src/certify.ts
|
|
316
|
+
var crypto2 = __toESM(require("crypto"), 1);
|
|
317
|
+
function certifyDecision(params) {
|
|
318
|
+
const executionId = params.executionId ?? crypto2.randomUUID();
|
|
319
|
+
const snapshot = createSnapshot({
|
|
320
|
+
executionId,
|
|
321
|
+
timestamp: params.timestamp,
|
|
322
|
+
provider: params.provider,
|
|
323
|
+
model: params.model,
|
|
324
|
+
modelVersion: params.modelVersion,
|
|
325
|
+
prompt: params.prompt,
|
|
326
|
+
input: params.input,
|
|
327
|
+
parameters: params.parameters,
|
|
328
|
+
output: params.output,
|
|
329
|
+
sdkVersion: params.sdkVersion,
|
|
330
|
+
appId: params.appId,
|
|
331
|
+
runId: params.runId,
|
|
332
|
+
stepId: params.stepId,
|
|
333
|
+
stepIndex: params.stepIndex,
|
|
334
|
+
workflowId: params.workflowId,
|
|
335
|
+
conversationId: params.conversationId,
|
|
336
|
+
prevStepHash: params.prevStepHash
|
|
337
|
+
});
|
|
338
|
+
return sealCer(snapshot, { meta: params.meta });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// src/run.ts
|
|
342
|
+
var crypto3 = __toESM(require("crypto"), 1);
|
|
343
|
+
var RunBuilder = class {
|
|
344
|
+
runId;
|
|
345
|
+
workflowId;
|
|
346
|
+
conversationId;
|
|
347
|
+
appId;
|
|
348
|
+
stepIndex = 0;
|
|
349
|
+
prevStepHash = null;
|
|
350
|
+
steps = [];
|
|
351
|
+
constructor(options) {
|
|
352
|
+
this.runId = options?.runId ?? crypto3.randomUUID();
|
|
353
|
+
this.workflowId = options?.workflowId ?? null;
|
|
354
|
+
this.conversationId = options?.conversationId ?? null;
|
|
355
|
+
this.appId = options?.appId ?? null;
|
|
356
|
+
}
|
|
357
|
+
step(params) {
|
|
358
|
+
const stepId = params.stepId ?? crypto3.randomUUID();
|
|
359
|
+
const executionId = `${this.runId}-step-${this.stepIndex}`;
|
|
360
|
+
const snapshot = createSnapshot({
|
|
361
|
+
executionId,
|
|
362
|
+
timestamp: params.timestamp,
|
|
363
|
+
provider: params.provider,
|
|
364
|
+
model: params.model,
|
|
365
|
+
modelVersion: params.modelVersion,
|
|
366
|
+
prompt: params.prompt,
|
|
367
|
+
input: params.input,
|
|
368
|
+
parameters: params.parameters,
|
|
369
|
+
output: params.output,
|
|
370
|
+
appId: this.appId,
|
|
371
|
+
runId: this.runId,
|
|
372
|
+
stepId,
|
|
373
|
+
stepIndex: this.stepIndex,
|
|
374
|
+
workflowId: this.workflowId,
|
|
375
|
+
conversationId: this.conversationId,
|
|
376
|
+
prevStepHash: this.prevStepHash
|
|
377
|
+
});
|
|
378
|
+
const bundle = sealCer(snapshot, { meta: params.meta });
|
|
379
|
+
this.steps.push({
|
|
380
|
+
stepIndex: this.stepIndex,
|
|
381
|
+
stepId,
|
|
382
|
+
executionId,
|
|
383
|
+
certificateHash: bundle.certificateHash,
|
|
384
|
+
prevStepHash: this.prevStepHash
|
|
385
|
+
});
|
|
386
|
+
this.prevStepHash = bundle.certificateHash;
|
|
387
|
+
this.stepIndex++;
|
|
388
|
+
return bundle;
|
|
389
|
+
}
|
|
390
|
+
finalize() {
|
|
391
|
+
return {
|
|
392
|
+
runId: this.runId,
|
|
393
|
+
workflowId: this.workflowId,
|
|
394
|
+
conversationId: this.conversationId,
|
|
395
|
+
stepCount: this.steps.length,
|
|
396
|
+
steps: [...this.steps],
|
|
397
|
+
finalStepHash: this.prevStepHash
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// src/sanitize.ts
|
|
403
|
+
function deepRemoveUndefined(value) {
|
|
404
|
+
if (value === null || value === void 0) return value;
|
|
405
|
+
if (typeof value === "bigint") {
|
|
406
|
+
throw new Error("BigInt values are not JSON-safe and cannot be sanitized");
|
|
407
|
+
}
|
|
408
|
+
if (typeof value === "function") {
|
|
409
|
+
throw new Error("Function values are not JSON-safe and cannot be sanitized");
|
|
410
|
+
}
|
|
411
|
+
if (typeof value === "symbol") {
|
|
412
|
+
throw new Error("Symbol values are not JSON-safe and cannot be sanitized");
|
|
413
|
+
}
|
|
414
|
+
if (Array.isArray(value)) {
|
|
415
|
+
return value.map(deepRemoveUndefined);
|
|
416
|
+
}
|
|
417
|
+
if (typeof value === "object") {
|
|
418
|
+
const result = {};
|
|
419
|
+
for (const [key, val] of Object.entries(value)) {
|
|
420
|
+
if (val === void 0) continue;
|
|
421
|
+
result[key] = deepRemoveUndefined(val);
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
return value;
|
|
426
|
+
}
|
|
427
|
+
function sanitizeForAttestation(bundle) {
|
|
428
|
+
return deepRemoveUndefined(bundle);
|
|
429
|
+
}
|
|
430
|
+
function hasAttestation(bundle) {
|
|
431
|
+
if (typeof bundle !== "object" || bundle === null) return false;
|
|
432
|
+
const b = bundle;
|
|
433
|
+
if (typeof b.attestationId === "string" && b.attestationId.length > 0) return true;
|
|
434
|
+
if (typeof b.nodeRuntimeHash === "string" && b.nodeRuntimeHash.length > 0) return true;
|
|
435
|
+
if (typeof b.attestation === "object" && b.attestation !== null) {
|
|
436
|
+
const att = b.attestation;
|
|
437
|
+
if (typeof att.attestationId === "string" && att.attestationId.length > 0) return true;
|
|
438
|
+
if (typeof att.nodeRuntimeHash === "string" && att.nodeRuntimeHash.length > 0) return true;
|
|
439
|
+
}
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// src/attest.ts
|
|
444
|
+
var SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
445
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
446
|
+
function validateHashFormat(value, fieldName) {
|
|
447
|
+
if (typeof value !== "string") return null;
|
|
448
|
+
if (!SHA256_PATTERN.test(value)) {
|
|
449
|
+
return `${fieldName} is not in sha256:<64hex> format: "${value}"`;
|
|
450
|
+
}
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
async function attest(bundle, options) {
|
|
454
|
+
const url = `${options.nodeUrl.replace(/\/+$/, "")}/api/attest`;
|
|
455
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
456
|
+
const sanitized = sanitizeForAttestation(bundle);
|
|
457
|
+
const controller = new AbortController();
|
|
458
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
459
|
+
let response;
|
|
460
|
+
try {
|
|
461
|
+
response = await fetch(url, {
|
|
462
|
+
method: "POST",
|
|
463
|
+
headers: {
|
|
464
|
+
"Content-Type": "application/json",
|
|
465
|
+
"Authorization": `Bearer ${options.apiKey}`
|
|
466
|
+
},
|
|
467
|
+
body: JSON.stringify(sanitized),
|
|
468
|
+
signal: controller.signal
|
|
469
|
+
});
|
|
470
|
+
} catch (err) {
|
|
471
|
+
clearTimeout(timer);
|
|
472
|
+
const error = err;
|
|
473
|
+
if (error.name === "AbortError") {
|
|
474
|
+
throw new CerAttestationError(
|
|
475
|
+
`Attestation request timed out after ${timeoutMs}ms`
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
throw new CerAttestationError(
|
|
479
|
+
`Network error contacting attestation node: ${error.message}`
|
|
480
|
+
);
|
|
481
|
+
} finally {
|
|
482
|
+
clearTimeout(timer);
|
|
483
|
+
}
|
|
484
|
+
let body;
|
|
485
|
+
try {
|
|
486
|
+
body = await response.json();
|
|
487
|
+
} catch {
|
|
488
|
+
const text = await response.text().catch(() => "");
|
|
489
|
+
throw new CerAttestationError(
|
|
490
|
+
`Attestation node returned non-JSON response (${response.status}): ${text}`,
|
|
491
|
+
response.status
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
if (!response.ok) {
|
|
495
|
+
const result2 = body;
|
|
496
|
+
const msg = typeof result2.error === "string" ? result2.error : `HTTP ${response.status}`;
|
|
497
|
+
const details = Array.isArray(result2.details) ? result2.details : void 0;
|
|
498
|
+
throw new CerAttestationError(
|
|
499
|
+
`Attestation failed: ${msg}`,
|
|
500
|
+
response.status,
|
|
501
|
+
body,
|
|
502
|
+
details
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
const result = body;
|
|
506
|
+
const errors = [];
|
|
507
|
+
if (typeof result.certificateHash === "string" && result.certificateHash !== bundle.certificateHash) {
|
|
508
|
+
errors.push(
|
|
509
|
+
`Node returned certificateHash "${result.certificateHash}" but bundle has "${bundle.certificateHash}"`
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
const certHashErr = validateHashFormat(result.certificateHash, "response.certificateHash");
|
|
513
|
+
if (certHashErr) errors.push(certHashErr);
|
|
514
|
+
const runtimeHashErr = validateHashFormat(result.nodeRuntimeHash, "response.nodeRuntimeHash");
|
|
515
|
+
if (runtimeHashErr) errors.push(runtimeHashErr);
|
|
516
|
+
if (errors.length > 0) {
|
|
517
|
+
throw new CerAttestationError(
|
|
518
|
+
`Attestation response validation failed: ${errors.join("; ")}`,
|
|
519
|
+
response.status,
|
|
520
|
+
body,
|
|
521
|
+
errors
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
ok: true,
|
|
526
|
+
attestationId: typeof result.attestationId === "string" ? result.attestationId : void 0,
|
|
527
|
+
nodeRuntimeHash: typeof result.nodeRuntimeHash === "string" ? result.nodeRuntimeHash : void 0,
|
|
528
|
+
certificateHash: typeof result.certificateHash === "string" ? result.certificateHash : void 0,
|
|
529
|
+
protocolVersion: typeof result.protocolVersion === "string" ? result.protocolVersion : void 0,
|
|
530
|
+
raw: body
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// src/archive.ts
|
|
535
|
+
function exportCer(bundle) {
|
|
536
|
+
return toCanonicalJson(bundle);
|
|
537
|
+
}
|
|
538
|
+
function importCer(json) {
|
|
539
|
+
let parsed;
|
|
540
|
+
try {
|
|
541
|
+
parsed = JSON.parse(json);
|
|
542
|
+
} catch (err) {
|
|
543
|
+
throw new CerVerificationError([`Invalid JSON: ${err.message}`]);
|
|
544
|
+
}
|
|
545
|
+
const bundle = parsed;
|
|
546
|
+
if (!bundle || typeof bundle !== "object") {
|
|
547
|
+
throw new CerVerificationError(["Parsed value is not an object"]);
|
|
548
|
+
}
|
|
549
|
+
if (bundle.bundleType !== "cer.ai.execution.v1") {
|
|
550
|
+
throw new CerVerificationError([`Expected bundleType "cer.ai.execution.v1", got "${bundle.bundleType}"`]);
|
|
551
|
+
}
|
|
552
|
+
const result = verifyCer(bundle);
|
|
553
|
+
if (!result.ok) {
|
|
554
|
+
throw new CerVerificationError(result.errors);
|
|
555
|
+
}
|
|
556
|
+
return bundle;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/providers/wrap.ts
|
|
560
|
+
var crypto4 = __toESM(require("crypto"), 1);
|
|
561
|
+
function wrapProvider(config) {
|
|
562
|
+
return {
|
|
563
|
+
async execute(params) {
|
|
564
|
+
const raw = await config.callFn(params.providerInput);
|
|
565
|
+
const output = config.extractOutput(raw);
|
|
566
|
+
const modelVersion = config.extractModelVersion ? config.extractModelVersion(raw) : params.modelVersion ?? null;
|
|
567
|
+
const snapshot = createSnapshot({
|
|
568
|
+
executionId: params.executionId ?? crypto4.randomUUID(),
|
|
569
|
+
provider: config.provider,
|
|
570
|
+
model: params.model,
|
|
571
|
+
modelVersion,
|
|
572
|
+
prompt: params.prompt,
|
|
573
|
+
input: params.input,
|
|
574
|
+
parameters: params.parameters,
|
|
575
|
+
output,
|
|
576
|
+
appId: params.appId
|
|
577
|
+
});
|
|
578
|
+
const bundle = sealCer(snapshot, { meta: params.meta });
|
|
579
|
+
return { output, snapshot, bundle };
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
584
|
+
0 && (module.exports = {
|
|
585
|
+
CerAttestationError,
|
|
586
|
+
CerVerificationError,
|
|
587
|
+
RunBuilder,
|
|
588
|
+
attest,
|
|
589
|
+
certifyDecision,
|
|
590
|
+
computeInputHash,
|
|
591
|
+
computeOutputHash,
|
|
592
|
+
createSnapshot,
|
|
593
|
+
exportCer,
|
|
594
|
+
hasAttestation,
|
|
595
|
+
hashCanonicalJson,
|
|
596
|
+
hashUtf8,
|
|
597
|
+
importCer,
|
|
598
|
+
sanitizeForAttestation,
|
|
599
|
+
sealCer,
|
|
600
|
+
sha256Hex,
|
|
601
|
+
toCanonicalJson,
|
|
602
|
+
verify,
|
|
603
|
+
verifyCer,
|
|
604
|
+
verifySnapshot,
|
|
605
|
+
wrapProvider
|
|
606
|
+
});
|
|
607
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/canonicalJson.ts","../src/hash.ts","../src/snapshot.ts","../src/cer.ts","../src/certify.ts","../src/run.ts","../src/sanitize.ts","../src/attest.ts","../src/archive.ts","../src/providers/wrap.ts"],"sourcesContent":["export type {\n AiExecutionSnapshotV1,\n AiExecutionParameters,\n CerAiExecutionBundle,\n CerMeta,\n VerificationResult,\n CreateSnapshotParams,\n AttestationResult,\n AttestOptions,\n CertifyDecisionParams,\n RunBuilderOptions,\n StepParams,\n RunSummary,\n ProviderConfig,\n WrappedExecutionParams,\n WrappedExecutionResult,\n} from './types.js';\n\nexport { CerVerificationError, CerAttestationError } from './errors.js';\nexport { toCanonicalJson } from './canonicalJson.js';\nexport { sha256Hex, hashUtf8, hashCanonicalJson, computeInputHash, computeOutputHash } from './hash.js';\nexport { createSnapshot, verifySnapshot } from './snapshot.js';\nexport { sealCer, verifyCer, verifyCer as verify } from './cer.js';\nexport { certifyDecision } from './certify.js';\nexport { RunBuilder } from './run.js';\nexport { attest } from './attest.js';\nexport { exportCer, importCer } from './archive.js';\nexport { wrapProvider } from './providers/wrap.js';\nexport { sanitizeForAttestation, hasAttestation } from './sanitize.js';\n","export class CerVerificationError extends Error {\n public readonly errors: string[];\n\n constructor(errors: string[]) {\n super(`CER verification failed: ${errors.join('; ')}`);\n this.name = 'CerVerificationError';\n this.errors = errors;\n }\n}\n\nexport class CerAttestationError extends Error {\n public readonly statusCode?: number;\n public readonly responseBody?: unknown;\n public readonly details?: string[];\n\n constructor(message: string, statusCode?: number, responseBody?: unknown, details?: string[]) {\n super(message);\n this.name = 'CerAttestationError';\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n this.details = details;\n }\n}\n","export function toCanonicalJson(value: unknown): string {\n return canonicalize(value);\n}\n\nfunction canonicalize(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`Non-finite number not allowed in canonical JSON: ${value}`);\n }\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n const items = value.map(item => canonicalize(item));\n return '[' + items.join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const entries = keys.map(key => {\n const val = obj[key];\n if (val === undefined) {\n return null;\n }\n return JSON.stringify(key) + ':' + canonicalize(val);\n }).filter(e => e !== null);\n return '{' + entries.join(',') + '}';\n }\n\n throw new Error(`Unsupported type for canonical JSON: ${typeof value}`);\n}\n","import * as crypto from 'crypto';\nimport { toCanonicalJson } from './canonicalJson.js';\n\nexport function sha256Hex(data: string | Uint8Array): string {\n const hash = crypto.createHash('sha256');\n if (typeof data === 'string') {\n hash.update(data, 'utf-8');\n } else {\n hash.update(data);\n }\n return hash.digest('hex');\n}\n\nexport function hashUtf8(value: string): string {\n return `sha256:${sha256Hex(value)}`;\n}\n\nexport function hashCanonicalJson(value: unknown): string {\n const canonical = toCanonicalJson(value);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function computeInputHash(input: string | Record<string, unknown>): string {\n if (typeof input === 'string') {\n return hashUtf8(input);\n }\n return hashCanonicalJson(input);\n}\n\nexport function computeOutputHash(output: string | Record<string, unknown>): string {\n if (typeof output === 'string') {\n return hashUtf8(output);\n }\n return hashCanonicalJson(output);\n}\n","import type { AiExecutionSnapshotV1, CreateSnapshotParams, VerificationResult, AiExecutionParameters } from './types.js';\nimport { computeInputHash, computeOutputHash } from './hash.js';\n\nconst PACKAGE_VERSION = '0.4.0';\n\nfunction validateParameters(params: AiExecutionParameters): string[] {\n const errors: string[] = [];\n\n if (typeof params.temperature !== 'number' || !Number.isFinite(params.temperature)) {\n errors.push(`parameters.temperature must be a finite number, got: ${params.temperature}`);\n }\n\n if (typeof params.maxTokens !== 'number' || !Number.isFinite(params.maxTokens)) {\n errors.push(`parameters.maxTokens must be a finite number, got: ${params.maxTokens}`);\n }\n\n if (params.topP !== null && (typeof params.topP !== 'number' || !Number.isFinite(params.topP))) {\n errors.push(`parameters.topP must be a finite number or null, got: ${params.topP}`);\n }\n\n if (params.seed !== null && (typeof params.seed !== 'number' || !Number.isFinite(params.seed))) {\n errors.push(`parameters.seed must be a finite number or null, got: ${params.seed}`);\n }\n\n return errors;\n}\n\nexport function createSnapshot(params: CreateSnapshotParams): AiExecutionSnapshotV1 {\n const paramErrors = validateParameters(params.parameters);\n if (paramErrors.length > 0) {\n throw new Error(`Invalid parameters: ${paramErrors.join('; ')}`);\n }\n\n const inputHash = computeInputHash(params.input);\n const outputHash = computeOutputHash(params.output);\n\n const snapshot: AiExecutionSnapshotV1 = {\n type: 'ai.execution.v1',\n protocolVersion: '1.2.0',\n executionSurface: 'ai',\n executionId: params.executionId,\n timestamp: params.timestamp ?? new Date().toISOString(),\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion ?? null,\n prompt: params.prompt,\n input: params.input,\n inputHash,\n parameters: {\n temperature: params.parameters.temperature,\n maxTokens: params.parameters.maxTokens,\n topP: params.parameters.topP ?? null,\n seed: params.parameters.seed ?? null,\n },\n output: params.output,\n outputHash,\n sdkVersion: params.sdkVersion ?? PACKAGE_VERSION,\n appId: params.appId ?? null,\n };\n\n if (params.runId !== undefined) snapshot.runId = params.runId ?? null;\n if (params.stepId !== undefined) snapshot.stepId = params.stepId ?? null;\n if (params.stepIndex !== undefined) snapshot.stepIndex = params.stepIndex ?? null;\n if (params.workflowId !== undefined) snapshot.workflowId = params.workflowId ?? null;\n if (params.conversationId !== undefined) snapshot.conversationId = params.conversationId ?? null;\n if (params.prevStepHash !== undefined) snapshot.prevStepHash = params.prevStepHash ?? null;\n\n return snapshot;\n}\n\nexport function verifySnapshot(snapshot: AiExecutionSnapshotV1): VerificationResult {\n const errors: string[] = [];\n\n if (snapshot.type !== 'ai.execution.v1') {\n errors.push(`Expected type \"ai.execution.v1\", got \"${snapshot.type}\"`);\n }\n\n if (snapshot.protocolVersion !== '1.2.0') {\n errors.push(`Expected protocolVersion \"1.2.0\", got \"${snapshot.protocolVersion}\"`);\n }\n\n if (snapshot.executionSurface !== 'ai') {\n errors.push(`Expected executionSurface \"ai\", got \"${snapshot.executionSurface}\"`);\n }\n\n if (!snapshot.executionId || typeof snapshot.executionId !== 'string') {\n errors.push('executionId must be a non-empty string');\n }\n\n if (!snapshot.timestamp || typeof snapshot.timestamp !== 'string') {\n errors.push('timestamp must be a non-empty string');\n }\n\n if (!snapshot.provider || typeof snapshot.provider !== 'string') {\n errors.push('provider must be a non-empty string');\n }\n\n if (!snapshot.model || typeof snapshot.model !== 'string') {\n errors.push('model must be a non-empty string');\n }\n\n if (!snapshot.prompt || typeof snapshot.prompt !== 'string') {\n errors.push('prompt must be a non-empty string');\n }\n\n if (snapshot.input === undefined || snapshot.input === null) {\n errors.push('input must be a string or object');\n }\n\n if (snapshot.output === undefined || snapshot.output === null) {\n errors.push('output must be a string or object');\n }\n\n const paramErrors = validateParameters(snapshot.parameters);\n errors.push(...paramErrors);\n\n if (!snapshot.inputHash || !snapshot.inputHash.startsWith('sha256:')) {\n errors.push(`inputHash must start with \"sha256:\", got \"${snapshot.inputHash}\"`);\n }\n\n if (!snapshot.outputHash || !snapshot.outputHash.startsWith('sha256:')) {\n errors.push(`outputHash must start with \"sha256:\", got \"${snapshot.outputHash}\"`);\n }\n\n const expectedInputHash = computeInputHash(snapshot.input);\n if (snapshot.inputHash !== expectedInputHash) {\n errors.push(`inputHash mismatch: expected ${expectedInputHash}, got ${snapshot.inputHash}`);\n }\n\n const expectedOutputHash = computeOutputHash(snapshot.output);\n if (snapshot.outputHash !== expectedOutputHash) {\n errors.push(`outputHash mismatch: expected ${expectedOutputHash}, got ${snapshot.outputHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import type { AiExecutionSnapshotV1, CerAiExecutionBundle, CerMeta, VerificationResult } from './types.js';\nimport { toCanonicalJson } from './canonicalJson.js';\nimport { sha256Hex } from './hash.js';\nimport { verifySnapshot } from './snapshot.js';\n\ninterface CertificatePayload {\n bundleType: 'cer.ai.execution.v1';\n createdAt: string;\n snapshot: AiExecutionSnapshotV1;\n version: '0.1';\n}\n\nfunction computeCertificateHash(payload: CertificatePayload): string {\n const canonical = toCanonicalJson(payload);\n return `sha256:${sha256Hex(canonical)}`;\n}\n\nexport function sealCer(\n snapshot: AiExecutionSnapshotV1,\n options?: { createdAt?: string; meta?: CerMeta }\n): CerAiExecutionBundle {\n const createdAt = options?.createdAt ?? new Date().toISOString();\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt,\n snapshot,\n version: '0.1',\n };\n\n const certificateHash = computeCertificateHash(payload);\n\n const bundle: CerAiExecutionBundle = {\n bundleType: 'cer.ai.execution.v1',\n certificateHash,\n createdAt,\n version: '0.1',\n snapshot,\n };\n\n if (options?.meta) {\n bundle.meta = options.meta;\n }\n\n return bundle;\n}\n\nexport function verifyCer(bundle: CerAiExecutionBundle): VerificationResult {\n const errors: string[] = [];\n\n if (bundle.bundleType !== 'cer.ai.execution.v1') {\n errors.push(`Expected bundleType \"cer.ai.execution.v1\", got \"${bundle.bundleType}\"`);\n }\n\n if (bundle.version !== '0.1') {\n errors.push(`Expected version \"0.1\", got \"${bundle.version}\"`);\n }\n\n if (!bundle.createdAt || typeof bundle.createdAt !== 'string') {\n errors.push('createdAt must be a non-empty string');\n }\n\n if (!bundle.certificateHash || !bundle.certificateHash.startsWith('sha256:')) {\n errors.push(`certificateHash must start with \"sha256:\", got \"${bundle.certificateHash}\"`);\n }\n\n if (!bundle.snapshot) {\n errors.push('snapshot is required');\n return { ok: false, errors };\n }\n\n const snapshotResult = verifySnapshot(bundle.snapshot);\n errors.push(...snapshotResult.errors);\n\n const payload: CertificatePayload = {\n bundleType: 'cer.ai.execution.v1',\n createdAt: bundle.createdAt,\n snapshot: bundle.snapshot,\n version: '0.1',\n };\n\n const expectedHash = computeCertificateHash(payload);\n if (bundle.certificateHash !== expectedHash) {\n errors.push(`certificateHash mismatch: expected ${expectedHash}, got ${bundle.certificateHash}`);\n }\n\n return { ok: errors.length === 0, errors };\n}\n","import * as crypto from 'crypto';\nimport type { CerAiExecutionBundle, CertifyDecisionParams } from './types.js';\nimport { createSnapshot } from './snapshot.js';\nimport { sealCer } from './cer.js';\n\nexport function certifyDecision(params: CertifyDecisionParams): CerAiExecutionBundle {\n const executionId = params.executionId ?? crypto.randomUUID();\n\n const snapshot = createSnapshot({\n executionId,\n timestamp: params.timestamp,\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion,\n prompt: params.prompt,\n input: params.input,\n parameters: params.parameters,\n output: params.output,\n sdkVersion: params.sdkVersion,\n appId: params.appId,\n runId: params.runId,\n stepId: params.stepId,\n stepIndex: params.stepIndex,\n workflowId: params.workflowId,\n conversationId: params.conversationId,\n prevStepHash: params.prevStepHash,\n });\n\n return sealCer(snapshot, { meta: params.meta });\n}\n","import * as crypto from 'crypto';\nimport type {\n CerAiExecutionBundle,\n RunBuilderOptions,\n StepParams,\n RunSummary,\n} from './types.js';\nimport { createSnapshot } from './snapshot.js';\nimport { sealCer } from './cer.js';\n\nexport class RunBuilder {\n private readonly runId: string;\n private readonly workflowId: string | null;\n private readonly conversationId: string | null;\n private readonly appId: string | null;\n private stepIndex: number = 0;\n private prevStepHash: string | null = null;\n private steps: RunSummary['steps'] = [];\n\n constructor(options?: RunBuilderOptions) {\n this.runId = options?.runId ?? crypto.randomUUID();\n this.workflowId = options?.workflowId ?? null;\n this.conversationId = options?.conversationId ?? null;\n this.appId = options?.appId ?? null;\n }\n\n step(params: StepParams): CerAiExecutionBundle {\n const stepId = params.stepId ?? crypto.randomUUID();\n const executionId = `${this.runId}-step-${this.stepIndex}`;\n\n const snapshot = createSnapshot({\n executionId,\n timestamp: params.timestamp,\n provider: params.provider,\n model: params.model,\n modelVersion: params.modelVersion,\n prompt: params.prompt,\n input: params.input,\n parameters: params.parameters,\n output: params.output,\n appId: this.appId,\n runId: this.runId,\n stepId,\n stepIndex: this.stepIndex,\n workflowId: this.workflowId,\n conversationId: this.conversationId,\n prevStepHash: this.prevStepHash,\n });\n\n const bundle = sealCer(snapshot, { meta: params.meta });\n\n this.steps.push({\n stepIndex: this.stepIndex,\n stepId,\n executionId,\n certificateHash: bundle.certificateHash,\n prevStepHash: this.prevStepHash,\n });\n\n this.prevStepHash = bundle.certificateHash;\n this.stepIndex++;\n\n return bundle;\n }\n\n finalize(): RunSummary {\n return {\n runId: this.runId,\n workflowId: this.workflowId,\n conversationId: this.conversationId,\n stepCount: this.steps.length,\n steps: [...this.steps],\n finalStepHash: this.prevStepHash,\n };\n }\n}\n","import type { CerAiExecutionBundle } from './types.js';\n\nfunction deepRemoveUndefined(value: unknown): unknown {\n if (value === null || value === undefined) return value;\n\n if (typeof value === 'bigint') {\n throw new Error('BigInt values are not JSON-safe and cannot be sanitized');\n }\n if (typeof value === 'function') {\n throw new Error('Function values are not JSON-safe and cannot be sanitized');\n }\n if (typeof value === 'symbol') {\n throw new Error('Symbol values are not JSON-safe and cannot be sanitized');\n }\n\n if (Array.isArray(value)) {\n return value.map(deepRemoveUndefined);\n }\n\n if (typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n if (val === undefined) continue;\n result[key] = deepRemoveUndefined(val);\n }\n return result;\n }\n\n return value;\n}\n\nexport function sanitizeForAttestation(bundle: CerAiExecutionBundle): CerAiExecutionBundle {\n return deepRemoveUndefined(bundle) as CerAiExecutionBundle;\n}\n\nexport function hasAttestation(bundle: unknown): boolean {\n if (typeof bundle !== 'object' || bundle === null) return false;\n const b = bundle as Record<string, unknown>;\n\n if (typeof b.attestationId === 'string' && b.attestationId.length > 0) return true;\n if (typeof b.nodeRuntimeHash === 'string' && b.nodeRuntimeHash.length > 0) return true;\n\n if (typeof b.attestation === 'object' && b.attestation !== null) {\n const att = b.attestation as Record<string, unknown>;\n if (typeof att.attestationId === 'string' && att.attestationId.length > 0) return true;\n if (typeof att.nodeRuntimeHash === 'string' && att.nodeRuntimeHash.length > 0) return true;\n }\n\n return false;\n}\n","import type { CerAiExecutionBundle, AttestationResult, AttestOptions } from './types.js';\nimport { CerAttestationError } from './errors.js';\nimport { sanitizeForAttestation } from './sanitize.js';\n\nconst SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/;\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction validateHashFormat(value: unknown, fieldName: string): string | null {\n if (typeof value !== 'string') return null;\n if (!SHA256_PATTERN.test(value)) {\n return `${fieldName} is not in sha256:<64hex> format: \"${value}\"`;\n }\n return null;\n}\n\nexport async function attest(\n bundle: CerAiExecutionBundle,\n options: AttestOptions,\n): Promise<AttestationResult> {\n const url = `${options.nodeUrl.replace(/\\/+$/, '')}/api/attest`;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const sanitized = sanitizeForAttestation(bundle);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n body: JSON.stringify(sanitized),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n const error = err as Error;\n if (error.name === 'AbortError') {\n throw new CerAttestationError(\n `Attestation request timed out after ${timeoutMs}ms`,\n );\n }\n throw new CerAttestationError(\n `Network error contacting attestation node: ${error.message}`,\n );\n } finally {\n clearTimeout(timer);\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n const text = await response.text().catch(() => '');\n throw new CerAttestationError(\n `Attestation node returned non-JSON response (${response.status}): ${text}`,\n response.status,\n );\n }\n\n if (!response.ok) {\n const result = body as Record<string, unknown>;\n const msg = typeof result.error === 'string'\n ? result.error\n : `HTTP ${response.status}`;\n const details = Array.isArray(result.details) ? result.details as string[] : undefined;\n throw new CerAttestationError(\n `Attestation failed: ${msg}`,\n response.status,\n body,\n details,\n );\n }\n\n const result = body as Record<string, unknown>;\n const errors: string[] = [];\n\n if (typeof result.certificateHash === 'string' && result.certificateHash !== bundle.certificateHash) {\n errors.push(\n `Node returned certificateHash \"${result.certificateHash}\" but bundle has \"${bundle.certificateHash}\"`,\n );\n }\n\n const certHashErr = validateHashFormat(result.certificateHash, 'response.certificateHash');\n if (certHashErr) errors.push(certHashErr);\n\n const runtimeHashErr = validateHashFormat(result.nodeRuntimeHash, 'response.nodeRuntimeHash');\n if (runtimeHashErr) errors.push(runtimeHashErr);\n\n if (errors.length > 0) {\n throw new CerAttestationError(\n `Attestation response validation failed: ${errors.join('; ')}`,\n response.status,\n body,\n errors,\n );\n }\n\n return {\n ok: true,\n attestationId: typeof result.attestationId === 'string' ? result.attestationId : undefined,\n nodeRuntimeHash: typeof result.nodeRuntimeHash === 'string' ? result.nodeRuntimeHash : undefined,\n certificateHash: typeof result.certificateHash === 'string' ? result.certificateHash : undefined,\n protocolVersion: typeof result.protocolVersion === 'string' ? result.protocolVersion : undefined,\n raw: body,\n };\n}\n","import type { CerAiExecutionBundle } from './types.js';\nimport { toCanonicalJson } from './canonicalJson.js';\nimport { verifyCer } from './cer.js';\nimport { CerVerificationError } from './errors.js';\n\nexport function exportCer(bundle: CerAiExecutionBundle): string {\n return toCanonicalJson(bundle);\n}\n\nexport function importCer(json: string): CerAiExecutionBundle {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (err) {\n throw new CerVerificationError([`Invalid JSON: ${(err as Error).message}`]);\n }\n\n const bundle = parsed as CerAiExecutionBundle;\n\n if (!bundle || typeof bundle !== 'object') {\n throw new CerVerificationError(['Parsed value is not an object']);\n }\n\n if (bundle.bundleType !== 'cer.ai.execution.v1') {\n throw new CerVerificationError([`Expected bundleType \"cer.ai.execution.v1\", got \"${bundle.bundleType}\"`]);\n }\n\n const result = verifyCer(bundle);\n if (!result.ok) {\n throw new CerVerificationError(result.errors);\n }\n\n return bundle;\n}\n","import * as crypto from 'crypto';\nimport type {\n ProviderConfig,\n WrappedExecutionParams,\n WrappedExecutionResult,\n} from '../types.js';\nimport { createSnapshot } from '../snapshot.js';\nimport { sealCer } from '../cer.js';\n\nexport function wrapProvider<TInput = unknown, TOutput = unknown>(\n config: ProviderConfig<TInput, TOutput>,\n) {\n return {\n async execute(params: WrappedExecutionParams & { providerInput: TInput }): Promise<WrappedExecutionResult> {\n const raw = await config.callFn(params.providerInput);\n const output = config.extractOutput(raw);\n const modelVersion = config.extractModelVersion\n ? config.extractModelVersion(raw)\n : (params.modelVersion ?? null);\n\n const snapshot = createSnapshot({\n executionId: params.executionId ?? crypto.randomUUID(),\n provider: config.provider,\n model: params.model,\n modelVersion,\n prompt: params.prompt,\n input: params.input,\n parameters: params.parameters,\n output,\n appId: params.appId,\n });\n\n const bundle = sealCer(snapshot, { meta: params.meta });\n\n return { output, snapshot, bundle };\n },\n };\n}\n"],"mappings":"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","names":["crypto","crypto","result","crypto"]}
|