@nexart/ai-execution 0.7.0 → 0.9.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 +85 -7
- package/dist/index.cjs +143 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +215 -3
- package/dist/index.d.ts +215 -3
- package/dist/index.mjs +139 -2
- package/dist/index.mjs.map +1 -1
- package/dist/providers/anthropic.cjs +1 -1
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.mjs +1 -1
- package/dist/providers/anthropic.mjs.map +1 -1
- package/dist/providers/openai.cjs +1 -1
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.mjs +1 -1
- package/dist/providers/openai.mjs.map +1 -1
- package/dist/providers/wrap.cjs +1 -1
- package/dist/providers/wrap.cjs.map +1 -1
- package/dist/providers/wrap.d.cts +1 -1
- package/dist/providers/wrap.d.ts +1 -1
- package/dist/providers/wrap.mjs +1 -1
- package/dist/providers/wrap.mjs.map +1 -1
- package/dist/{types-CcqCDPrD.d.cts → types-C5t12OK8.d.cts} +2 -0
- package/dist/{types-CcqCDPrD.d.ts → types-C5t12OK8.d.ts} +2 -0
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CreateSnapshotParams, A as AiExecutionSnapshotV1, V as VerificationResult, a as CerMeta, B as BundleDeclaration, b as CerAiExecutionBundle, c as CertifyDecisionParams, R as RunBuilderOptions, S as StepParams, d as RunSummary, e as AttestOptions, f as AttestationResult, g as SanitizeStorageOptions, h as AttestationReceipt, N as NodeKeysDocument, i as NodeReceiptVerifyResult, j as SignedAttestationReceipt, k as CerVerifyCode, l as AiefVerifyResult, T as ToolEvent, m as RunSummaryVerifyResult, n as AiefProfile } from './types-
|
|
2
|
-
export { o as AiExecutionParameters, p as AttestationReceiptResult, q as ClientDefaults, r as NexArtClient, P as ProviderCallParams, s as ProviderCallResult, t as ProviderConfig, u as RedactionEnvelope, W as WrappedExecutionParams, v as WrappedExecutionResult } from './types-
|
|
1
|
+
import { C as CreateSnapshotParams, A as AiExecutionSnapshotV1, V as VerificationResult, a as CerMeta, B as BundleDeclaration, b as CerAiExecutionBundle, c as CertifyDecisionParams, R as RunBuilderOptions, S as StepParams, d as RunSummary, e as AttestOptions, f as AttestationResult, g as SanitizeStorageOptions, h as AttestationReceipt, N as NodeKeysDocument, i as NodeReceiptVerifyResult, j as SignedAttestationReceipt, k as CerVerifyCode, l as AiefVerifyResult, T as ToolEvent, m as RunSummaryVerifyResult, n as AiefProfile } from './types-C5t12OK8.cjs';
|
|
2
|
+
export { o as AiExecutionParameters, p as AttestationReceiptResult, q as ClientDefaults, r as NexArtClient, P as ProviderCallParams, s as ProviderCallResult, t as ProviderConfig, u as RedactionEnvelope, W as WrappedExecutionParams, v as WrappedExecutionResult } from './types-C5t12OK8.cjs';
|
|
3
3
|
export { wrapProvider } from './providers/wrap.cjs';
|
|
4
4
|
|
|
5
5
|
declare class CerVerificationError extends Error {
|
|
@@ -353,4 +353,216 @@ interface ProfileValidationResult {
|
|
|
353
353
|
*/
|
|
354
354
|
declare function validateProfile(target: AiExecutionSnapshotV1 | CerAiExecutionBundle, profile: AiefProfile): ProfileValidationResult;
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
/**
|
|
357
|
+
* @nexart/ai-execution — Verifiable redacted export helper
|
|
358
|
+
*
|
|
359
|
+
* exportVerifiableRedacted() produces a NEW sealed bundle whose snapshot has
|
|
360
|
+
* sensitive fields replaced with redaction envelopes via redactBeforeSeal().
|
|
361
|
+
*
|
|
362
|
+
* The result is a fully independently verifiable bundle with a NEW certificateHash.
|
|
363
|
+
* The original certificateHash is preserved in meta.provenance as an informational
|
|
364
|
+
* cross-reference ONLY — it does not establish any cryptographic relationship
|
|
365
|
+
* between the two bundles.
|
|
366
|
+
*
|
|
367
|
+
* verify(newBundle) → { ok: true } ✅ the new bundle verifies on its own
|
|
368
|
+
* verify(originalBundle) → { ok: true } ✅ the original is unaffected
|
|
369
|
+
*
|
|
370
|
+
* IMPORTANT CONSTRAINTS:
|
|
371
|
+
* - Only `input` and `output` paths are safe to redact (their content hashes are
|
|
372
|
+
* recomputed from the envelope). Schema-validated string fields like `prompt`
|
|
373
|
+
* cannot be replaced with an object envelope — verify() will return SCHEMA_ERROR.
|
|
374
|
+
* - `meta.provenance.originalCertificateHash` is reference metadata only.
|
|
375
|
+
* Anyone who receives only the new bundle cannot verify the original's integrity.
|
|
376
|
+
*/
|
|
377
|
+
|
|
378
|
+
interface ExportVerifiableRedactedOptions {
|
|
379
|
+
createdAt?: string;
|
|
380
|
+
}
|
|
381
|
+
interface ExportVerifiableRedactedProvenance {
|
|
382
|
+
originalCertificateHash: string;
|
|
383
|
+
redactionPolicy: {
|
|
384
|
+
paths: string[];
|
|
385
|
+
};
|
|
386
|
+
redactedAt: string;
|
|
387
|
+
}
|
|
388
|
+
interface ExportVerifiableRedactedResult {
|
|
389
|
+
bundle: CerAiExecutionBundle;
|
|
390
|
+
/**
|
|
391
|
+
* The original bundle's certificateHash. Convenience alias for
|
|
392
|
+
* `bundle.meta.provenance.originalCertificateHash`.
|
|
393
|
+
* Reference only — no cryptographic link to the new bundle.
|
|
394
|
+
*/
|
|
395
|
+
originalCertificateHash: string;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Produce a new sealed bundle with redacted snapshot fields.
|
|
399
|
+
*
|
|
400
|
+
* @param bundle The original sealed bundle to redact from.
|
|
401
|
+
* @param policy Which snapshot paths to redact. Only 'input' and 'output'
|
|
402
|
+
* are safe for verifiable redaction (their content hashes are
|
|
403
|
+
* recomputed). Other schema-validated string fields will cause
|
|
404
|
+
* verify() to return SCHEMA_ERROR on the new bundle.
|
|
405
|
+
* @param options Optional overrides (createdAt).
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```typescript
|
|
409
|
+
* import { certifyDecision, verify, exportVerifiableRedacted } from '@nexart/ai-execution';
|
|
410
|
+
*
|
|
411
|
+
* const original = certifyDecision({ ... });
|
|
412
|
+
* const { bundle, originalCertificateHash } = exportVerifiableRedacted(
|
|
413
|
+
* original,
|
|
414
|
+
* { paths: ['input', 'output'] },
|
|
415
|
+
* );
|
|
416
|
+
*
|
|
417
|
+
* verify(bundle).ok; // true
|
|
418
|
+
* bundle.meta.provenance.originalCertificateHash; // 'sha256:...' — reference only
|
|
419
|
+
* bundle.snapshot.input; // { _redacted: true, hash: 'sha256:...' }
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
declare function exportVerifiableRedacted(bundle: CerAiExecutionBundle, policy: RedactBeforeSealPolicy, options?: ExportVerifiableRedactedOptions): ExportVerifiableRedactedResult;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @nexart/ai-execution — Opinionated run helper
|
|
426
|
+
*
|
|
427
|
+
* certifyAndAttestRun(): certify every step in a multi-step run via RunBuilder,
|
|
428
|
+
* optionally attest each sealed bundle, and return a consolidated result.
|
|
429
|
+
*
|
|
430
|
+
* Design principles:
|
|
431
|
+
* - Does NOT mutate or wrap any externally-owned RunBuilder. Creates its own.
|
|
432
|
+
* - RunBuilder semantics are unchanged: prevStepHash chaining is automatic.
|
|
433
|
+
* - attestStep is optional and injectable so callers can mock in tests without
|
|
434
|
+
* hitting the network.
|
|
435
|
+
* - Network failures from attestStep bubble up — wrap in try/catch for partial
|
|
436
|
+
* failure tolerance.
|
|
437
|
+
*/
|
|
438
|
+
|
|
439
|
+
interface CertifyAndAttestRunOptions {
|
|
440
|
+
runId?: string;
|
|
441
|
+
workflowId?: string | null;
|
|
442
|
+
conversationId?: string | null;
|
|
443
|
+
appId?: string | null;
|
|
444
|
+
/**
|
|
445
|
+
* Optional per-step attestation function. Receives each sealed step bundle
|
|
446
|
+
* immediately after it is created. Return an AttestationReceipt on success.
|
|
447
|
+
*
|
|
448
|
+
* If omitted, all receipts will be null (bundles are sealed but not attested).
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```typescript
|
|
452
|
+
* import { attest } from '@nexart/ai-execution';
|
|
453
|
+
* certifyAndAttestRun(steps, {
|
|
454
|
+
* attestStep: (bundle) => attest(bundle, { nodeUrl, apiKey }),
|
|
455
|
+
* });
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
attestStep?: (bundle: CerAiExecutionBundle) => Promise<AttestationReceipt>;
|
|
459
|
+
}
|
|
460
|
+
interface CertifyAndAttestRunResult {
|
|
461
|
+
runSummary: RunSummary;
|
|
462
|
+
stepBundles: CerAiExecutionBundle[];
|
|
463
|
+
/**
|
|
464
|
+
* Attestation receipts in step order. `null` at index i means the step
|
|
465
|
+
* was sealed but not attested (no `attestStep` option was provided).
|
|
466
|
+
*/
|
|
467
|
+
receipts: (AttestationReceipt | null)[];
|
|
468
|
+
/** Alias for runSummary.finalStepHash — the last step's certificateHash. */
|
|
469
|
+
finalStepHash: string | null;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Certify every step in a multi-step run and optionally attest each bundle.
|
|
473
|
+
*
|
|
474
|
+
* Each step is sealed via RunBuilder, which automatically:
|
|
475
|
+
* - assigns stepIndex (0-based)
|
|
476
|
+
* - sets prevStepHash to the previous step's certificateHash
|
|
477
|
+
* - assigns a unique executionId and stepId per step
|
|
478
|
+
*
|
|
479
|
+
* The resulting runSummary + stepBundles can be validated offline with
|
|
480
|
+
* verifyRunSummary(runSummary, stepBundles).
|
|
481
|
+
*
|
|
482
|
+
* @param steps Ordered list of step parameters (step 0 first).
|
|
483
|
+
* @param options Run-level options and optional attestation hook.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```typescript
|
|
487
|
+
* import { certifyAndAttestRun, verifyRunSummary } from '@nexart/ai-execution';
|
|
488
|
+
*
|
|
489
|
+
* const { runSummary, stepBundles, receipts, finalStepHash } =
|
|
490
|
+
* await certifyAndAttestRun(
|
|
491
|
+
* [step0Params, step1Params, step2Params],
|
|
492
|
+
* {
|
|
493
|
+
* runId: 'analysis-run',
|
|
494
|
+
* workflowId: 'data-pipeline',
|
|
495
|
+
* attestStep: (bundle) => attest(bundle, { nodeUrl, apiKey }),
|
|
496
|
+
* },
|
|
497
|
+
* );
|
|
498
|
+
*
|
|
499
|
+
* verifyRunSummary(runSummary, stepBundles); // { ok: true }
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
declare function certifyAndAttestRun(steps: StepParams[], options?: CertifyAndAttestRunOptions): Promise<CertifyAndAttestRunResult>;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* CER Protocol verification types — v0.9.0
|
|
506
|
+
*
|
|
507
|
+
* These are the canonical structured verification types for the NexArt
|
|
508
|
+
* Certified Execution Record (CER) Protocol. All NexArt-compatible verifiers
|
|
509
|
+
* should produce a CerVerificationResult.
|
|
510
|
+
*
|
|
511
|
+
* NOTE: The existing VerificationResult type (ok/errors/code shape) is preserved
|
|
512
|
+
* for backward compatibility. CerVerificationResult is the new protocol-aligned type.
|
|
513
|
+
*/
|
|
514
|
+
type VerificationStatus = 'VERIFIED' | 'FAILED' | 'NOT_FOUND';
|
|
515
|
+
type CheckStatus = 'PASS' | 'FAIL' | 'SKIPPED';
|
|
516
|
+
declare const ReasonCode: {
|
|
517
|
+
readonly BUNDLE_HASH_MISMATCH: "BUNDLE_HASH_MISMATCH";
|
|
518
|
+
readonly NODE_SIGNATURE_INVALID: "NODE_SIGNATURE_INVALID";
|
|
519
|
+
readonly NODE_SIGNATURE_MISSING: "NODE_SIGNATURE_MISSING";
|
|
520
|
+
readonly RECEIPT_HASH_MISMATCH: "RECEIPT_HASH_MISMATCH";
|
|
521
|
+
readonly SCHEMA_VERSION_UNSUPPORTED: "SCHEMA_VERSION_UNSUPPORTED";
|
|
522
|
+
readonly RECORD_NOT_FOUND: "RECORD_NOT_FOUND";
|
|
523
|
+
readonly BUNDLE_CORRUPTED: "BUNDLE_CORRUPTED";
|
|
524
|
+
};
|
|
525
|
+
type ReasonCode = typeof ReasonCode[keyof typeof ReasonCode];
|
|
526
|
+
/**
|
|
527
|
+
* Canonical protocol verification result.
|
|
528
|
+
*
|
|
529
|
+
* Produced by verifyAiCerBundleDetailed() and verifyCodeModeSnapshotDetailed().
|
|
530
|
+
* All checks that are not applicable to a given bundle type are SKIPPED (never FAIL).
|
|
531
|
+
*/
|
|
532
|
+
interface CerVerificationResult {
|
|
533
|
+
status: VerificationStatus;
|
|
534
|
+
checks: {
|
|
535
|
+
bundleIntegrity: CheckStatus;
|
|
536
|
+
nodeSignature: CheckStatus;
|
|
537
|
+
receiptConsistency: CheckStatus;
|
|
538
|
+
};
|
|
539
|
+
reasonCodes: ReasonCode[];
|
|
540
|
+
certificateHash: string;
|
|
541
|
+
bundleType: string;
|
|
542
|
+
verifiedAt: string;
|
|
543
|
+
verifier: string;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* verifyAiCerBundleDetailed — protocol-aligned AI CER verifier
|
|
548
|
+
*
|
|
549
|
+
* Returns a CerVerificationResult conforming to the CER Protocol spec.
|
|
550
|
+
* Wraps the existing verifyCer() + hasAttestation() helpers and maps
|
|
551
|
+
* their results into the structured protocol schema.
|
|
552
|
+
*/
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Verify a CER AI execution bundle and return a structured CerVerificationResult.
|
|
556
|
+
*
|
|
557
|
+
* - bundleIntegrity: PASS/FAIL based on certificateHash integrity
|
|
558
|
+
* - nodeSignature: PASS if attestation present and structurally valid; SKIPPED if absent
|
|
559
|
+
* - receiptConsistency: mirrors nodeSignature (SKIPPED when no attestation)
|
|
560
|
+
*
|
|
561
|
+
* Attestation is optional — its absence sets nodeSignature/receiptConsistency
|
|
562
|
+
* to SKIPPED, not FAIL.
|
|
563
|
+
*
|
|
564
|
+
* @param bundle - The raw CER bundle (typed as unknown for safety; validated internally)
|
|
565
|
+
*/
|
|
566
|
+
declare function verifyAiCerBundleDetailed(bundle: unknown): CerVerificationResult;
|
|
567
|
+
|
|
568
|
+
export { AiExecutionSnapshotV1, AiefProfile, AiefVerifyResult, AttestOptions, AttestationReceipt, AttestationResult, BundleDeclaration, CerAiExecutionBundle, CerAttestationError, CerMeta, CerVerificationError, type CerVerificationResult, CerVerifyCode, CerVerifyCode as CerVerifyCodeType, type CertifyAndAttestRunOptions, type CertifyAndAttestRunResult, CertifyDecisionParams, type CheckStatus, CreateSnapshotParams, type ExportVerifiableRedactedOptions, type ExportVerifiableRedactedProvenance, type ExportVerifiableRedactedResult, type MakeToolEventParams, NodeKeysDocument, NodeReceiptVerifyResult, type ProfileValidationResult, ReasonCode, ReasonCode as ReasonCodeType, type RedactBeforeSealPolicy, RunBuilder, RunBuilderOptions, RunSummary, RunSummaryVerifyResult, SanitizeStorageOptions, SignedAttestationReceipt, StepParams, ToolEvent, VerificationResult, type VerificationStatus, type VerifyRunSummaryOptions, attest, attestIfNeeded, certifyAndAttestDecision, certifyAndAttestRun, certifyDecision, certifyDecisionFromProviderCall, computeInputHash, computeOutputHash, createClient, createSnapshot, exportCer, exportVerifiableRedacted, fetchNodeKeys, getAttestationReceipt, hasAttestation, hashCanonicalJson, hashToolOutput, hashUtf8, importCer, makeToolEvent, mapToAiefReason, redactBeforeSeal, sanitizeForAttestation, sanitizeForStamp, sanitizeForStorage, sealCer, selectNodeKey, sha256Hex, toCanonicalJson, validateProfile, verifyCer as verify, verifyAiCerBundleDetailed, verifyAief, verifyBundleAttestation, verifyCer, verifyNodeReceiptSignature, verifyRunSummary, verifySnapshot };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CreateSnapshotParams, A as AiExecutionSnapshotV1, V as VerificationResult, a as CerMeta, B as BundleDeclaration, b as CerAiExecutionBundle, c as CertifyDecisionParams, R as RunBuilderOptions, S as StepParams, d as RunSummary, e as AttestOptions, f as AttestationResult, g as SanitizeStorageOptions, h as AttestationReceipt, N as NodeKeysDocument, i as NodeReceiptVerifyResult, j as SignedAttestationReceipt, k as CerVerifyCode, l as AiefVerifyResult, T as ToolEvent, m as RunSummaryVerifyResult, n as AiefProfile } from './types-
|
|
2
|
-
export { o as AiExecutionParameters, p as AttestationReceiptResult, q as ClientDefaults, r as NexArtClient, P as ProviderCallParams, s as ProviderCallResult, t as ProviderConfig, u as RedactionEnvelope, W as WrappedExecutionParams, v as WrappedExecutionResult } from './types-
|
|
1
|
+
import { C as CreateSnapshotParams, A as AiExecutionSnapshotV1, V as VerificationResult, a as CerMeta, B as BundleDeclaration, b as CerAiExecutionBundle, c as CertifyDecisionParams, R as RunBuilderOptions, S as StepParams, d as RunSummary, e as AttestOptions, f as AttestationResult, g as SanitizeStorageOptions, h as AttestationReceipt, N as NodeKeysDocument, i as NodeReceiptVerifyResult, j as SignedAttestationReceipt, k as CerVerifyCode, l as AiefVerifyResult, T as ToolEvent, m as RunSummaryVerifyResult, n as AiefProfile } from './types-C5t12OK8.js';
|
|
2
|
+
export { o as AiExecutionParameters, p as AttestationReceiptResult, q as ClientDefaults, r as NexArtClient, P as ProviderCallParams, s as ProviderCallResult, t as ProviderConfig, u as RedactionEnvelope, W as WrappedExecutionParams, v as WrappedExecutionResult } from './types-C5t12OK8.js';
|
|
3
3
|
export { wrapProvider } from './providers/wrap.js';
|
|
4
4
|
|
|
5
5
|
declare class CerVerificationError extends Error {
|
|
@@ -353,4 +353,216 @@ interface ProfileValidationResult {
|
|
|
353
353
|
*/
|
|
354
354
|
declare function validateProfile(target: AiExecutionSnapshotV1 | CerAiExecutionBundle, profile: AiefProfile): ProfileValidationResult;
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
/**
|
|
357
|
+
* @nexart/ai-execution — Verifiable redacted export helper
|
|
358
|
+
*
|
|
359
|
+
* exportVerifiableRedacted() produces a NEW sealed bundle whose snapshot has
|
|
360
|
+
* sensitive fields replaced with redaction envelopes via redactBeforeSeal().
|
|
361
|
+
*
|
|
362
|
+
* The result is a fully independently verifiable bundle with a NEW certificateHash.
|
|
363
|
+
* The original certificateHash is preserved in meta.provenance as an informational
|
|
364
|
+
* cross-reference ONLY — it does not establish any cryptographic relationship
|
|
365
|
+
* between the two bundles.
|
|
366
|
+
*
|
|
367
|
+
* verify(newBundle) → { ok: true } ✅ the new bundle verifies on its own
|
|
368
|
+
* verify(originalBundle) → { ok: true } ✅ the original is unaffected
|
|
369
|
+
*
|
|
370
|
+
* IMPORTANT CONSTRAINTS:
|
|
371
|
+
* - Only `input` and `output` paths are safe to redact (their content hashes are
|
|
372
|
+
* recomputed from the envelope). Schema-validated string fields like `prompt`
|
|
373
|
+
* cannot be replaced with an object envelope — verify() will return SCHEMA_ERROR.
|
|
374
|
+
* - `meta.provenance.originalCertificateHash` is reference metadata only.
|
|
375
|
+
* Anyone who receives only the new bundle cannot verify the original's integrity.
|
|
376
|
+
*/
|
|
377
|
+
|
|
378
|
+
interface ExportVerifiableRedactedOptions {
|
|
379
|
+
createdAt?: string;
|
|
380
|
+
}
|
|
381
|
+
interface ExportVerifiableRedactedProvenance {
|
|
382
|
+
originalCertificateHash: string;
|
|
383
|
+
redactionPolicy: {
|
|
384
|
+
paths: string[];
|
|
385
|
+
};
|
|
386
|
+
redactedAt: string;
|
|
387
|
+
}
|
|
388
|
+
interface ExportVerifiableRedactedResult {
|
|
389
|
+
bundle: CerAiExecutionBundle;
|
|
390
|
+
/**
|
|
391
|
+
* The original bundle's certificateHash. Convenience alias for
|
|
392
|
+
* `bundle.meta.provenance.originalCertificateHash`.
|
|
393
|
+
* Reference only — no cryptographic link to the new bundle.
|
|
394
|
+
*/
|
|
395
|
+
originalCertificateHash: string;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Produce a new sealed bundle with redacted snapshot fields.
|
|
399
|
+
*
|
|
400
|
+
* @param bundle The original sealed bundle to redact from.
|
|
401
|
+
* @param policy Which snapshot paths to redact. Only 'input' and 'output'
|
|
402
|
+
* are safe for verifiable redaction (their content hashes are
|
|
403
|
+
* recomputed). Other schema-validated string fields will cause
|
|
404
|
+
* verify() to return SCHEMA_ERROR on the new bundle.
|
|
405
|
+
* @param options Optional overrides (createdAt).
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```typescript
|
|
409
|
+
* import { certifyDecision, verify, exportVerifiableRedacted } from '@nexart/ai-execution';
|
|
410
|
+
*
|
|
411
|
+
* const original = certifyDecision({ ... });
|
|
412
|
+
* const { bundle, originalCertificateHash } = exportVerifiableRedacted(
|
|
413
|
+
* original,
|
|
414
|
+
* { paths: ['input', 'output'] },
|
|
415
|
+
* );
|
|
416
|
+
*
|
|
417
|
+
* verify(bundle).ok; // true
|
|
418
|
+
* bundle.meta.provenance.originalCertificateHash; // 'sha256:...' — reference only
|
|
419
|
+
* bundle.snapshot.input; // { _redacted: true, hash: 'sha256:...' }
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
declare function exportVerifiableRedacted(bundle: CerAiExecutionBundle, policy: RedactBeforeSealPolicy, options?: ExportVerifiableRedactedOptions): ExportVerifiableRedactedResult;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @nexart/ai-execution — Opinionated run helper
|
|
426
|
+
*
|
|
427
|
+
* certifyAndAttestRun(): certify every step in a multi-step run via RunBuilder,
|
|
428
|
+
* optionally attest each sealed bundle, and return a consolidated result.
|
|
429
|
+
*
|
|
430
|
+
* Design principles:
|
|
431
|
+
* - Does NOT mutate or wrap any externally-owned RunBuilder. Creates its own.
|
|
432
|
+
* - RunBuilder semantics are unchanged: prevStepHash chaining is automatic.
|
|
433
|
+
* - attestStep is optional and injectable so callers can mock in tests without
|
|
434
|
+
* hitting the network.
|
|
435
|
+
* - Network failures from attestStep bubble up — wrap in try/catch for partial
|
|
436
|
+
* failure tolerance.
|
|
437
|
+
*/
|
|
438
|
+
|
|
439
|
+
interface CertifyAndAttestRunOptions {
|
|
440
|
+
runId?: string;
|
|
441
|
+
workflowId?: string | null;
|
|
442
|
+
conversationId?: string | null;
|
|
443
|
+
appId?: string | null;
|
|
444
|
+
/**
|
|
445
|
+
* Optional per-step attestation function. Receives each sealed step bundle
|
|
446
|
+
* immediately after it is created. Return an AttestationReceipt on success.
|
|
447
|
+
*
|
|
448
|
+
* If omitted, all receipts will be null (bundles are sealed but not attested).
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```typescript
|
|
452
|
+
* import { attest } from '@nexart/ai-execution';
|
|
453
|
+
* certifyAndAttestRun(steps, {
|
|
454
|
+
* attestStep: (bundle) => attest(bundle, { nodeUrl, apiKey }),
|
|
455
|
+
* });
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
attestStep?: (bundle: CerAiExecutionBundle) => Promise<AttestationReceipt>;
|
|
459
|
+
}
|
|
460
|
+
interface CertifyAndAttestRunResult {
|
|
461
|
+
runSummary: RunSummary;
|
|
462
|
+
stepBundles: CerAiExecutionBundle[];
|
|
463
|
+
/**
|
|
464
|
+
* Attestation receipts in step order. `null` at index i means the step
|
|
465
|
+
* was sealed but not attested (no `attestStep` option was provided).
|
|
466
|
+
*/
|
|
467
|
+
receipts: (AttestationReceipt | null)[];
|
|
468
|
+
/** Alias for runSummary.finalStepHash — the last step's certificateHash. */
|
|
469
|
+
finalStepHash: string | null;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Certify every step in a multi-step run and optionally attest each bundle.
|
|
473
|
+
*
|
|
474
|
+
* Each step is sealed via RunBuilder, which automatically:
|
|
475
|
+
* - assigns stepIndex (0-based)
|
|
476
|
+
* - sets prevStepHash to the previous step's certificateHash
|
|
477
|
+
* - assigns a unique executionId and stepId per step
|
|
478
|
+
*
|
|
479
|
+
* The resulting runSummary + stepBundles can be validated offline with
|
|
480
|
+
* verifyRunSummary(runSummary, stepBundles).
|
|
481
|
+
*
|
|
482
|
+
* @param steps Ordered list of step parameters (step 0 first).
|
|
483
|
+
* @param options Run-level options and optional attestation hook.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```typescript
|
|
487
|
+
* import { certifyAndAttestRun, verifyRunSummary } from '@nexart/ai-execution';
|
|
488
|
+
*
|
|
489
|
+
* const { runSummary, stepBundles, receipts, finalStepHash } =
|
|
490
|
+
* await certifyAndAttestRun(
|
|
491
|
+
* [step0Params, step1Params, step2Params],
|
|
492
|
+
* {
|
|
493
|
+
* runId: 'analysis-run',
|
|
494
|
+
* workflowId: 'data-pipeline',
|
|
495
|
+
* attestStep: (bundle) => attest(bundle, { nodeUrl, apiKey }),
|
|
496
|
+
* },
|
|
497
|
+
* );
|
|
498
|
+
*
|
|
499
|
+
* verifyRunSummary(runSummary, stepBundles); // { ok: true }
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
declare function certifyAndAttestRun(steps: StepParams[], options?: CertifyAndAttestRunOptions): Promise<CertifyAndAttestRunResult>;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* CER Protocol verification types — v0.9.0
|
|
506
|
+
*
|
|
507
|
+
* These are the canonical structured verification types for the NexArt
|
|
508
|
+
* Certified Execution Record (CER) Protocol. All NexArt-compatible verifiers
|
|
509
|
+
* should produce a CerVerificationResult.
|
|
510
|
+
*
|
|
511
|
+
* NOTE: The existing VerificationResult type (ok/errors/code shape) is preserved
|
|
512
|
+
* for backward compatibility. CerVerificationResult is the new protocol-aligned type.
|
|
513
|
+
*/
|
|
514
|
+
type VerificationStatus = 'VERIFIED' | 'FAILED' | 'NOT_FOUND';
|
|
515
|
+
type CheckStatus = 'PASS' | 'FAIL' | 'SKIPPED';
|
|
516
|
+
declare const ReasonCode: {
|
|
517
|
+
readonly BUNDLE_HASH_MISMATCH: "BUNDLE_HASH_MISMATCH";
|
|
518
|
+
readonly NODE_SIGNATURE_INVALID: "NODE_SIGNATURE_INVALID";
|
|
519
|
+
readonly NODE_SIGNATURE_MISSING: "NODE_SIGNATURE_MISSING";
|
|
520
|
+
readonly RECEIPT_HASH_MISMATCH: "RECEIPT_HASH_MISMATCH";
|
|
521
|
+
readonly SCHEMA_VERSION_UNSUPPORTED: "SCHEMA_VERSION_UNSUPPORTED";
|
|
522
|
+
readonly RECORD_NOT_FOUND: "RECORD_NOT_FOUND";
|
|
523
|
+
readonly BUNDLE_CORRUPTED: "BUNDLE_CORRUPTED";
|
|
524
|
+
};
|
|
525
|
+
type ReasonCode = typeof ReasonCode[keyof typeof ReasonCode];
|
|
526
|
+
/**
|
|
527
|
+
* Canonical protocol verification result.
|
|
528
|
+
*
|
|
529
|
+
* Produced by verifyAiCerBundleDetailed() and verifyCodeModeSnapshotDetailed().
|
|
530
|
+
* All checks that are not applicable to a given bundle type are SKIPPED (never FAIL).
|
|
531
|
+
*/
|
|
532
|
+
interface CerVerificationResult {
|
|
533
|
+
status: VerificationStatus;
|
|
534
|
+
checks: {
|
|
535
|
+
bundleIntegrity: CheckStatus;
|
|
536
|
+
nodeSignature: CheckStatus;
|
|
537
|
+
receiptConsistency: CheckStatus;
|
|
538
|
+
};
|
|
539
|
+
reasonCodes: ReasonCode[];
|
|
540
|
+
certificateHash: string;
|
|
541
|
+
bundleType: string;
|
|
542
|
+
verifiedAt: string;
|
|
543
|
+
verifier: string;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* verifyAiCerBundleDetailed — protocol-aligned AI CER verifier
|
|
548
|
+
*
|
|
549
|
+
* Returns a CerVerificationResult conforming to the CER Protocol spec.
|
|
550
|
+
* Wraps the existing verifyCer() + hasAttestation() helpers and maps
|
|
551
|
+
* their results into the structured protocol schema.
|
|
552
|
+
*/
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Verify a CER AI execution bundle and return a structured CerVerificationResult.
|
|
556
|
+
*
|
|
557
|
+
* - bundleIntegrity: PASS/FAIL based on certificateHash integrity
|
|
558
|
+
* - nodeSignature: PASS if attestation present and structurally valid; SKIPPED if absent
|
|
559
|
+
* - receiptConsistency: mirrors nodeSignature (SKIPPED when no attestation)
|
|
560
|
+
*
|
|
561
|
+
* Attestation is optional — its absence sets nodeSignature/receiptConsistency
|
|
562
|
+
* to SKIPPED, not FAIL.
|
|
563
|
+
*
|
|
564
|
+
* @param bundle - The raw CER bundle (typed as unknown for safety; validated internally)
|
|
565
|
+
*/
|
|
566
|
+
declare function verifyAiCerBundleDetailed(bundle: unknown): CerVerificationResult;
|
|
567
|
+
|
|
568
|
+
export { AiExecutionSnapshotV1, AiefProfile, AiefVerifyResult, AttestOptions, AttestationReceipt, AttestationResult, BundleDeclaration, CerAiExecutionBundle, CerAttestationError, CerMeta, CerVerificationError, type CerVerificationResult, CerVerifyCode, CerVerifyCode as CerVerifyCodeType, type CertifyAndAttestRunOptions, type CertifyAndAttestRunResult, CertifyDecisionParams, type CheckStatus, CreateSnapshotParams, type ExportVerifiableRedactedOptions, type ExportVerifiableRedactedProvenance, type ExportVerifiableRedactedResult, type MakeToolEventParams, NodeKeysDocument, NodeReceiptVerifyResult, type ProfileValidationResult, ReasonCode, ReasonCode as ReasonCodeType, type RedactBeforeSealPolicy, RunBuilder, RunBuilderOptions, RunSummary, RunSummaryVerifyResult, SanitizeStorageOptions, SignedAttestationReceipt, StepParams, ToolEvent, VerificationResult, type VerificationStatus, type VerifyRunSummaryOptions, attest, attestIfNeeded, certifyAndAttestDecision, certifyAndAttestRun, certifyDecision, certifyDecisionFromProviderCall, computeInputHash, computeOutputHash, createClient, createSnapshot, exportCer, exportVerifiableRedacted, fetchNodeKeys, getAttestationReceipt, hasAttestation, hashCanonicalJson, hashToolOutput, hashUtf8, importCer, makeToolEvent, mapToAiefReason, redactBeforeSeal, sanitizeForAttestation, sanitizeForStamp, sanitizeForStorage, sealCer, selectNodeKey, sha256Hex, toCanonicalJson, validateProfile, verifyCer as verify, verifyAiCerBundleDetailed, verifyAief, verifyBundleAttestation, verifyCer, verifyNodeReceiptSignature, verifyRunSummary, verifySnapshot };
|
package/dist/index.mjs
CHANGED
|
@@ -114,7 +114,7 @@ function computeOutputHash(output) {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
// src/snapshot.ts
|
|
117
|
-
var PACKAGE_VERSION = "0.
|
|
117
|
+
var PACKAGE_VERSION = "0.8.0";
|
|
118
118
|
function validateParameters(params) {
|
|
119
119
|
const errors = [];
|
|
120
120
|
if (typeof params.temperature !== "number" || !Number.isFinite(params.temperature)) {
|
|
@@ -382,7 +382,7 @@ function certifyDecision(params) {
|
|
|
382
382
|
conversationId: params.conversationId,
|
|
383
383
|
prevStepHash: params.prevStepHash
|
|
384
384
|
});
|
|
385
|
-
return sealCer(snapshot, { meta: params.meta });
|
|
385
|
+
return sealCer(snapshot, { createdAt: params.createdAt, meta: params.meta });
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
// src/run.ts
|
|
@@ -2410,14 +2410,149 @@ function validateProfile(target, profile) {
|
|
|
2410
2410
|
}
|
|
2411
2411
|
return { ok: errors.length === 0, errors };
|
|
2412
2412
|
}
|
|
2413
|
+
|
|
2414
|
+
// src/exportRedacted.ts
|
|
2415
|
+
function exportVerifiableRedacted(bundle, policy, options) {
|
|
2416
|
+
const createdAt = options?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2417
|
+
const redactedSnapshot = redactBeforeSeal(bundle.snapshot, policy);
|
|
2418
|
+
const provenance = {
|
|
2419
|
+
originalCertificateHash: bundle.certificateHash,
|
|
2420
|
+
redactionPolicy: { paths: [...policy.paths] },
|
|
2421
|
+
redactedAt: createdAt
|
|
2422
|
+
};
|
|
2423
|
+
const mergedMeta = {
|
|
2424
|
+
...bundle.meta,
|
|
2425
|
+
provenance
|
|
2426
|
+
};
|
|
2427
|
+
const newBundle = sealCer(redactedSnapshot, {
|
|
2428
|
+
createdAt,
|
|
2429
|
+
meta: mergedMeta,
|
|
2430
|
+
declaration: bundle.declaration
|
|
2431
|
+
});
|
|
2432
|
+
return {
|
|
2433
|
+
bundle: newBundle,
|
|
2434
|
+
originalCertificateHash: bundle.certificateHash
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// src/runHelper.ts
|
|
2439
|
+
async function certifyAndAttestRun(steps, options) {
|
|
2440
|
+
const run = new RunBuilder({
|
|
2441
|
+
runId: options?.runId,
|
|
2442
|
+
workflowId: options?.workflowId,
|
|
2443
|
+
conversationId: options?.conversationId,
|
|
2444
|
+
appId: options?.appId
|
|
2445
|
+
});
|
|
2446
|
+
const stepBundles = [];
|
|
2447
|
+
const receipts = [];
|
|
2448
|
+
for (const stepParams of steps) {
|
|
2449
|
+
const bundle = run.step(stepParams);
|
|
2450
|
+
stepBundles.push(bundle);
|
|
2451
|
+
if (options?.attestStep) {
|
|
2452
|
+
const receipt = await options.attestStep(bundle);
|
|
2453
|
+
receipts.push(receipt);
|
|
2454
|
+
} else {
|
|
2455
|
+
receipts.push(null);
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
const runSummary = run.finalize();
|
|
2459
|
+
return {
|
|
2460
|
+
runSummary,
|
|
2461
|
+
stepBundles,
|
|
2462
|
+
receipts,
|
|
2463
|
+
finalStepHash: runSummary.finalStepHash
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
// src/cerProtocol.ts
|
|
2468
|
+
var ReasonCode = {
|
|
2469
|
+
BUNDLE_HASH_MISMATCH: "BUNDLE_HASH_MISMATCH",
|
|
2470
|
+
NODE_SIGNATURE_INVALID: "NODE_SIGNATURE_INVALID",
|
|
2471
|
+
NODE_SIGNATURE_MISSING: "NODE_SIGNATURE_MISSING",
|
|
2472
|
+
RECEIPT_HASH_MISMATCH: "RECEIPT_HASH_MISMATCH",
|
|
2473
|
+
SCHEMA_VERSION_UNSUPPORTED: "SCHEMA_VERSION_UNSUPPORTED",
|
|
2474
|
+
RECORD_NOT_FOUND: "RECORD_NOT_FOUND",
|
|
2475
|
+
BUNDLE_CORRUPTED: "BUNDLE_CORRUPTED"
|
|
2476
|
+
};
|
|
2477
|
+
|
|
2478
|
+
// src/verifyDetailed.ts
|
|
2479
|
+
function mapCerCodeToReasonCodes(cerCode) {
|
|
2480
|
+
switch (cerCode) {
|
|
2481
|
+
case CerVerifyCode.CERTIFICATE_HASH_MISMATCH:
|
|
2482
|
+
case CerVerifyCode.SNAPSHOT_HASH_MISMATCH:
|
|
2483
|
+
case CerVerifyCode.INPUT_HASH_MISMATCH:
|
|
2484
|
+
case CerVerifyCode.OUTPUT_HASH_MISMATCH:
|
|
2485
|
+
return [ReasonCode.BUNDLE_HASH_MISMATCH];
|
|
2486
|
+
case CerVerifyCode.SCHEMA_ERROR:
|
|
2487
|
+
return [ReasonCode.SCHEMA_VERSION_UNSUPPORTED];
|
|
2488
|
+
case CerVerifyCode.CANONICALIZATION_ERROR:
|
|
2489
|
+
case CerVerifyCode.UNKNOWN_ERROR:
|
|
2490
|
+
case CerVerifyCode.INVALID_SHA256_FORMAT:
|
|
2491
|
+
return [ReasonCode.BUNDLE_CORRUPTED];
|
|
2492
|
+
case CerVerifyCode.ATTESTATION_INVALID_SIGNATURE:
|
|
2493
|
+
case CerVerifyCode.ATTESTATION_KEY_FORMAT_UNSUPPORTED:
|
|
2494
|
+
case CerVerifyCode.ATTESTATION_KEY_NOT_FOUND:
|
|
2495
|
+
return [ReasonCode.NODE_SIGNATURE_INVALID];
|
|
2496
|
+
case CerVerifyCode.ATTESTATION_MISSING:
|
|
2497
|
+
return [ReasonCode.NODE_SIGNATURE_MISSING];
|
|
2498
|
+
default:
|
|
2499
|
+
return [];
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
function verifyAiCerBundleDetailed(bundle) {
|
|
2503
|
+
const verifiedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2504
|
+
const verifier = "@nexart/ai-execution";
|
|
2505
|
+
if (!bundle || typeof bundle !== "object" || Array.isArray(bundle)) {
|
|
2506
|
+
return {
|
|
2507
|
+
status: "FAILED",
|
|
2508
|
+
checks: { bundleIntegrity: "FAIL", nodeSignature: "SKIPPED", receiptConsistency: "SKIPPED" },
|
|
2509
|
+
reasonCodes: [ReasonCode.BUNDLE_CORRUPTED],
|
|
2510
|
+
certificateHash: "",
|
|
2511
|
+
bundleType: "",
|
|
2512
|
+
verifiedAt,
|
|
2513
|
+
verifier
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
const b = bundle;
|
|
2517
|
+
const bundleType = typeof b["bundleType"] === "string" ? b["bundleType"] : "";
|
|
2518
|
+
const certificateHash = typeof b["certificateHash"] === "string" ? b["certificateHash"] : "";
|
|
2519
|
+
if (bundleType !== "cer.ai.execution.v1") {
|
|
2520
|
+
return {
|
|
2521
|
+
status: "FAILED",
|
|
2522
|
+
checks: { bundleIntegrity: "FAIL", nodeSignature: "SKIPPED", receiptConsistency: "SKIPPED" },
|
|
2523
|
+
reasonCodes: [ReasonCode.SCHEMA_VERSION_UNSUPPORTED],
|
|
2524
|
+
certificateHash,
|
|
2525
|
+
bundleType,
|
|
2526
|
+
verifiedAt,
|
|
2527
|
+
verifier
|
|
2528
|
+
};
|
|
2529
|
+
}
|
|
2530
|
+
const cerResult = verifyCer(bundle);
|
|
2531
|
+
const bundleIntegrity = cerResult.ok ? "PASS" : "FAIL";
|
|
2532
|
+
const attestationPresent = hasAttestation(bundle);
|
|
2533
|
+
const nodeSignature = attestationPresent ? "PASS" : "SKIPPED";
|
|
2534
|
+
const receiptConsistency = attestationPresent ? "PASS" : "SKIPPED";
|
|
2535
|
+
const reasonCodes = cerResult.ok ? [] : mapCerCodeToReasonCodes(cerResult.code);
|
|
2536
|
+
return {
|
|
2537
|
+
status: cerResult.ok ? "VERIFIED" : "FAILED",
|
|
2538
|
+
checks: { bundleIntegrity, nodeSignature, receiptConsistency },
|
|
2539
|
+
reasonCodes,
|
|
2540
|
+
certificateHash,
|
|
2541
|
+
bundleType,
|
|
2542
|
+
verifiedAt,
|
|
2543
|
+
verifier
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2413
2546
|
export {
|
|
2414
2547
|
CerAttestationError,
|
|
2415
2548
|
CerVerificationError,
|
|
2416
2549
|
CerVerifyCode,
|
|
2550
|
+
ReasonCode,
|
|
2417
2551
|
RunBuilder,
|
|
2418
2552
|
attest,
|
|
2419
2553
|
attestIfNeeded,
|
|
2420
2554
|
certifyAndAttestDecision,
|
|
2555
|
+
certifyAndAttestRun,
|
|
2421
2556
|
certifyDecision,
|
|
2422
2557
|
certifyDecisionFromProviderCall,
|
|
2423
2558
|
computeInputHash,
|
|
@@ -2425,6 +2560,7 @@ export {
|
|
|
2425
2560
|
createClient,
|
|
2426
2561
|
createSnapshot,
|
|
2427
2562
|
exportCer,
|
|
2563
|
+
exportVerifiableRedacted,
|
|
2428
2564
|
fetchNodeKeys,
|
|
2429
2565
|
getAttestationReceipt,
|
|
2430
2566
|
hasAttestation,
|
|
@@ -2444,6 +2580,7 @@ export {
|
|
|
2444
2580
|
toCanonicalJson,
|
|
2445
2581
|
validateProfile,
|
|
2446
2582
|
verifyCer as verify,
|
|
2583
|
+
verifyAiCerBundleDetailed,
|
|
2447
2584
|
verifyAief,
|
|
2448
2585
|
verifyBundleAttestation,
|
|
2449
2586
|
verifyCer,
|