nexart.iodocs

    Project Bundle Registration

    Registration turns a locally verified bundle into a publicly verifiable artifact on verify.nexart.io.

    When to use registration

    Use when

    • Multiple steps or agents
    • Workflow-level public verification
    • External auditor must resolve without your SDK
    • Node-signed receipt required as trust anchor

    Skip when

    • Single execution (use Path A + /api/attest)
    • Independent decisions, not a workflow
    • Internal-only audit trail, never resolved publicly

    The three verification layers

    These are distinct and not interchangeable. A bundle can pass one and still need the next.

    1. Local SDK verification. verifyProjectBundle(bundle) recomputes hashes and checks step integrity against the bundle's own contents. It proves the artifact has not been modified since it was produced.
    2. Node registration. POST /v1/project-bundle/register persists the bundle in the node's proof tables and returns a signed receipt. This is the trust anchor for any third party.
    3. Public verification. verify.nexart.io/p/{projectHash} resolves the registered bundle and re-runs verification against the node's stored copy. Anyone with the projectHash can verify, without your code or your SDK.

    Minimal end-to-end flow

    import {
      certifyDecision,
      createProjectBundle,
      verifyProjectBundle,
      registerProjectBundle,
    } from "@nexart/ai-execution";
    
    // 1. Produce step CERs (each step is its own verifiable record).
    const stepA = await certifyDecision({ /* step A inputs */ });
    const stepB = await certifyDecision({ /* step B inputs */ });
    
    // 2. Group steps into a Project Bundle (computes projectHash).
    const bundle = await createProjectBundle({
      projectId: "workflow-123",
      steps: [stepA.cer, stepB.cer],
    });
    
    // 3. Local verification - integrity only.
    const local = await verifyProjectBundle(bundle);
    if (!local.ok) throw new Error("Bundle is not internally consistent");
    
    // 4. Register on the node - REQUIRED for public verification.
    const reg = await registerProjectBundle(bundle, {
      apiKey: process.env.NEXART_API_KEY!,
    });
    
    console.log("Public URL:", `https://verify.nexart.io/p/${reg.projectHash}`);

    Successful registration response

    {
      "ok": true,
      "projectHash": "sha256:7d4a...e91",
      "registeredAt": "2026-04-21T12:00:00Z",
      "receipt": {
        "alg": "Ed25519",
        "kid": "node-key-2026-01",
        "sig": "base64..."
      }
    }

    What the registration helper does

    • POSTs the canonical bundle JSON to /v1/project-bundle/register.
    • Authenticates with your NEXART_API_KEY.
    • Receives a node-signed receipt over the bundle's projectHash.
    • Is idempotent: re-registering the same bundle returns the existing record.

    Failure modes

    For a complete catalogue of node responses and what to do about them, see Verification Statuses & Errors. The most common ones at registration time:

    • HASH_MISMATCH - the recomputed projectHash does not match the value in the submitted bundle. Usually caused by non-canonical JSON (extra whitespace, undefined values, key reordering).
    • PERSISTENCE_FAILED - node accepted the request but could not write to its proof tables. Retry with backoff; the operation is idempotent on projectHash.
    • AUTH_INVALID - missing or rejected API key.

    Related