nexart.iodocs

    Getting Started

    Pick the path that matches your use case: a single execution CER, or a multi-step Project Bundle.

    Start here. This is the canonical NexArt integration model.

    NexArt Integration (Canonical Flow)

    Flow:

    1. Capture execution input
    2. Seal locally (offline)
    3. Verify locally
    4. (Optional) Certify via node
    5. Verify again

    Verification outcomes:

    • Sealed → Integrity: PASS, Receipt: SKIPPED, Envelope: SKIPPED
    • Certified → Integrity: PASS, Receipt: PASS, Envelope: PASS

    Rules:

    • Sealing does NOT require a node
    • Certification is OPTIONAL
    • Verification does NOT require trust
    • SKIPPED is expected for local artifacts and is NOT a failure

    Do NOT:

    • call the node before sealing
    • recompute hashes manually
    • modify bundles after sealing
    • treat SKIPPED as failure

    Start here

    The recommended path. Follow these four steps in order.

    1. 1
      Run the minimal example
      Copy one script, set two environment variables, and produce your first certified record.
      Open the Quickstart →
    2. 2
      Understand what was created
      Read the canonical reference: how the record is built, what is hashed, and how it is verified.
      Read the Architecture →
    3. 3
      Integrate into your system
      Wire NexArt into your application using the official SDK reference.
      Open the SDK reference →
    4. 4
      Verify your first record
      Confirm the record is intact and independently verifiable.
      Open the Verification guide →

    Technical truth

    What a CER is
    A Certified Execution Record (CER) is a canonical, tamper-evident bundle representing one execution. It has bundleType: "cer.ai.execution.v1", a version, a createdAt ISO-8601 timestamp, a snapshot (model, inputHash, outputHash, metadata), and an optional context / contextSummary. The CER is identified by its certificateHash (SHA-256). Inputs and outputs are stored as hashes; raw payloads are not part of the bundle.
    Fields covered by certificateHash (whitelist)
    The hash is computed using JCS canonicalization (RFC 8785) over a strict whitelist projection:bundleType, version, createdAt, snapshot, and (only when present) context, contextSummary. Any modification to a covered field changes the hash.
    Fields excluded from hashing
    The following are explicitly excluded from the hash payload and may be added, updated, or removed without invalidating the certificateHash: certificateHash itself, meta (including meta.attestation and the receipt), declaration, verificationEnvelope, verificationEnvelopeSignature, receipt, and any unknown fields not in the whitelist. Verifiers MUST apply the whitelist projection to the bundle as received; no reconstruction or normalization beyond JCS.
    The three verification layers
    • certificateHash (integrity) — recompute SHA-256 over the JCS-canonicalized whitelist projection and compare with the bundle's certificateHash.
    • receipt signature (node attestation) — validate the Ed25519 receipt at meta.attestation using the node key matched by kid, and confirm it references the bundle's certificateHash.
    • verification envelope (full bundle signature, v0.16.1) — validate meta.verificationEnvelopeSignature against meta.verificationEnvelope. When absent, this layer returns SKIPPED.

    Each layer reports independently as PASS, FAIL, or SKIPPED. Verification statuses: VERIFIED, FAILED, NOT_FOUND.

    Independence model: local sealing, optional node certification, independent verification

    Local sealing — produced by the SDK (@nexart/ai-execution@0.16.1 via sealCer()) or the CLI (@nexart/cli@0.8.0 via nexart ai seal). Builds a canonical CER bundle and computes the certificateHash fully offline. No API key, no network call, no receipt, no verification envelope. The result is a sealed bundle: integrity only.

    Optional node certification — performed by the attestation node (POST /v1/cer/ai/certify / nexart ai certify). The node validates the bundle and issues an Ed25519-signed receipt (identified by kid) referencing the bundle's certificateHash, plus a verification envelope. Receipt and signatures are stored at bundle.meta.attestation and meta.verificationEnvelope. Certification adds attestation layers; it does not change the certificateHash. The result is a certified bundle.

    Independent verification — performed by anyone, with no trust in NexArt infrastructure required. Available via verify.nexart.io, the SDK, or the CLI. The bundle plus the node's published public keys are sufficient. For sealed bundles, only Layer 1 (integrity) is applicable; Layers 2 and 3 return SKIPPED. For certified bundles, all three layers return PASS.

    Verify Your First Certified Execution (2 minutes)
    Copy this script, set two environment variables, run it. If you see three PASS lines, NexArt is working end-to-end. No abstractions, no helpers, no partial snippets.
    1. Install
    npm install @nexart/ai-execution
    export NEXART_NODE_URL="https://node.nexart.io"
    export NEXART_API_KEY="<your-api-key>"
    2. test-harness.ts (single file, copy as-is)
    import {
      certifyLangChainRun,
      verifyAiCerBundleDetailed,
    } from "@nexart/ai-execution";
    
    async function main() {
      // Create + certify in one node round-trip.
      const { bundle, certificateHash, verificationUrl } = await certifyLangChainRun({
        provider: "openai",
        model: "gpt-4o-mini",
        input:  { messages: [{ role: "user", content: "Should this refund be approved?" }] },
        output: { decision: "approve", reason: "policy_passed" },
        nodeUrl: process.env.NEXART_NODE_URL!,
        apiKey:  process.env.NEXART_API_KEY!,
      });
    
      console.log("certificateHash :", certificateHash);
      console.log("verificationUrl :", verificationUrl);
    
      // Independent verification of the returned bundle. No trust required.
      const report = await verifyAiCerBundleDetailed(bundle);
    
      console.log("Integrity (Layer 1) :", report.integrity);
      console.log("Receipt   (Layer 2) :", report.receipt);
      console.log("Envelope  (Layer 3) :", report.envelope);
    }
    
    main().catch((err) => {
      console.error("FAILED:", err);
      process.exit(1);
    });
    3. Run
    npx tsx test-harness.ts
    Expected output (success)
    certificateHash : sha256:9f2b1c8e4a7d6f3b0c5e8a1d2f4b6c8e9a0d3f5b7c2e4a6d8f1b3c5e7a9d0f2b
    verificationUrl : https://verify.nexart.io/c/sha256:9f2b1c8e4a7d6f3b0c5e8a1d2f4b6c8e9a0d3f5b7c2e4a6d8f1b3c5e7a9d0f2b
    Integrity (Layer 1) : PASS
    Receipt   (Layer 2) : PASS
    Envelope  (Layer 3) : PASS

    Three PASS lines mean the bundle is byte-identical to what the node attested, the receipt signature validates against the node key, and the verification envelope binds the attestation projection to the bundle.

    Expected verification result — Sealed bundle (local, offline)
    integrity
    : PASS
    receipt
    : SKIPPED
    envelope
    : SKIPPED

    Produced by nexart ai seal or the SDKsealCer(). No node call, no API key.

    Expected verification result — Certified bundle (node-attested)
    integrity
    : PASS
    receipt
    : PASS
    envelope
    : PASS

    Produced by nexart ai certify or the SDKcertifyLangChainRun(). Node returns receipt + envelope.

    If any layer returns FAIL, the integration is incorrect. SKIPPED is expected for local (sealed) artifacts and MUST NOT be treated as a failure.

    If something fails
    • Integrity FAIL (Layer 1)
      Payload mismatch. The recomputed certificateHash does not match the bundle. Cause: the bundle was mutated, re-serialized with a different canonicalization, or the version field was changed. The bundle MUST be persisted byte-for-byte after certification.
    • Receipt FAIL (Layer 2)
      Node or auth issue. The receipt signature did not validate against the node key. Cause: wrong NEXART_NODE_URL, missing or invalid NEXART_API_KEY, or the node key published at /.well-known/nexart-node.json does not match the receipt kid.
    • Envelope FAIL (Layer 3)
      Bundle mutation after attestation. The envelope signature covers a 5-field attestation projection (attestationId, attestedAt, kid, nodeRuntimeHash, protocolVersion). If any of those fields were altered or stripped, the envelope cannot validate. Do not modify meta.attestation after sealing.
    Mental model
    • Logs describe. CERs prove.
    • Integrity ≠ Stamp ≠ Envelope.
    • Verification does not require trust.

    Quick Implementation Flow

    Four steps. Each has a single responsibility. Following them in order produces a record anyone can verify without trusting your infrastructure.

    Quick Implementation Flow
    The four steps required to integrate NexArt correctly. Each step has a single responsibility.
    1. Step 1Capture execution
      What: Record the model, input, output, and any structured signals.
      Why: The certificateHash is computed from this data. Capture must happen before sealing.
      @nexart/signals · createContext() (optional) → passed into createLangChainCer(...)
    2. Step 2Create CER
      What: Build a CER bundle and compute certificateHash over the strict whitelist (JCS).
      Why: The hash is the canonical identity of the record. It binds the bundle to its content.
      createLangChainCer(...) · or sealCer(bundle) for manual sealing
    3. Step 3Certify via node
      What: Submit the bundle to the attestation node. Receive a signed receipt and verification envelope.
      Why: The node provides an independent witness and a public verification surface.
      POST /v1/cer/ai/certify
    4. Step 4Verify independently
      What: Anyone can re-derive certificateHash, validate the receipt signature, and validate the envelope.
      Why: Verification requires no trust in your infrastructure or the node beyond its published key.
      verifyAiCerBundleDetailed(bundle) · or https://verify.nexart.io/c/{certificateHash}
    Deeper reference: Verification · Verification Layers · Hashes

    Minimal working example

    One execution, one CER, one certification, one verification. This is the canonical example reused across the docs.

    How the SDK is split
    • Creation is local and deterministic. It produces a bundle and a certificateHash. No network call.
    • Certification is node-based. It returns a signed receipt, a verification envelope, and a public verificationUrl.
    • verificationUrl exists ONLY after certification. It is not produced by local creation.
    Flow A - Certified execution (recommended)
    import {
      certifyLangChainRun,
      verifyAiCerBundleDetailed,
    } from "@nexart/ai-execution";
    
    // Steps 1-3: capture execution, create the CER, certify via the node.
    // certifyLangChainRun is async because it contacts the attestation node.
    const { bundle, certificateHash, verificationUrl } = await certifyLangChainRun({
      provider: "openai",
      model: "gpt-4o-mini",
      input:  { messages: [{ role: "user", content: "Should this refund be approved?" }] },
      output: { decision: "approve", reason: "policy_passed" },
      nodeUrl: process.env.NEXART_NODE_URL!,
      apiKey:  process.env.NEXART_API_KEY!,
    });
    
    console.log(certificateHash);   // sha256:...
    console.log(verificationUrl);   // https://verify.nexart.io/c/{certificateHash}
    
    // Step 4: independent verification. No trust in your infrastructure required.
    const report = await verifyAiCerBundleDetailed(bundle);
    // report.integrity -> PASS  (Layer 1: certificateHash recomputed from snapshot)
    // report.receipt   -> PASS  (Layer 2: node signature over the receipt)
    // report.envelope  -> PASS  (Layer 3: envelope signature over the attestation projection)
    
    Flow B - Local-only execution (no node interaction)
    import { createLangChainCer } from "@nexart/ai-execution";
    
    // createLangChainCer is synchronous and deterministic.
    // It produces a valid CER bundle and certificateHash WITHOUT contacting the node.
    // There is no receipt, no envelope, and no verificationUrl in this flow.
    const { bundle, certificateHash } = createLangChainCer({
      provider: "openai",
      model: "gpt-4o-mini",
      input:  { messages: [{ role: "user", content: "Should this refund be approved?" }] },
      output: { decision: "approve", reason: "policy_passed" },
    });
    
    console.log(certificateHash);   // sha256:...
    // To obtain a signed receipt and a public verificationUrl, submit the bundle
    // to the node (see Flow A) or POST it to /v1/cer/ai/certify.
    

    What NexArt Does

    NexArt creates Certified Execution Records (CERs), cryptographically bound records of AI or deterministic execution that can be independently verified.

    Every CER produces a deterministic certificateHash. That hash is the canonical identity of the record. Optional node attestation produces a signed receipt so anyone can verify the record without trusting your infrastructure.

    Two Integration Paths

    NexArt supports both single-execution certification and multi-step workflow certification. Pick the one that matches your use case. You do not need Project Bundles for every integration.

    Path A - Single CER
    One execution, one verifiable record.
    • Run the execution
    • Seal a CER locally (sealCer()) — offline, no API key
    • Verify locally (integrity PASS, receipt & envelope SKIPPED)
    • Optional: certify via node and share /c/{certificateHash}
    Path B - Project Bundle
    Multi-step or multi-agent workflows verified as a unit.
    • Create a CER per step
    • Assemble a Project Bundle
    • Register the bundle on the node
    • Verify publicly at verify.nexart.io

    Install the SDK

    npm install @nexart/ai-execution

    Current version: @nexart/ai-execution@0.16.1.

    Path A: Seal a Single CER

    The simplest integration. One execution produces one verifiable record. Sealing is fully offline — no API key, no network call.

    Seal a Single CER (offline)
    import { sealCer, verifyAiCerBundleDetailed } from "@nexart/ai-execution";
    
    const { bundle, certificateHash } = sealCer({
      provider: "openai",
      model: "gpt-4o-mini",
      input: {
        messages: [{ role: "user", content: "What is 2 + 2?" }]
      },
      output: {
        text: "4"
      }
    });
    
    console.log(certificateHash);
    
    const report = await verifyAiCerBundleDetailed(bundle);
    // report.integrity === "PASS"
    // report.receipt   === "SKIPPED"  (no node attestation yet)
    // report.envelope  === "SKIPPED"  (no envelope yet)

    The certificateHash is the canonical identity of the record. To make the bundle independently verifiable end-to-end (Layers 2 and 3 PASS), submit it to the attestation node via certifyLangChainRun() or POST /v1/cer/ai/certify. The certificateHash does not change.

    Note: executionId is not a unique artifact identifier. Always look up records by certificateHash.

    Path B: Workflow with a Project Bundle

    For multi-step or multi-agent workflows, certify each step as its own CER and group them into a Project Bundle. The bundle has its own projectHash covering all step certificateHash values.

    Linear workflow with @nexart/agent-kit
    import { startWorkflow } from "@nexart/agent-kit";
    
    const workflow = startWorkflow({ projectTitle: "Contract review" });
    
    const clauses = await workflow.step("Extract clauses", async () => {
      return await llm.call("Extract key clauses...");
    });
    
    const risks = await workflow.step("Summarize risks", async () => {
      return await llm.call("Summarize risks from: " + clauses);
    });
    
    const bundle = workflow.finish();
    // bundle.integrity.projectHash is the verifiable hash

    For public verification on verify.nexart.io, the bundle must be registered on the node. See End-to-End Verification for the full registration flow.

    Verify the Record

    Verification can be performed independently. Open https://verify.nexart.io and paste the certificateHash, or open the URL directly:

    https://verify.nexart.io/c/{certificateHash}

    Official Example Repos

    Common mistakes

    Common Mistakes
    Verified failure patterns observed in real integrations. Avoid these to prevent verification errors.
    • Wrong: Setting version: "1.0" on the bundle
      Right: Use version: "0.1" (matches cer.ai.execution.v1).
      Why: An incorrect version changes the canonical projection and breaks certificateHash recomputation.
    • Wrong: Hashing the full bundle (including meta.attestation, signature, receipt)
      Right: Hash only the strict whitelist: bundleType, version, createdAt, snapshot, context, contextSummary (JCS).
      Why: meta and attestation are added after sealing. Hashing them produces a different, non-verifiable hash.
    • Wrong: Trying to verify the Verification Envelope from a publicly redacted record
      Right: Layer 3 envelope verification requires the full attestation projection. Redacted public payloads support Layer 1 and Layer 2 only.
      Why: Envelope signature covers a 5-field projection that may be removed by redaction.
    • Wrong: Mutating the bundle after certification (re-ordering keys, adding fields, normalizing dates)
      Right: Treat the certified bundle as immutable. Persist it byte-for-byte.
      Why: Any mutation invalidates certificateHash and the receipt. The node enforces EXECUTION_MUTATION_DETECTED (409) on resubmit.
    • Wrong: Looking up records by executionId
      Right: Always look up by certificateHash. executionId is not a unique artifact identity.
      Why: Two attempts of the same execution can share an executionId but produce different certificateHashes.

    What happens if it fails

    What happens if verification fails
    Each verification layer fails for a different, specific reason. Isolating the failed layer tells you exactly what went wrong.
    LayerFailureMeaningAction
    Layer 1 — IntegritycertificateHash mismatchThe bundle was modified after sealing, or the wrong projection was hashed.Re-derive certificateHash with sealCer(...) over the strict whitelist. If it still differs, the stored bundle is no longer authentic.
    Layer 2 — Signed ReceiptReceipt signature invalidThe receipt was not produced by the published node key, or the receipt payload was modified.Refetch the node key set from /.well-known/nexart-node.json. If signature still fails, the receipt is not trustworthy.
    Layer 3 — Verification EnvelopeEnvelope signature invalid or projection mismatchThe envelope payload (5-field attestation projection) does not match what was signed, or the kid is wrong.Confirm the bundle includes meta.verificationEnvelope and meta.verificationEnvelopeSignature. Public/redacted payloads cannot satisfy Layer 3.
    NodeEXECUTION_MUTATION_DETECTED (409)An execution_id already maps to a different certificateHash. The node rejects mutation by design.Do not re-submit modified bundles under the same execution_id. Create a new execution.

    Next Steps