@nexart/ai-execution 0.11.0 → 0.12.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 +90 -4
- package/dist/index.cjs +73 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -1
- package/dist/index.d.ts +113 -1
- package/dist/index.mjs +67 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @nexart/ai-execution v0.
|
|
1
|
+
# @nexart/ai-execution v0.12.0
|
|
2
2
|
|
|
3
3
|
Tamper-evident records and Certified Execution Records (CER) for AI operations.
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ Tamper-evident records and Certified Execution Records (CER) for AI operations.
|
|
|
7
7
|
| Component | Version |
|
|
8
8
|
|---|---|
|
|
9
9
|
| Service | — |
|
|
10
|
-
| SDK | 0.
|
|
10
|
+
| SDK | 0.12.0 |
|
|
11
11
|
| Protocol | 1.2.0 |
|
|
12
12
|
|
|
13
13
|
## Why Not Just Store Logs?
|
|
@@ -213,6 +213,78 @@ const bundle = sealCer(snapshot, {
|
|
|
213
213
|
// verifyCer(bundle).ok === true — declaration does not affect the result
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
+
## CER Packages (v0.12.0+)
|
|
217
|
+
|
|
218
|
+
A **CER package** is a transport/export envelope that wraps a sealed `cer.ai.execution.v1` bundle with optional receipt, signature, and attestation metadata.
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
{
|
|
222
|
+
"cer": { ...sealed cer.ai.execution.v1 bundle... },
|
|
223
|
+
"receipt": { ...optional attestation receipt... },
|
|
224
|
+
"signature": "base64url...",
|
|
225
|
+
"attestation": { ...optional attestation summary... },
|
|
226
|
+
"verificationEnvelope": { ...optional envelope metadata... },
|
|
227
|
+
"verificationEnvelopeSignature": "base64url..."
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**When to use package helpers vs raw bundle helpers**
|
|
232
|
+
|
|
233
|
+
| Use case | Recommended API |
|
|
234
|
+
|---|---|
|
|
235
|
+
| Creating, verifying, or archiving a CER locally | `certifyDecision`, `verifyCer`, `exportCer` / `importCer` (raw bundle) |
|
|
236
|
+
| Wrapping a CER for transport or external storage with optional metadata | `createCerPackage`, `exportCerPackage`, `importCerPackage` |
|
|
237
|
+
| Detecting whether an object is a package or a raw bundle | `isCerPackage` |
|
|
238
|
+
| Extracting the CER from a received package | `getCerFromPackage` |
|
|
239
|
+
| Verifying integrity of a received package's inner CER | `verifyCerPackage` |
|
|
240
|
+
|
|
241
|
+
The `cer` field inside a package is authoritative. Package helpers never mutate it, never re-hash it, and never inject package-level fields into the CER.
|
|
242
|
+
|
|
243
|
+
### Creating and exporting a package
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { certifyDecision, createCerPackage, exportCerPackage } from '@nexart/ai-execution';
|
|
247
|
+
|
|
248
|
+
const cer = certifyDecision({
|
|
249
|
+
provider: 'openai',
|
|
250
|
+
model: 'gpt-4o',
|
|
251
|
+
prompt: 'Summarize.',
|
|
252
|
+
input: userQuery,
|
|
253
|
+
output: llmResponse,
|
|
254
|
+
parameters: { temperature: 0.7, maxTokens: 1024, topP: null, seed: null },
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const pkg = createCerPackage({
|
|
258
|
+
cer,
|
|
259
|
+
receipt: myAttestationReceipt, // optional
|
|
260
|
+
signature: 'base64url...', // optional
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const json = exportCerPackage(pkg); // stable canonical JSON
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Importing and verifying a package
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { importCerPackage, verifyCerPackage, getCerFromPackage } from '@nexart/ai-execution';
|
|
270
|
+
|
|
271
|
+
// importCerPackage parses + validates shape + verifies inner CER hash
|
|
272
|
+
const pkg = importCerPackage(receivedJsonString); // throws CerVerificationError on failure
|
|
273
|
+
|
|
274
|
+
// Alternatively: parse yourself then verify
|
|
275
|
+
const result = verifyCerPackage(parsedObj);
|
|
276
|
+
if (!result.ok) throw new Error(result.errors.join('; '));
|
|
277
|
+
|
|
278
|
+
const cer = getCerFromPackage(parsedObj); // throws if not a valid package
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Design constraints of package helpers:**
|
|
282
|
+
- Additive only — no changes to CER hashing, canonicalization, or `verifyCer()` semantics
|
|
283
|
+
- `verifyCerPackage` only verifies the inner `cer` bundle; receipt/signature/envelope fields are opaque transport metadata not verified here
|
|
284
|
+
- All existing raw bundle flows (`importCer`, `exportCer`, `verifyCer`) are unchanged
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
216
288
|
## Attestation
|
|
217
289
|
|
|
218
290
|
Endpoint: `POST {nodeUrl}/api/attest`
|
|
@@ -635,6 +707,19 @@ Fixtures at `fixtures/vectors/` and `fixtures/golden/`. Cross-language implement
|
|
|
635
707
|
| `exportCer(bundle)` | Serialize to canonical JSON string |
|
|
636
708
|
| `importCer(json)` | Parse + verify from JSON string |
|
|
637
709
|
|
|
710
|
+
### CER Package Helpers (v0.12.0+)
|
|
711
|
+
|
|
712
|
+
| Function | Description |
|
|
713
|
+
|---|---|
|
|
714
|
+
| `isCerPackage(value)` | Type guard: returns `true` if `value` is a CER package shape (`{ cer: { bundleType: 'cer.ai.execution.v1', ... }, ... }`). Structural check only — does not verify the inner CER hash. |
|
|
715
|
+
| `createCerPackage(params)` | Assemble a CER package from a sealed CER and optional transport fields (`receipt`, `signature`, `attestation`, `verificationEnvelope`, `verificationEnvelopeSignature`). Assembly only — does not re-hash or re-sign. |
|
|
716
|
+
| `getCerFromPackage(pkg)` | Extract and return the inner CER bundle. Throws `CerVerificationError` if `pkg` is not a valid package shape. |
|
|
717
|
+
| `exportCerPackage(pkg)` | Serialize a CER package to a stable canonical JSON string. |
|
|
718
|
+
| `importCerPackage(json)` | Parse a CER package JSON string, validate its shape, and verify the inner CER with `verifyCer()`. Throws `CerVerificationError` on any failure. |
|
|
719
|
+
| `verifyCerPackage(pkg)` | Verify the inner CER of a package using `verifyCer()`. Returns a `VerificationResult`. Conservative: only verifies the inner `cer` — does not verify receipt/signature/envelope. |
|
|
720
|
+
|
|
721
|
+
**Exported types:** `AiCerPackage`, `CreateCerPackageParams`
|
|
722
|
+
|
|
638
723
|
### Provider Drop-in (v0.6.0+)
|
|
639
724
|
|
|
640
725
|
| Function | Description |
|
|
@@ -686,7 +771,7 @@ Priority when multiple failures exist: `CANONICALIZATION_ERROR` > `SCHEMA_ERROR`
|
|
|
686
771
|
|
|
687
772
|
## LangChain Integration
|
|
688
773
|
|
|
689
|
-
`@nexart/ai-execution` includes a minimal LangChain helper surface (introduced v0.10.0, current v0.
|
|
774
|
+
`@nexart/ai-execution` includes a minimal LangChain helper surface (introduced v0.10.0, current v0.12.0). Certify the final input and output of any LangChain chain, agent, or runnable as a tamper-evident CER — no LangChain package dependency required.
|
|
690
775
|
|
|
691
776
|
`certifyLangChainRun` operates in two modes depending on whether `nodeUrl` and `apiKey` are supplied:
|
|
692
777
|
|
|
@@ -957,7 +1042,8 @@ import type { CerContextSignal, CerContext } from '@nexart/ai-execution';
|
|
|
957
1042
|
| v0.8.0 | Helper APIs: `exportVerifiableRedacted()` (post-seal re-seal with redacted snapshot + provenance metadata); `certifyAndAttestRun()` (one-call multi-step certify + optional per-step attestation with injectable mock); test determinism fix; all v0.1–v0.7 bundles verify identically |
|
|
958
1043
|
| v0.9.0 | CER Protocol types: `CerVerificationResult`, `ReasonCode`, `CheckStatus`; `verifyAiCerBundleDetailed()`; `CertifyDecisionParams.createdAt` wired through; determinism bug fix |
|
|
959
1044
|
| v0.10.0 | LangChain integration: `createLangChainCer()` (sync/local); `certifyLangChainRun()` dual-mode — local (sync) or node-attested (`Promise<LangChainAttestedResult>` when `nodeUrl`+`apiKey` supplied); `LangChainAttestedResult`, `AttestDecisionFn`; injectable `_attestFn` for test mocking. **Context signals:** optional `signals?: CerContextSignal[]` on `certifyDecision`, `certifyLangChainRun`, and `createLangChainCer` — sealed into `bundle.context` and included in `certificateHash` when non-empty; absent or empty = hash unchanged from pre-v0.10.0. New types: `CerContextSignal`, `CerContext`. New example: `examples/signals-cer.ts`. 413 total tests; all prior bundles verify identically |
|
|
960
|
-
|
|
|
1045
|
+
| v0.11.0 | Version release. Ships all v0.10.0 features (LangChain integration + context signals) as the published package version. `cerSignals.test.js` added to the `npm test` script. No API, hash, or canonicalization changes |
|
|
1046
|
+
| **v0.12.0** | CER package helpers: `isCerPackage`, `createCerPackage`, `getCerFromPackage`, `exportCerPackage`, `importCerPackage`, `verifyCerPackage`. New types: `AiCerPackage`, `CreateCerPackageParams`. Additive only — no changes to CER hashing, canonicalization, or verification semantics. 466 total tests; all prior bundles verify identically |
|
|
961
1047
|
| v1.0.0 | Planned: API stabilization, freeze public API surface |
|
|
962
1048
|
|
|
963
1049
|
## Releasing
|
package/dist/index.cjs
CHANGED
|
@@ -44,18 +44,23 @@ __export(src_exports, {
|
|
|
44
44
|
certifyLangChainRun: () => certifyLangChainRun,
|
|
45
45
|
computeInputHash: () => computeInputHash,
|
|
46
46
|
computeOutputHash: () => computeOutputHash,
|
|
47
|
+
createCerPackage: () => createCerPackage,
|
|
47
48
|
createClient: () => createClient,
|
|
48
49
|
createLangChainCer: () => createLangChainCer,
|
|
49
50
|
createSnapshot: () => createSnapshot,
|
|
50
51
|
exportCer: () => exportCer,
|
|
52
|
+
exportCerPackage: () => exportCerPackage,
|
|
51
53
|
exportVerifiableRedacted: () => exportVerifiableRedacted,
|
|
52
54
|
fetchNodeKeys: () => fetchNodeKeys,
|
|
53
55
|
getAttestationReceipt: () => getAttestationReceipt,
|
|
56
|
+
getCerFromPackage: () => getCerFromPackage,
|
|
54
57
|
hasAttestation: () => hasAttestation,
|
|
55
58
|
hashCanonicalJson: () => hashCanonicalJson,
|
|
56
59
|
hashToolOutput: () => hashToolOutput,
|
|
57
60
|
hashUtf8: () => hashUtf8,
|
|
58
61
|
importCer: () => importCer,
|
|
62
|
+
importCerPackage: () => importCerPackage,
|
|
63
|
+
isCerPackage: () => isCerPackage,
|
|
59
64
|
makeToolEvent: () => makeToolEvent,
|
|
60
65
|
mapToAiefReason: () => mapToAiefReason,
|
|
61
66
|
redactBeforeSeal: () => redactBeforeSeal,
|
|
@@ -72,6 +77,7 @@ __export(src_exports, {
|
|
|
72
77
|
verifyAief: () => verifyAief,
|
|
73
78
|
verifyBundleAttestation: () => verifyBundleAttestation,
|
|
74
79
|
verifyCer: () => verifyCer,
|
|
80
|
+
verifyCerPackage: () => verifyCerPackage,
|
|
75
81
|
verifyNodeReceiptSignature: () => verifyNodeReceiptSignature,
|
|
76
82
|
verifyRunSummary: () => verifyRunSummary,
|
|
77
83
|
verifySnapshot: () => verifySnapshot,
|
|
@@ -2737,6 +2743,67 @@ function certifyLangChainRun(input, _options) {
|
|
|
2737
2743
|
}
|
|
2738
2744
|
return createLangChainCer(input);
|
|
2739
2745
|
}
|
|
2746
|
+
|
|
2747
|
+
// src/package.ts
|
|
2748
|
+
function isCerPackage(value) {
|
|
2749
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2750
|
+
const pkg = value;
|
|
2751
|
+
if (typeof pkg["cer"] !== "object" || pkg["cer"] === null) return false;
|
|
2752
|
+
const cer = pkg["cer"];
|
|
2753
|
+
return cer["bundleType"] === "cer.ai.execution.v1";
|
|
2754
|
+
}
|
|
2755
|
+
function createCerPackage(params) {
|
|
2756
|
+
const pkg = { cer: params.cer };
|
|
2757
|
+
if (params.receipt !== void 0) pkg.receipt = params.receipt;
|
|
2758
|
+
if (params.signature !== void 0) pkg.signature = params.signature;
|
|
2759
|
+
if (params.attestation !== void 0) pkg.attestation = params.attestation;
|
|
2760
|
+
if (params.verificationEnvelope !== void 0) pkg.verificationEnvelope = params.verificationEnvelope;
|
|
2761
|
+
if (params.verificationEnvelopeSignature !== void 0) pkg.verificationEnvelopeSignature = params.verificationEnvelopeSignature;
|
|
2762
|
+
return pkg;
|
|
2763
|
+
}
|
|
2764
|
+
function getCerFromPackage(pkg) {
|
|
2765
|
+
if (!isCerPackage(pkg)) {
|
|
2766
|
+
throw new CerVerificationError([
|
|
2767
|
+
"getCerFromPackage: value is not a valid CER package (missing or invalid cer field)"
|
|
2768
|
+
]);
|
|
2769
|
+
}
|
|
2770
|
+
return pkg.cer;
|
|
2771
|
+
}
|
|
2772
|
+
function exportCerPackage(pkg) {
|
|
2773
|
+
return toCanonicalJson(pkg);
|
|
2774
|
+
}
|
|
2775
|
+
function importCerPackage(json) {
|
|
2776
|
+
let parsed;
|
|
2777
|
+
try {
|
|
2778
|
+
parsed = JSON.parse(json);
|
|
2779
|
+
} catch (err2) {
|
|
2780
|
+
throw new CerVerificationError([
|
|
2781
|
+
`importCerPackage: invalid JSON: ${err2.message}`
|
|
2782
|
+
]);
|
|
2783
|
+
}
|
|
2784
|
+
if (!isCerPackage(parsed)) {
|
|
2785
|
+
throw new CerVerificationError([
|
|
2786
|
+
"importCerPackage: parsed value is not a CER package (missing or invalid cer field)"
|
|
2787
|
+
]);
|
|
2788
|
+
}
|
|
2789
|
+
const result = verifyCer(parsed.cer);
|
|
2790
|
+
if (!result.ok) {
|
|
2791
|
+
throw new CerVerificationError([
|
|
2792
|
+
`importCerPackage: inner CER failed verification: ${result.errors.join("; ")}`
|
|
2793
|
+
]);
|
|
2794
|
+
}
|
|
2795
|
+
return parsed;
|
|
2796
|
+
}
|
|
2797
|
+
function verifyCerPackage(pkg) {
|
|
2798
|
+
if (!isCerPackage(pkg)) {
|
|
2799
|
+
return {
|
|
2800
|
+
ok: false,
|
|
2801
|
+
errors: ["verifyCerPackage: value is not a CER package (missing or invalid cer field)"],
|
|
2802
|
+
code: CerVerifyCode.SCHEMA_ERROR
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2805
|
+
return verifyCer(pkg.cer);
|
|
2806
|
+
}
|
|
2740
2807
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2741
2808
|
0 && (module.exports = {
|
|
2742
2809
|
CerAttestationError,
|
|
@@ -2753,18 +2820,23 @@ function certifyLangChainRun(input, _options) {
|
|
|
2753
2820
|
certifyLangChainRun,
|
|
2754
2821
|
computeInputHash,
|
|
2755
2822
|
computeOutputHash,
|
|
2823
|
+
createCerPackage,
|
|
2756
2824
|
createClient,
|
|
2757
2825
|
createLangChainCer,
|
|
2758
2826
|
createSnapshot,
|
|
2759
2827
|
exportCer,
|
|
2828
|
+
exportCerPackage,
|
|
2760
2829
|
exportVerifiableRedacted,
|
|
2761
2830
|
fetchNodeKeys,
|
|
2762
2831
|
getAttestationReceipt,
|
|
2832
|
+
getCerFromPackage,
|
|
2763
2833
|
hasAttestation,
|
|
2764
2834
|
hashCanonicalJson,
|
|
2765
2835
|
hashToolOutput,
|
|
2766
2836
|
hashUtf8,
|
|
2767
2837
|
importCer,
|
|
2838
|
+
importCerPackage,
|
|
2839
|
+
isCerPackage,
|
|
2768
2840
|
makeToolEvent,
|
|
2769
2841
|
mapToAiefReason,
|
|
2770
2842
|
redactBeforeSeal,
|
|
@@ -2781,6 +2853,7 @@ function certifyLangChainRun(input, _options) {
|
|
|
2781
2853
|
verifyAief,
|
|
2782
2854
|
verifyBundleAttestation,
|
|
2783
2855
|
verifyCer,
|
|
2856
|
+
verifyCerPackage,
|
|
2784
2857
|
verifyNodeReceiptSignature,
|
|
2785
2858
|
verifyRunSummary,
|
|
2786
2859
|
verifySnapshot,
|