AI Execution Verification

    Verify Certified Execution Records independently. No API key, no account, no trust in NexArt required.

    Minimum Integration, 3 Steps

    1. Load, Parse the CER bundle JSON (use importCer(json) or JSON.parse).
    2. Verify locally, Call verify(bundle) to check certificate hash and snapshot hashes.
    3. Verify stamp, If a signed receipt is present, call verifyBundleAttestation(bundle, { nodeUrl }).

    Local Integrity Verification

    Local verification re-computes all hashes from the bundle's data and compares them to the recorded values. No network call is needed. This works entirely offline.

    import { verify } from '@nexart/ai-execution';
    // or for Code Mode:
    // import { verify } from '@nexart/codemode-sdk';
    
    const bundle = JSON.parse(fs.readFileSync('record.cer.json', 'utf8'));
    const result = verify(bundle);
    
    if (result.ok) {
      console.log('✓ Record intact, hashes match');
    } else {
      console.log('✗ Integrity breach:', result.code);
      console.log('  Reason:', result.details?.reason);
      console.log('  Expected:', result.details?.expected);
      console.log('  Actual:', result.details?.actual);
    }

    What gets checked:

    • certificateHash, SHA-256 of canonical JSON of { bundleType, version, createdAt, snapshot }
    • inputHash, SHA-256 of the input field
    • outputHash, SHA-256 of the output field
    • Schema validity, correct bundleType, version, required fields present

    Node Stamp Verification

    If the bundle includes a signed receipt (from a canonical attestation node), you can verify the Ed25519 signature offline. The only network call is fetching the node's public keys from /.well-known/nexart-node.json, verifyBundleAttestation does not call /api/attest or submit anything to the node.

    import { verifyBundleAttestation } from '@nexart/ai-execution';
    
    const result = await verifyBundleAttestation(bundle, {
      nodeUrl: 'https://nexart-canonical-renderer-production.up.railway.app',
    });
    
    console.log(result.ok);   // true or false
    console.log(result.code); // "OK", "ATTESTATION_INVALID_SIGNATURE", etc.
    
    // Detailed mismatch info (when result.ok is false):
    console.log(result.details);
    // { reason: "signature_mismatch", kid: "key-2025-01", ... }

    This performs the following automatically:

    1. Extracts the signed receipt and signature from the bundle
    2. Cross-checks receipt.certificateHash === bundle.certificateHash (prevents receipt-swapping)
    3. Fetches the node's public keys from /.well-known/nexart-node.json
    4. Selects the correct key by kid or activeKid
    5. Verifies the Ed25519 signature over the canonical JSON bytes of the receipt

    Browser vs Server Verification

    EnvironmentSHA-256Ed25519Notes
    BrowserWebCrypto (crypto.subtle.digest)SDK verifier (@noble/ed25519)No native Ed25519 in WebCrypto; SDK bundles a pure-JS verifier
    Node.jscrypto.createHash@noble/ed25519 or built-in crypto.verifySDK uses noble by default; may use built-in crypto when available

    The SDK handles this automatically. verify() and verifyBundleAttestation() work in both environments without configuration.

    Recânon: For a zero-setup browser verification experience, upload your CER JSON to recanon.xyz. Verification runs entirely in your browser. No data is sent to any server.

    What "Stamp Incomplete" Means

    A bundle may have been attested but lack the full signed receipt fields introduced in v0.5.0. This is not an error, it means the bundle was attested under an earlier SDK version.

    Fields PresentStatusWhat You Can Verify
    receipt + signature + attestorKeyIdFully signedLocal integrity + node signature
    attestationId + nodeRuntimeHash (no signature)Legacy attestationLocal integrity only
    No attestation fieldsNot attestedLocal integrity only

    Legacy stamp fields may appear either at the top level of the bundle or nested under meta.attestation, depending on the producer. The SDK's getAttestationReceipt() normalizes both locations automatically.

    verifyBundleAttestation() returns ATTESTATION_MISSING when no signed receipt is found. This does not invalidate the bundle itself. Local integrity can still pass.

    Verification semantics

    • status: "verified" means integrity match only. It does not imply that a signature was verified.
    • checks.signature must equal "pass" for authenticity.
    • Unsigned bundles may still return "verified", integrity passed, no signed receipt was present.
    • verifyCer() provides classification; the node recomputes verification independently and aligns with the SDK classification.

    Trust boundaries

    • Integrity, fully independent. Bundle + SHA-256 + matching canonicalisation is sufficient.
    • Authenticity, depends on trust in the binding between the public key and the node operator.
    • Timestamp, two layers: a node-issued timestamp providing an ordering guarantee within the node's signing chain, and an RFC 3161 timestamp issued via DigiCert's public timestamp authority (applied by default) providing an independent anchor of when the record existed.
    • Transparency, internal to the node today; no public Merkle log or third-party inclusion proof.
    • Completeness, not enforced by the substrate; ensuring every relevant execution is submitted is an integration-level responsibility.

    Stranger verification (no NexArt code)

    A third party can verify a CER with only the bundle JSON, the node's published public key, and standard crypto libraries:

    1. Recompute certificateHash = SHA-256 of the canonical JSON of { bundleType, version, createdAt, snapshot, context?, contextSummary?, policyEvaluation? }.
    2. Reconstruct the signable payload by canonicalising the receipt object, and cross-check receipt.certificateHash matches the bundle.
    3. Verify the Ed25519 signature with any standard library, using the public key from /.well-known/nexart-node.json selected by kid.

    Verification uses protocol-pinned canonicalisation: nexart-v1 for Protocol 1.2.0, RFC 8785 (JCS) for Protocol 1.3.0. You are not required to trust NexArt's implementation, Protocol 1.3.0 enables verification using a public standard (RFC 8785) and standard Ed25519 libraries.

    Fix: Re-attest the bundle with a current node to obtain receipt + signature + kid.