Post Oak Labs · Open Specification

How OpenChainGraph works

Decision tools produce artifacts. Artifacts carry a fingerprint of their inputs and outputs. Each artifact can cite the fingerprints of the artifacts it consumed, forming a verifiable, tamper-evident provenance chain. v0.2 adds W3C PROV-DM semantic context, buildType URI, in-toto envelopes, Ed25519 signing, and OpenTelemetry span mapping. v0.3 adds ISO 20022 payload alignment, LEI & did:key party identity, and an OKF companion bundle. v0.3.1 formalizes profile conformance via dereferenceable dct:conformsTo URIs. v0.4 adds Compute Binding (gpu:false kernels run server-side in a single MCP round-trip) and Export Profiles (chaingraph_export generates xlsx, pdf, csv, xbrl, and vc renderings downstream of a fixed execution_hash). v0.5 adds Proof Binding (§16): an optional W3C Data Integrity proof (eddsa-jcs-2022) at audit_signature.proof that turns the artifact from tamper-evidence into authenticated attestation, default-off, holder-chosen, backward-compatible. v0.6 adds Kernel Identity Binding (§17): audit_signature.build_identity.kernel_digest, SHA-256 over the LF-normalised kernel source, cross-checked three ways against the Graph Index compute_images[], closing the gap that execution_hash proves some logic ran but not which. v0.6 also adds Compute-Integrity Proof (§18): an optional zkVM receipt (audit_signature.compute_proof, groth16-bn254 recommended) that turns the §4 hash from re-execute-to-verify into a succinct proof of correct execution, optionally without revealing inputs, software-only, no TEE, no chain. Any agent, anywhere, can re-run the math to confirm any link. No trusted authority required.

Before Stage 1, Foundation

First: what is a hash?

BeginnerNormative version: §4

OpenChainGraph is built on a concept called cryptographic hashing. Before diving into stages, you need to understand this one idea. Think of a hash as a digital fingerprint for any piece of data, a document, a number, a decision. Feed any data into a hash function (we use SHA-256) and it spits out a unique 64-character string.

Try it yourself, live SHA-256

Type anything below. Watch the 64-character fingerprint recompute with every keystroke. Then change a single character, even one space, and see the entire output transform.

SHA-256 output
,
Input
Apple
↓ SHA-256 ↓
f223faa96f22916294922b171a2696d868fd1f9129302eb41a45b2a2ea2ebbfd
Input, one character changed
apple
↓ SHA-256 ↓
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b

Changing one letter, just the capital A to lowercase, completely changed all 64 characters of the fingerprint. That's the key property: even the tiniest change produces a totally different hash. There's no "slightly different", it's all or nothing.

1
Same input = same output, always
Run SHA-256 on "Apple" a million times in a million different countries and you always get the same hash. This is called determinism.
2
Tiny change = completely different hash
One character difference flips the entire 64-character output. This means any tampering, even changing a single digit in a decision output, is immediately detectable.
3
It's one-way, you can't reverse it
Given only the hash, you cannot work backward to the original data. It's a fingerprint, not encryption. You can only verify by re-running the hash yourself.
For Everyone · No Jargon

Imagine you're submitting a group project

Beginner

Before the math and the JSON, here's the same idea explained with something you already know. Click each step to expand it.

1
You write a report and get it stamped
📝

You finish your history essay. Before handing it in, the teacher runs your paper through a machine that produces a unique 64-character code, your paper's fingerprint. If you change even one word after that, the machine produces a completely different code.

In OpenChainGraph: a decision tool runs a calculation and SHA-256 hashes its inputs + outputs. That hash is the fingerprint, the execution_hash.

execution_hash
2
Your teammate cites your work, and includes your stamp
🔗

Your teammate writes the next section of the group project. At the top of her section, she writes: "This builds on Roger's section, fingerprint: a3f9…". Now her work is linked to yours by your fingerprint code.

If anyone later tries to swap in a different version of your section, her fingerprint reference will no longer match, the tamper is caught instantly.

In OpenChainGraph: Tool B lists Tool A's execution_hash in its chain.parent_hashes array. The link is the hash, not a file name, not a URL.

chain.parent_hashes
3
The teacher verifies the whole chain, without trusting anyone
🔍

The teacher takes your section, re-runs it through the fingerprint machine, and checks: does the code match what your teammate wrote at the top of her section? If yes, your section is authentic, unmodified.

She then does the same for your teammate's section. She doesn't need to call you, email you, or trust any middleman. The math is the proof.

In OpenChainGraph: any agent or auditor re-hashes {policy_parameters, output_payload} and compares it to the stored execution_hash. Match = verified. No trusted authority required.

verify_execution_hash
4
A third student from another school joins, same rules, same trust
🌐

Now a student from a completely different school wants to cite your group's project in her own work. She doesn't know your teacher, your school, or your systems, but she can still verify the fingerprints herself. The fingerprint standard is public and open.

She cites your teammate's fingerprint in her bibliography. Now there's a three-link chain spanning two schools, zero phone calls, zero emails asking "can you confirm this is the right version?"

In OpenChainGraph: this is cross-vendor chaining. Two organizations that have never met can form a verifiable provenance chain by both following the same open hash specification.

x-chaingraph capability
The Bridge

Replace "history essay" with a credit risk score. Replace "teacher" with a bank regulator. Replace "student from another school" with a fintech vendor. The protocol is identical, and that's the point. OpenChainGraph is just the fingerprint standard, applied to financial decisions.

For Everyone · The Tamper Test

What happens when someone tries to cheat?

Beginner

The whole point of the fingerprint system is that you can't secretly change anything. Press the red button below to watch what happens when a bad actor tweaks just one number inside an artifact, even a tiny edit.

✓ chain intact, all hashes match
☠ After tampering

Changing even one byte of an artifact produces a completely different SHA-256 hash. Every downstream artifact that cited the old hash now holds a broken reference. The mismatch is instant and obvious, no investigation needed.

✓ Why this protects you

There's no central authority to bribe or fool. The math runs locally on any verifier's machine. A bad actor can't quietly edit a credit score, a risk rating, or a loan decision, any change detonates every downstream link in the chain.

For Everyone · Real World

You apply for a college loan, here's the full chain

Beginner

Four separate tools make four separate decisions, each one citing the hash of the one before it. Six months later, a regulator audits the loan. Watch the chain light up as each hash is verified, left to right, step by step.

📊
credit_assessment
Credit score tool
Pulls your payment history. Emits a score of 712 and an execution_hash. This is depth: 0, the starting point.
💰
affordability_check
Affordability tool
Takes the credit score artifact as input. Cites its hash in parent_hashes. Decides you can afford $850/month repayments.
⚖️
risk_control
Risk model tool
Cites both the credit and affordability artifacts. Assigns a risk band of Low. depth: 2, two links back to the origin.
loan_decision
Loan approval tool
Cites the risk model artifact. Approves the loan at 6.4% APR. depth: 3, the full chain of decisions is now locked in.
What the regulator sees six months later

The auditor re-runs SHA-256 on each artifact, in order. Every hash matches. That means no one altered the credit score, the affordability calculation, the risk rating, or the final decision between the day the loan was approved and today. The chain is the audit trail: no spreadsheets, no emails, no "trust me."

Stage 1 of 22

A decision tool runs and emits an artifact

BeginnerNormative version: §1

Every conformant tool takes structured inputs (policy_parameters), runs a deterministic computation, and produces outputs (output_payload). It then wraps inputs + outputs together into a JSON envelope and runs SHA-256 over the combined package. That hash, called the execution_hash, gets stamped onto the artifact before it's sent anywhere.

📌 Watch the animation: the document leaving the tool is labeled "raw result", it has no hash yet. It becomes a "JSON payload" in the artifact envelope. Only then does SHA-256 compute the fingerprint.
Tool runs → artifact built → SHA-256 stamps the execution_hash · animating live
🔧
Decision Tool
Deterministic compute
Same inputs always produce identical outputs. No timestamps or random numbers inside the hash preimage, those would make the hash different every second, breaking reproducibility.
📄
Artifact Envelope
The standard receipt
A JSON object wrapping the inputs (policy_parameters) and outputs (output_payload) together. Adding the execution_hash turns it into a verifiable record.
#️⃣
Execution Hash
SHA-256 of inputs + outputs
Computed over {"policy_parameters":…, "output_payload":…} with keys sorted alphabetically. Any party can re-run this exact procedure to verify the hash independently.
🏷️
Mandate Type
Classification of the decision
e.g. risk_control, liquidity_mandate, credit_assessment. Think of it like a category label, it tells downstream tools and agents what kind of decision this artifact represents.
{
  "@context": "https://ocg.postoaklabs.com/ns/v0.5",
  "chaingraph_version": "0.4.0",
  "buildType": "WebCryptoSHA256",
  "chain_depth": 2,
  "parent_hashes": ["sha256:3f9a…"],
  "policy_parameters": { "loan_amount": 45000, "rate": 6.4 },
  "output_payload": { "decision": "APPROVED", "score": 712 },
  "mandate_id": "urn:uuid:a1b2c3d4…",
  "compliance_flags": [],
  "audit_signature": {
    "execution_hash": "sha256:8e5a…",
    "signatures": […],
    "proof": {…}
  }
}
Stage 2 of 22

Artifacts cite each other, chains form

BeginnerNormative version: §1

When Tool B consumes the output of Tool A, it copies Tool A's execution_hash into its own chain.parent_hashes array. This single act creates a cryptographically linked chain. Tool C can cite both A and B. The result is a directed acyclic graph (DAG), like a family tree of decisions, where every connection is a hash reference that can be independently verified.

A named chain of steps like this is a workflow. Package a workflow with a signed manifest, declared inputs, sample data, and any review gates, and it becomes a pack — a workflow ready to run in Helm.

parent_hashes links forming a verifiable DAG in real time · depth labels shown below each node
What does "depth" mean?
depth: 0 Starting point. This artifact has no parents, it was built from raw inputs only. "I started from scratch." In the animation, Tool A is depth 0.
depth: 1 One link back. This artifact consumed a depth-0 artifact. "I built on one original source." Tool B and Tool C are depth 1, they both cite Tool A.
depth: 2 Two links back. This artifact's parents are themselves derived from original sources. Tool D is depth 2, it cites B and C, which each cited A.
depth: 3 Three links back. Tool E cites Tool D (depth 2), making E depth 3. The depth tells an auditor: "to verify me fully, you need to trace back 3 steps to the root."
Why this matters

An auditor can pick any node in the chain, re-run the tool with the recorded policy_parameters, recompute the SHA-256 hash, and compare. A hash mismatch means the artifact was altered or the tool is non-deterministic. No signer, no certificate authority, trust comes from reproducibility. You can verify it yourself in your own browser.

Chain speed:
Stage 3 of 22

AI agents discover, call, and verify over MCP

PractitionerNormative version: §7

A conformant tool exposes a tools/call MCP endpoint. An AI assistant, Claude, ChatGPT, or any MCP-compatible agent, can call emit_artifact, receive the envelope, then call verify_execution_hash to confirm integrity. The agent never needs to trust the server. It runs the SHA-256 check itself, the same way you ran "Apple" through SHA-256 in the pre-stage above. If the numbers match, the artifact is genuine.

MCP call/response cycle with hash verification · read-only, no auth required
🤖
MCP Agent
tools/call → structuredContent
The agent sends policy_parameters and receives the full artifact envelope. It never modifies anything, the server declares readOnlyHint: true, meaning nothing on the server changes from this call.
Verify Endpoint
verify_execution_hash
Given an artifact, the server re-runs the same SHA-256 procedure and returns match or mismatch. Agents call this on every artifact before trusting it, the same way you'd double-check a bank balance.
🏗️
Build OpenChainGraph
build_chaingraph
Given a goal or chain name, returns the ordered list of tools to call, with parent_hashes wiring. This is the agent's recipe, like a cooking recipe that tells you exactly what order to do things.
📡
Graph Index
Machine-discoverable catalog
A published JSON document listing all tools, their mandate_type, and which tools consume which outputs. Agents read this first to plan a chain before calling anything, like reading a menu before ordering.
✓ verification passed
Stage 4 of 22

Chains cross vendor boundaries, the graph is the product

PractitionerNormative version: §7

When two vendors both publish the x-chaingraph A2A capability extension, an orchestrating agent can chain artifacts across them. An OCS constraint solution can cite an ApexLogics credit assessment as a parent. An AINumbers compliance verdict can cite either. Every link is verified through each vendor's own verify_execution_hash. No vendor needs to trust another, the hash is the contract.

Cross-vendor artifact DAG · gold lines = cross-vendor citations · each vendor verifies their own links independently
The payoff

Once two suites are L4 with x-chaingraph, their artifacts can chain, and any third party can independently verify the entire provenance graph without asking either vendor. That cross-suite auditability is why OpenChainGraph is a standard rather than an internal convention. The math is the trust. No authority needed.

Platform Integration · AINumbers.co

AIN Bridge, the browser-side wiring layer

Practitioner

OCG defines the artifact format and the hash. AIN Bridge is how AINumbers tools actually receive inputs from agents, composers, and prior tool outputs, entirely in the browser, with no server round-trips and no storage writes. Every tool in the suite carries a small Bridge script that listens on three channels and fills form inputs the moment the page loads.

Why it's not an OCG stage: the OpenChainGraph standard covers provenance structure, hashing, and cross-vendor chaining. AIN Bridge is the AINumbers implementation of how that chaining reaches a browser tool. The standard doesn't require it, any transport that populates tool inputs works. Bridge is one such transport, designed to be zero-network and zero-egress.
Three channels converge client-side · URL hash fragment, parent postMessage, Policy Mandate JSON · zero network · fields filled, tool ready to run
🔗
#in=<b64url>
Prefill deep-link
Encode {"elementId": value, …} as base64url and append as a URL hash fragment: tool.html#in=<token>. Add &run=1 to auto-execute. The hash is never sent to a server, it lives only in the browser. Agents use this to hand off a pre-configured tool URL to a user with one click.
📨
postMessage
Composer messaging
Composer pages load tools in <iframe> elements and drive them via window.postMessage. Three message types: AIN_PREFILL (fill inputs), AIN_RUN (trigger execution), AIN_COLLECT (retrieve the output Policy Mandate). Same-origin only, cross-origin composers cannot drive tools.
📄
.policy.json
Policy Mandate intake
Tools with intake: true render a drop zone. Drag, choose, or paste a .policy.json from any prior tool. Bridge validates mandate_id, tool_id, and payload, then maps payload keys to matching element IDs, the same mechanism as prefill, driven by mandate rather than URL. The execution_hash field in the mandate closes the OCG provenance loop.
🛡️
Zero-network · zero-storage
No server. No egress. No log.
All three channels decode client-side. URL hash fragments are not included in HTTP requests. postMessage is same-origin only. Policy Mandate JSON never leaves the browser tab. Bridge dispatches input and change events after filling so reactive tool UIs update correctly.
Stage 5 of 22 · v0.2

Semantic context, W3C PROV-DM and buildType

Advanced

v0.2 adds a @context URL to every artifact. This single field makes OpenChainGraph artifacts interpretable by any W3C-compliant provenance tool. Field names like tool_id map to standardized PROV-DM terms, so a DORA audit system, a prov:Entity processor, and a DCAT catalog can all consume the same artifact without a custom adapter. A buildType URI declares exactly which hash construction algorithm was used, making the provenance machine-auditable end to end.

📌 Watch the animation: artifacts flow through an @context relay that maps OpenChainGraph fields to W3C standard terms. The rotating label shows each field mapping. The buildType tag appears below the artifact node.
Artifact fields mapped to W3C PROV-DM via @context · buildType URI declares hash algorithm · three consumer systems
🌐
@context URL
JSON-LD semantic context
A single URL (https://ainumbers.co/chaingraph/context/v0.3) that maps all OpenChainGraph field names to W3C standard vocabulary. Any JSON-LD processor understands the artifact automatically.
🔗
prov:wasDerivedFrom
Parent hash mapping
parent_hashes maps to this PROV-DM property, the standard W3C term for "this entity was derived from another entity." Auditors using any PROV-aware tool see the chain automatically.
🏷️
buildType URI
Hash algorithm declaration
https://ainumbers.co/chaingraph/context/v0.2#WebCryptoSHA256 declares the exact construction: sorted-key JSON → UTF-8 → WebCrypto SHA-256. No ambiguity about what was hashed or how.
📚
DCAT 3.0
Machine-discoverable graph index
chaingraph.json is expressible as a dcat:Catalog with each tool as a dcat:Dataset. Any data catalog portal can index an OpenChainGraph suite without a custom connector.
Stage 6 of 22 · v0.2

Authenticity layer, in-toto envelopes and Ed25519 signing

Advanced

The execution_hash proves integrity: the content hasn't changed. But it doesn't prove authenticity: who produced it. v0.2 upgrades audit_signature from a bare string to a structured in-toto ITE-6 attestation envelope, {payloadType, payload, signatures[{keyid, sig}]}. An optional Ed25519 key (RFC 8032, via WebCrypto) signs over the execution_hash. These are two independent checks: a valid hash but invalid signature means the content is intact but the signer is wrong.

📌 Two tracks: top = integrity (hash path) and bottom = authenticity (signature path). Both converge at VERIFY. A ✓ means both checks passed independently.
Integrity track (SHA-256) and authenticity track (Ed25519 → in-toto) · independent checks · both must pass
🔒
in-toto ITE-6
Attestation envelope
Upgrades audit_signature from a free-form string to a structured object: payloadType (MIME type), payload (base64url), and a signatures array with keyid and sig per signer.
✍️
Ed25519 (RFC 8032)
Digital signature over the hash
An optional WebCrypto Ed25519 key pair signs over the execution_hash bytes. Small (32-byte keys, 64-byte signatures), fast, and natively available in modern browsers via crypto.subtle.
⚖️
Integrity ≠ Authenticity
Two independent properties
Integrity = content unchanged (hash check). Authenticity = came from the right key (signature check). Both can pass, both can fail, or either can fail independently. Always verify both separately.
🪪
keyid field
Key identity declaration
The keyid in each signature entry identifies which public key was used. Verifiers look up the public key by keyid to confirm the signature, enabling key rotation without re-signing old artifacts.
✓ integrity + authenticity both valid
Stage 7 of 22 · v0.2

Observability, chains appear as distributed traces in OTel

Advanced

v0.2 defines a deterministic mapping from OpenChainGraph artifacts to OpenTelemetry spans. The first 8 bytes of an artifact's execution_hash become its spanId. The first 8 bytes of parent_hashes[0] become the parentSpanId. The root artifact's execution_hash becomes the traceId for the whole chain. Run artifactToOtelSpan() on any artifact and it drops into Datadog, Jaeger, or Honeycomb as a waterfall trace, no instrumentation code required.

📌 Left: a chain of 4 artifacts (depth 0→3). Center: artifactToOtelSpan(). Right: the resulting OTel waterfall, each bar indented by depth, showing spanId and parentSpanId labels.
execution_hash → spanId · parent_hashes[0] → parentSpanId · root hash → traceId · OTel waterfall animating
🆔
spanId
Artifact identity in OTel
The first 8 bytes (16 hex chars) of execution_hash become this artifact's OTel span ID. Deterministic, same artifact always maps to the same spanId. No random IDs, no coordination required.
↩️
parentSpanId
Chain link in OTel
The first 8 bytes of parent_hashes[0] become the parentSpanId, pointing to the parent artifact's span. This is what creates the waterfall indentation in Datadog / Jaeger / Honeycomb.
🔍
traceId
Full chain identifier
The root artifact's execution_hash (depth: 0, no parents) becomes the traceId for the entire chain. Every artifact in the chain shares this traceId, grouping them into one coherent trace.
artifactToOtelSpan()
Zero-instrumentation tracing
A pure function: takes an artifact, returns an OTel span object. No SDK, no agents, no code changes to existing tools. Export the span to any OTel-compatible backend and your decision chains are instantly observable.
Span / Tool
Timeline
Duration
├ Credit Score
traceId: 3f9a… · spanId: 3f9a… · depth:0
48 ms
├ Affordability
parentSpan: 3f9a… · spanId: 7c2b… · depth:1
62 ms
├ Risk Model
parentSpan: 7c2b… · spanId: a1d9… · depth:2
55 ms
└ Loan Approval
parentSpan: a1d9… · spanId: 8e5a… · depth:3
38 ms

ⓘ spanId = first 16 hex chars of execution_hash · parentSpanId = first 16 hex chars of parent_hashes[0] · traceId = root artifact execution_hash · status.code = ERROR if any compliance_flag has severity:ERROR

Stage 8 of 22 · v0.3

Financial payload alignment, ISO 20022 semantic profile

AdvancedNormative version: §8

v0.3 gives the financial payload a semantic standard to complement the provenance envelope's W3C PROV-DM alignment. The ISO 20022 semantic profile is an optional JSON-LD overlay, a second @context entry, that maps amount, currency, party, and agent fields to ISO 20022 business elements. It never touches the execution_hash preimage (§2 is unchanged). Tools that aren't payment tools carry no profile: a VaR engine or DORA classifier has nothing ISO 20022-shaped to declare.

📌 Watch field names fly from the OCG artifact through the context relay and land on their ISO 20022 equivalents. The profile is applied by adding a second @context URL, nothing else changes in the artifact.
OCG payload fields → ISO 20022 context relay → ISO 20022 business elements · optional overlay, hash preimage unchanged
💱
ISO 20022 Alignment
Payload crosswalk, not registration
OpenChainGraph is ISO 20022-aligned, not a registered ISO 20022 message. The profile maps common financial fields to ISO 20022 business element names so banks, PSPs, and regulators can read artifacts without a custom adapter, using vocabulary they already know.
📋
Dual @context
Two context URLs in an array
Applying the profile means adding a second entry to the @context array: the existing OCG context plus the new iso20022-context.jsonld. No other field changes. The execution_hash preimage is unaffected, a v0.1 verifier produces an identical hash.
🏦
External Code Sets
ISO 4217 · 3166 · 9362 · 17442
Currency (ISO 4217), country (ISO 3166), BIC/SWIFT (ISO 9362), and LEI (ISO 17442) code sets are adopted by reference, the same external code lists ISO 20022 payments already use. No new registries; no proprietary enumerations.
🎯
Minimal by Design
Amount, party, agent fields only
Only fields with a direct ISO 20022 counterpart are mapped: amount, currency, debtor, creditor, lei, bicfi, settlement_date, remittance_information. Risk scores, model outputs, compliance flags, none of those are profiled.
Stage 9 of 22 · v0.3

Party identity, LEI anchors and did:key signing

AdvancedNormative version: §9

v0.3 formalizes two optional identity anchors. A did:key identifier, a self-describing, multicodec-prefixed base58btc encoding of the Ed25519 public key, is the recommended form for keyid in the signature envelope. An ISO 17442 Legal Entity Identifier (LEI) optionally binds the publisher (and signing key) to a regulator-grade legal-entity anchor. Together they bridge the signing layer (§6) and the ISO 20022 payload layer (§8): the same LEI can identify both the tool vendor and a debtor or creditor in a payment artifact.

📌 Left: Ed25519 key pair. Center: did:key URI derived, self-describing, no registry needed. Right: LEI optionally ties the signer to a legal entity (GLEIF-registered, regulator-grade). Each layer is optional and additive.
Ed25519 key pair → did:key URI (self-describing) → optional LEI (ISO 17442) · each layer additive, none enters hash preimage
🔑
did:key
Self-describing key identity
A did:key:z6Mk… URI encodes the raw Ed25519 public key in multicodec + base58btc form. It's resolvable without a registry, anyone can derive the public key from the DID alone. Replaces an opaque hex fingerprint with a standardized W3C DID identifier.
🏢
LEI (ISO 17442)
Regulator-grade entity identity
A 20-character alphanumeric code issued by the Global LEI System (GLEIF). Banks, PSPs, and supervisors already consume LEIs. Optionally binds an OpenChainGraph vendor, and their signing key, to a legal entity that regulators can look up directly.
🌉
Identity Bridge
Links signing ↔ payment identity
The same LEI can appear in both publisher.lei (who signed this artifact) and debtor.lei / creditor.lei (party to this payment). One identifier serves both the provenance signing layer and the ISO 20022 financial payload layer.
🔒
Envelope-Level Only
Identity fields outside hash preimage
publisher.lei and the keyid form describe who produced the artifact, not what decision was made. Neither enters the execution_hash preimage, a verifier correct for v0.1 computes identical hashes on v0.3 artifacts with full party identity.
Stage 10 of 22 · v0.3

Knowledge layer, OKF companion bundle

AdvancedNormative version: §10

v0.3 publishes an Open Knowledge Format (OKF) companion bundle auto-generated from chaingraph.json: one markdown concept file per Graph Index node. It's the narrative complement to the DCAT catalog, DCAT is what an agent reads to plan a chain before calling anything; OKF is what an agent (or human) reads to understand what a tool does and when to use it. Crucially, OKF concept documents are knowledge, never decision artifacts, they MUST NOT carry an execution_hash.

📌 One source: chaingraph.json generates both outputs. Left branch → DCAT catalog (machine-optimized, agent-plannable). Right branch → OKF bundle (narrative context, human + agent readable). The two outputs are strictly separate, knowledge ≠ decision artifact.
chaingraph.json → DCAT catalog (agent plans chain) + OKF bundle (narrative context) · two outputs, one source, never mixed
📚
OKF = Context-In
Knowledge read before acting
OKF concept documents explain what a tool means, its intent, when to use it, how its output feeds downstream decisions. An agent reads OKF before choosing tools; a human reads it to understand what's in the catalog. It's the annotation layer, not the execution map.
📡
DCAT = Provenance-Out
Machine-readable execution recipe
The DCAT catalog (chaingraph.json) tells an agent which tools exist, which tools feed which, and which MCP endpoint to call. It's the execution map. OKF sits on top of it as the meaning layer, separate by design.
🔗
consumes/feeds → Links
Graph edges become markdown links
The ocg:consumes and ocg:feeds edges in the DCAT catalog become markdown hyperlinks between concept documents, reproducing the graph structure in a human-readable form. One concept file per live node; regenerated on every index change.
🚫
No execution_hash in OKF
Knowledge ≠ decision artifact
An OKF concept document MUST NOT carry an execution_hash or audit_signature. It is knowledge, not a decision. Nothing in the OpenChainGraph verification path depends on OKF, the bundle is generated, swappable, and purely informational.
Stage 11 of 22 · v0.3.1

Profile conformance, dct:conformsTo and dereferenceable URIs

AdvancedNormative version: §11

v0.3.1 makes semantic profile conformance machine-resolvable using W3C PROF and Content Negotiation by Profile. A profile is now published at a dereferenceable URI and declared with dct:conformsTo, not just named by an opaque string token. The semantic_profile token (e.g. "iso20022:pacs.008-subset") is retained as a registered alias pointing to the URI via a token↔URI registry. Every node declares only what it truthfully conforms to, a VaR engine carries no ISO 20022 profile. The hash preimage is unchanged; all prior artifacts remain valid.

📌 Left: v0.3.1 artifact with both semantic_profile token and dct:conformsTo URI. Center: verifier dereferences the URI. Right: prof:Profile document confirms the schema and guidance. Hash preimage is unchanged throughout, this is metadata about the artifact, not the artifact's decision content.
dct:conformsTo URI → dereferenced profile document → prof:Profile schema check · semantic_profile token as registered alias · hash unchanged
🔗
dct:conformsTo
Dereferenceable conformance URI
Instead of an opaque token, v0.3.1 declares conformance with a real URL: dct:conformsTo: ["https://ainumbers.co/chaingraph/profiles/iso20022/pacs008-subset.jsonld"]. Any verifier can fetch it. The profile URI resolves to a PROF prof:Profile resource listing schema and guidance.
🏷️
Token Alias
semantic_profile retained as shorthand
The semantic_profile string token (e.g. "iso20022:pacs.008-subset") is retained as a registered alias. The authoritative token↔URI map is published at profiles/registry.json. Existing v0.3 artifacts remain valid with no changes required.
Truthful Conformance
Declare only what you actually conform to
A payment node gets iso20022:pacs.008-subset. A party-only node gets the new iso20022:party-identification profile. A VaR engine or DORA classifier gets no ISO 20022 profile. Forcing a payment profile onto a non-payment node would be a false conformance claim, this design avoids it.
#️⃣
Hash Preimage Unchanged
v0.1 verifiers compute identical hashes
dct:conformsTo, @context, and semantic_profile are all outside the execution_hash preimage (sorted-key SHA-256 over {policy_parameters, output_payload}). Backward compatibility is complete and mathematical, not just claimed.
Stage 12 of 22 · v0.4

Compute Binding, server-side kernels make every tool agent-native

PractitionerNormative version: §12

v0.4 introduces Compute Binding: a registered kernel (pure ESM, exports compute(), buildArtifact(), meta) runs directly on the Cloudflare Worker for nodes where gpu:false. An AI agent sends policy_parameters in a single tools/call and receives a complete, fully-hashed v0.4 artifact in one round-trip, no browser delegation, no user interaction, no waiting for a page to load. The new compute_mode: "server" envelope field tells every downstream consumer how the hash was computed. It is excluded from the hash preimage, so all prior artifacts remain valid.

📌 Watch both paths: the old browser-delegated flow (top, purple) requires a delegation URL, a browser runtime, and multiple steps. The v0.4 server-side flow (bottom, green) returns a signed artifact in a single MCP call, the Worker itself runs the ESM kernel. No browser. No wait. No UI.
Top: pre-v0.4 gpu:true path, browser delegation required · Bottom: v0.4 gpu:false path, Worker kernel, single round-trip, compute_mode:"server"
⚙️
gpu:false kernel
Pure ESM, runs on the Worker
A v0.4 kernel exports three things: compute(params) runs the calculation server-side; buildArtifact(params, output) assembles the OCG envelope with execution_hash; meta declares the kernel name and tool version. Registered in kernels/index.mjs and vendored into data/ at build time.
🚀
compute_mode: "server"
New v0.4 envelope field
The v0.4 artifact envelope adds compute_mode: "server" when the Worker ran the kernel, excluded from the hash preimage. The compute_capability field in chaingraph.json advertises which nodes support server-side compute, so agents can discover it before calling. compute_mode: "auto" lets the Worker decide.
🔄
Single round-trip
Agent-native by design
Before v0.4, every tool call returned a delegation URL the agent had to open in a browser, requiring a JS runtime and user interaction. v0.4 collapses this to one MCP tools/call: the agent sends parameters and receives a complete, signed artifact. No browser. No wait. The spec calls this agent-native execution.
🛡️
Privacy boundary
Stateless, no telemetry
§12.4: the Worker kernel runs in a stateless context. No PII is logged. No computation telemetry is emitted. The privacy boundary is identical to the MCP contract, readOnlyHint: true. Sensitive policy_parameters never leave the MCP call/response envelope.
Old path (browser round-trip)
0.00s
vs
Compute Binding (single MCP call)
0ms
Stage 13 of 22 · v0.4

Export Profiles, the hash travels to the last mile

PractitionerNormative version: §13

v0.4 defines the chaingraph_export umbrella: xlsx, pdf, csv, xbrl, and vc renderings generated from a verified artifact. v0.4.1 adds chaingraph_export:vc (W3C Verifiable Credentials 2.0) as a base profile available on every node, covered in Stage 14. The key invariant: exports are produced downstream of execution_hash and are excluded from the hash preimage. The cryptographic anchor is fixed before any export runs. The export_artifact MCP tool (readOnlyHint: true) takes an artifact and a format and returns a deterministic rendering, the execution_hash travels intact into every output as embedded metadata. Regulatory XBRL submissions use the xbrl_taxonomy parameter (e.g. "eba-corep-own-funds") to select the filing profile.

📌 Three layers: the verified JSON artifact (provenance-out), the OKF concept bundle (knowledge-in, see Stage 10), and the export renderings (rendered-for-review). Only the first layer carries an execution_hash and enters verification chains. The export layer annotates it, it doesn't modify it.
Verified artifact (locked execution_hash) → export_artifact MCP tool → xlsx, pdf, csv, xbrl renderings · hash preimage unchanged throughout
📦
chaingraph_export
The v0.4 export umbrella
Four profiles ship in v0.4: xlsx (three-sheet analyst workbook: Decision / Summary / Provenance), pdf (signed printable render), csv (tabular data extract), xbrl (machine-readable regulatory submission). Each is generated from output_payload after the execution_hash is already fixed.
📤
export_artifact
MCP tool, readOnlyHint: true
The agent calls export_artifact(artifact, format, xbrl_taxonomy?). The tool generates the rendering on demand and returns it, nothing on the server changes. Advertised via export_capability in chaingraph.json nodes so agents can discover it before calling.
#️⃣
Preimage unchanged
Exports excluded from hash computation
The chaingraph_export field and all export outputs are outside the hash preimage. The hash is computed over {policy_parameters, output_payload} only, as in every prior version. All existing artifacts remain valid with no re-hashing required. The export is the last mile, not the source of truth.
🏛️
XBRL regulatory filing
Machine-readable for regulators
Pass xbrl_taxonomy: "eba-corep-own-funds" for a bank capital COREP filing. The XBRL instance document embeds execution_hash as a named fact, regulators can trace every submitted number back to the verified artifact that produced it, with no spreadsheet chain-of-custody required.
Stage 14 of 22 · v0.4.1

Export Profile: W3C Verifiable Credentials, the standards shell

AdvancedNormative version: §13

v0.4.1 adds a fifth export profile: chaingraph_export:vc. Unlike xlsx/pdf/csv/xbrl, which target human reviewers and regulatory filings, the VC profile targets agents and counterparties that already speak W3C Verifiable Credentials 2.0. It renders any verified artifact as an OpenChainGraphCredential (application/vc+json). It is a base profile: no export_capability declaration required, available on every node. The ocg:hashAnchor field re-states the canonical execution_hash inside the VC envelope so downstream consumers can always route verification back to the canonical JSON. Key distinction: this is a view, not a secured credential, it carries no VC proof. For a signed, secured artifact, see Stage 15.

📌 The verified artifact (left) passes through the VC renderer, the same execution_hash travels into the credential envelope as ocg:hashAnchor. The VC is a lossless structural re-expression. Hash preimage unchanged; chaingraph_version stays "0.4.0".
Verified artifact → VC renderer → OpenChainGraphCredential · ocg:hashAnchor carries execution_hash · hash preimage unchanged · view only
🏅
Base Profile, every node
No export_capability declaration needed
A structural re-expression of any OCG artifact into VC format always exists, so this profile is universally available, unlike xlsx or xbrl, which are domain-specific and must be declared in export_capability.
🪪
OpenChainGraphCredential
Deterministic VC identity
The VC type array contains "VerifiableCredential" and "OpenChainGraphCredential". The id is urn:ocg:artifact:<bare-execution-hash>, deterministic, no UUID or clock. Same artifact always maps to the same credential URI.
#️⃣
ocg:hashAnchor
Pointer back to verification
Re-states the canonical execution_hash, digestMethod, and a verify_url inside the VC envelope. Not a VC proof suite, a structured pointer that routes any downstream consumer back to the original verification path.
👁️
View, not secured credential
No new hash · no securing proof
Like all §13 exports, the VC mints no new execution_hash and adds no W3C Data Integrity proof. The envelope and chaingraph_version are unchanged. For a secured VC, add a proof via Stage 15 (Proof Binding).
Stage 15 of 22 · v0.5

Proof Binding, from tamper-evidence to authenticated attestation

AdvancedNormative version: §16

v0.5 adds the final layer: Proof Binding. Until now, execution_hash proved integrity, the content hasn't changed since it was produced. But it didn't prove who produced it at the artifact level. v0.5 adds an OPTIONAL W3C Data Integrity proof (eddsa-jcs-2022) at audit_signature.proof. Because execution_hash sits inside the secured document, one signature transitively secures both the §4 hash anchor and the full artifact envelope. The mechanism is default-off: signing makes the run linkable to a key, eroding the zero-PII anonymous posture. Tools MUST surface that opting in de-anonymizes the run. The hash preimage is unchanged; unsigned artifacts are byte-identical to v0.4.1; only spec_version advances to 0.5.0.

📌 Watch three guarantees converge on the artifact: execution_hash (integrity, always present), signatures[] (hash-level authenticity, v0.2+), and the new proof (whole-artifact authenticity, v0.5). The proof track auto-toggles every 5 seconds to illustrate the default-off posture. Unsigned artifacts are byte-identical to v0.4.1.
Three convergent paths: execution_hash (integrity) · signatures[] (hash authenticity) · proof (whole-artifact authenticity, default-off) · proof auto-toggles to illustrate default-off
📍
audit_signature.proof
Backward-compatible proof placement
The proof lives at audit_signature.proof, not at artifact root (additionalProperties:false in frozen v0.4 schema) and not inside signatures[] (which retains its DSSE/in-toto meaning). A signed v0.5 artifact still validates under the v0.4 schema.
🔏
eddsa-jcs-2022
W3C Data Integrity cryptosuite
Uses the same cgCanon JCS canonicalizer from kernels/_hash.mjs as §4, no second canonicalization path. proofValue is "z" + base58btc(Ed25519.sign(key, hashData)), multibase-encoded. Produced by shared kernels/_proof.mjs; browser inlines it, Worker imports it, byte-identical output.
🔗
Transitive security
One signature · two guarantees
The secured document is the full artifact minus proof. Because execution_hash sits inside the secured document, a whole-artifact signature transitively secures both the §4 hash anchor and all other artifact fields, one key pair, two guarantees.
🔐
did:key vs did:web
Ephemeral vs institutional issuers
Ephemeral or client-side signing uses did:key, self-describing, no registry. Institutional issuers SHOULD use did:web anchored to their domain, key held in HSM/KMS, signing performed server-side via the §12 Compute path (same Worker).
Privacy tradeoff, default-off by design
Signing makes the run linkable to a key, the signer becomes known. The zero_pii_verified guarantee still holds for inputs; only the identity of the signer is revealed. Proof Binding MUST default OFF and MUST NOT be auto-applied. A tool may offer signing as an opt-in for institutional issuers wanting auditor-grade attestation while preserving anonymous-by-default behavior for all other callers.
Default off — run is anonymous
Stage 16 of 22 · v0.1+ (now explicit)

compliance_flags[] and mandate_id, the decision identity fields

PractitionerNormative version: §5

Every artifact carries two fields that Stage 1 didn't have space to unpack. mandate_id is a UUID v4 assigned at run time, it's the "ticket number" for this specific execution, used by ops teams for support queries and audit lookup. compliance_flags[] is the structured exception layer: an array of flag objects with code, severity (INFO / WARN / ERROR), and message. A valid execution_hash and one or more compliance_flags with severity ERROR are not contradictory, integrity and business-logic warnings are fully independent. The OTel mapping converts compliance_flags into span status.code: any ERROR flag produces status.code = ERROR on the span.

📌 Watch flags build up in the artifact as the tool runs, WARN (yellow), ERROR (red), then cleared (green). The execution_hash stays fixed throughout: content integrity is separate from compliance outcome.
mandate_id (run identity) · compliance_flags[] building up (INFO→WARN→ERROR→cleared) · execution_hash stays fixed · OTel status.code updates
🎫
mandate_id
Run identity, the ticket number
UUID v4 assigned at execution time. Uniquely identifies this specific run of this tool. Used by ops teams for support lookup, audit queries, and recall. Does not enter the hash preimage, the same inputs always produce the same hash regardless of when they run.
🚩
compliance_flags[]
Structured exception layer
Array of flag objects: {code, severity, message}. Severity levels: INFO, WARN, ERROR. A valid hash + ERROR flag is fully valid, the content is intact AND the business logic raised a warning. These are independent properties.
📡
OTel status.code
Flags → span status
The OTel mapping (§6) converts compliance_flags into span status.code: any flag with severity: ERROR sets status.code = ERROR on the span. INFO and WARN flags leave status at OK. This makes compliance exceptions visible in Datadog, Jaeger, and any OTel-compatible trace viewer.
🔑
Preimage independence
Flags don't affect the hash
compliance_flags and mandate_id are outside the hash preimage, only policy_parameters and output_payload are hashed. This means a tool can raise a WARN or ERROR flag without changing the verifiable hash of its decision inputs and outputs.
Stage 17 of 22 · v0.2+

Ed25519 key lifecycle, generate, publish, sign, verify, rotate

Advanced

Stage 6 covered what the signature does. This stage covers how the key is born, where it lives, how verification finds it, and how it gets rotated. The full lifecycle is four steps: Generate (crypto.subtle.generateKey in the browser, or Node's crypto.generateKeyPairSync server-side), Publish (export the public key as hex → did:key → add to chaingraph.json under ocg:signing_keys), Sign (the kernels/_proof.mjs or in-toto envelope signer produces the signature bytes), Verify (any verifier imports the public key from the Graph Index and calls crypto.subtle.verify). Rotation adds a new entry with a valid_from date, old artifacts signed under the prior key remain permanently verifiable using the prior entry.

📌 The four-panel canvas cycles through GENERATE → PUBLISH → SIGN → VERIFY. Watch the key bytes (purple) travel from the keypair generation into the chaingraph.json Graph Index, then into the signature, then back out to the verifier's verify call. Key rotation is shown by the second key entry appearing alongside the first.
Ed25519 lifecycle: generate keypair → publish did:key to Graph Index → sign artifact → verify using public key → key rotation (valid_from)
⚙️
Generate
crypto.subtle.generateKey
crypto.subtle.generateKey({name:"Ed25519"}, true, ["sign","verify"]) produces a CryptoKeyPair. Export public key as raw bytes → hex string → derive did:key (multicodec 0xed01 prefix + base58btc). Never export the private key bytes outside a secure context.
📋
Publish
ocg:signing_keys in chaingraph.json
Add the public key to the tool's Graph Index entry: ocg:signing_keys: [{keyid:"did:key:z6Mk…", valid_from:"2025-01-01"}]. Any verifier that fetches chaingraph.json from the tool's endpoint can now derive the public key from the did:key and verify any artifact signed with it.
✍️
Sign
Ed25519.sign over payload or JCS
For in-toto: sign the base64url-encoded artifact body (PAE envelope). For Proof Binding (v0.5): sign the JCS-canonicalized document via kernels/_proof.mjs. Both use crypto.subtle.sign("Ed25519", privateKey, data). Output: 64 bytes → encoded in the artifact.
🔁
Rotate
valid_from / valid_until
Add a new key entry with today's valid_from. Set valid_until on the old entry if desired. Verifiers MUST use the key whose valid_from/valid_until bracket the artifact's created_at timestamp. Old artifacts remain verifiable permanently, rotation is additive, not destructive.
Stage 18 of 22 · v0.4+

The chaingraph.json Graph Index, how agents plan before calling

PractitionerNormative version: §7

Stage 3 showed an agent calling a tool. Stage 4 showed cross-vendor chains. But neither answered: how does the agent know which tools to call, in what order, before making any calls? The answer is the chaingraph.json Graph Index, a DCAT 3.0 catalog that every node publishes at its well-known URL. It declares ocg:consumes (what this node depends on) and ocg:feeds (what this node can produce input for), forming a dependency DAG. Agents read the full graph before calling anything, plan the optimal execution path, and avoid invalid partial chains. ocg:conformance_level (L1–L4) signals implementation completeness. dcat:accessService + ocg:mcp_tool_name give the callable address. The Graph Index is what makes OCG an orchestration protocol, not just a hash format.

📌 Click any tool node in the canvas to expand its Graph Index entry. The agent node reads the full DAG, highlights the optimal path (A → B → D), and shows a conformance badge on each node. ocg:consumes and ocg:feeds are the dependency edges, dotted in, solid out.
chaingraph.json catalog → ocg:consumes / ocg:feeds dependency DAG → agent plans optimal path → conformance levels L1–L4 → dcat:accessService MCP endpoint
🗺️
dcat:Catalog
Machine-readable recipe book
The chaingraph.json is a DCAT 3.0 dcat:Catalog published at the tool's well-known URL. Each tool is a dcat:Dataset entry with mandate_type, compute_capability, export_capability, dct:title, and ocg:mcp_tool_name. Agents fetch this once to understand the full tool landscape.
↔️
ocg:consumes / ocg:feeds
Dependency DAG edges
ocg:consumes: this node reads artifacts from these upstream tools. ocg:feeds: this node's output can be consumed by these downstream tools. Together they form a directed acyclic graph, agents traverse it to determine which tool calls must precede others and which can be parallelized.
📊
Conformance levels L1–L4
ocg:conformance_level
L1: canonical artifact + hash only. L2: + PROV-DM context + buildType. L3: + in-toto signature + OTel mapping. L4: + profile conformance + compute binding + export profiles. An agent can filter the DAG to only plan paths through L3+ nodes for high-assurance workflows.
🔌
dcat:accessService
The callable MCP address
dcat:accessService.endpointURL + ocg:mcp_tool_name give the agent everything it needs to call the tool: the MCP server URL and the tools/call tool name. No out-of-band configuration required, the Graph Index is the service directory.
Stage 19 of 22 · v0.6

Kernel Identity Binding, pinning which logic ran

AdvancedNormative version: §17

Every previous stage has shown that execution_hash proves "this output follows from these inputs". But it says nothing about which code performed the computation. A dishonest server could substitute a different kernel, one with backdoors, different rounding, or different regulatory logic, while still producing a valid hash over its outputs. v0.6 closes this gap with Kernel Identity Binding (§17): the artifact MAY record a kernel_digest, a SHA-256 over the LF-normalised kernel source bytes, at audit_signature.build_identity. A verifier performs a three-way cross-check: artifact kernel_digest == Graph Index compute_images[].image_id == digest recomputed from the published source file. Any mismatch fails the binding. Important caveat (§17.2): this is an advisory claim, not a cryptographic proof of execution, a dishonest server could still record the right digest while running different code. That is what §18 solves.

📌 Watch the kernel source file (left) get hashed by _buildid.mjs (LF-normalised, WebCrypto SHA-256). The digest travels into the artifact at audit_signature.build_identity.kernel_digest AND into the Graph Index compute_images[]. The verifier pulls both and checks three-way equality. The tamper button swaps the kernel, watch all three values diverge and the binding fail.
kernel source → _buildid.mjs (LF-normalise, SHA-256) → kernel_digest → artifact build_identity + Graph Index compute_images[] → three-way cross-check
✓ three-way binding valid
🧬
kernel_digest
SHA-256 over kernel source
_buildid.mjs reads the kernel file, normalises all line endings to LF, and runs WebCrypto SHA-256 over the UTF-8 bytes. Result: sha256:<hex>. Stored at audit_signature.build_identity.kernel_digest. Deterministic: same source always → same digest regardless of OS or runtime.
📑
compute_images[]
Graph Index publication
Each live node in chaingraph.json SHOULD publish its kernel digest: compute_images: [{system:"sha256-source", image_id:"sha256:…", valid_from:"…"}]. This is the second leg of the three-way cross-check, the public, independently verifiable record of which kernel a node claims to run.
🔍
Three-way cross-check
Artifact ↔ Graph Index ↔ Source
Verifier checks: (1) artifact.build_identity.kernel_digest == (2) chaingraph.json compute_images[].image_id == (3) recomputed digest from the published source file. All three must match. Any mismatch, tampered artifact, stale Graph Index, or modified source, fails the binding immediately.
⚠️
Honesty caveat (§17.2)
Advisory claim, not proof of execution
§17 cannot prevent a dishonest server recording the correct digest while actually running different code. It strengthens tamper-evidence (the digest is inside the §16 secured set when both apply) and makes forgery auditable, but it does not prove the named kernel produced the output. That is §18's job.
Stage 20 of 22 · v0.6

Compute-Integrity Proof, succinct proof of correct execution

AdvancedNormative version: §18

§17 pins which kernel was claimed. §18 makes it cryptographic. An artifact MAY attach an optional zkVM receipt at audit_signature.compute_proof: a zero-knowledge proof that this specific program (identified by imageId) produced this specific output (recorded in journal) from some inputs, without the verifier having to re-run the kernel, and optionally without revealing those inputs at all. This is OCG's analogue of Trusted Compute Units (arXiv:2504.15717), but software-only: no TEE, no hardware enclave, no blockchain anchor. The system is agnostic (risc0, sp1, jolt…); groth16-bn254 (~200 bytes) is recommended. Seal verification is delegated to the named system's vetted verifier, exactly as §4 delegates SHA-256 to WebCrypto and §16 delegates Ed25519. Proving is off-band: it requires a Rust toolchain and heavy compute; it MUST NOT be claimed to run in the browser or Worker. Default-off.

📌 The canvas shows the verifiable-computation ladder: L1 (§4 hash, always), L2 (§16 proof, optional), L3 (§18 receipt, optional). Click any rung to expand it. The zkVM proving and verification flow animates left to right: guest program + inputs → prover (off-band) → receipt (seal + journal) → verifier checks seal, then journal == output_payload.
zkVM proving (off-band, heavy) → receipt (seal + journal) → verifier: check seal via zkVM verifier → check journal == output_payload → no re-execution needed • optional: inputs may be withheld
Public inputs — §4 recompute also available
🧾
ZkVmReceipt
The proof object
{type:"ZkVmReceipt", system:"risc0"|"sp1"|"jolt", receiptFormat:"groth16-bn254"|"stark", imageId:"sha256:…", seal:"<base64>", journal:{output:…}}. Lives at audit_signature.compute_proof, hash-excluded, under the tolerant audit_signature object. A v0.6 artifact still validates under the frozen v0.4 schema.
🔗
imageId ↔ compute_images[]
Program identity binding
imageId in the receipt MUST match compute_images[].image_id in the Graph Index node entry, the published claim of which program the node runs. Together with §17 kernel_digest, this gives a two-layer program identity check: source digest (advisory) + zkVM guest identity (cryptographic).
📖
journal == output_payload
Output binding
The receipt's journal.output MUST equal the artifact's output_payload. The verifier checks this binding directly, no re-execution. If the journal matches and the seal verifies, the verifier has cryptographic assurance that this program produced this output.
🔒
Confidential inputs (§18.3)
Verify without seeing inputs
When inputs are confidential, policy_parameters carries commitments/hashes instead of cleartext. §4 recompute is then unavailable to third parties. The receipt becomes the sole verification path. A tool in this mode MUST surface that to users. Like §16, default-off.
The verifiable-computation ladder (§18.4)

L1, §4 execution_hash: tamper-evidence; verifier must re-run with cleartext inputs.  L2, §16 Proof Binding: authenticated attestation; a named key vouches for the whole artifact.  L3, §18 Compute-Integrity Proof: succinct proof of correct execution; verifier checks a receipt without re-running, optionally without seeing inputs. They compose: a §18 receipt MAY itself be covered by a §16 proof. Proving is off-band, MUST NOT be claimed to run in the browser or Worker.

Stage 21 of 22 · §15

How the standard polices itself

PractitionerNormative version: §15

A rulebook nobody checks is just a wish list. Most specifications are written as prose: they say a conformant tool should do this and must not do that, and then everyone hopes implementers read carefully and behave. OpenChainGraph takes a stricter stance, and it is the reason you can trust everything on the pages before this one.

The rule is simple: every sentence in the standard that says MUST has to name a script that fails the build the moment the rule is broken. Conformance is not a promise a vendor makes. It is a test that either passes or does not.

📌 The one-line version: a rule with no gate is not part of the standard. If nothing can fail when the rule is broken, the rule is only decoration.
📜
Rule names a gate
Every MUST is executable
Each normative rule points at a real check. "The hash preimage is built exactly one way" is not a paragraph you trust; it is a gate that re-derives the hash and fails if a tool used any other recipe.
👮
Meta-gate
A gate that watches the gates
One check reads the rule-to-gate matrix and fails the build if any numbered rule has no gate attached. You cannot quietly add a rule and forget to enforce it, and you cannot delete a gate and leave the rule stranded.
🚫
No gate, no rule
Prose alone does not count
If a proposed rule cannot be expressed as something a machine can check, it does not enter the standard as a MUST. It stays advice. That keeps the normative core small, precise, and impossible to fake.

A few of the gates a build has to pass before anything ships:

preimageOne canonical way to build the hash input. The gate re-computes every published hash and rejects any tool that shortcut the recipe.
coverageThe meta-gate: every numbered rule in the standard maps to a named check. A rule with no check fails the whole build.
page parityThe friendly spec page you read cannot drift from the written standard. If the page shows a section the standard does not define, the build stops.

This is what "conformance-by-construction" means. You do not audit a vendor's good intentions. The standard ships with its own enforcement, so a build that is green is a build that obeyed every rule, and a build that broke a rule never reached anyone.

Stage 22 of 22 · §20

Anchoring artifacts in time

PractitionerNormative version: §20

An artifact's execution_hash proves what a tool computed. It does not prove when. Section 20 closes that gap by defining the anchor_bindings array, which sits outside the hash scope so an artifact's integrity proof is unchanged while carrying one or more independent timestamp receipts.

Each binding names a timestamp authority, carries the hash that was sent, and embeds the signed response. The timestamp authority never sees your file, only the hex digest.

📌 The timestamp authority signs the hash, not the document. You send 32 bytes; you receive a signed RFC 3161 receipt. The document never leaves your browser, and no account is required.
OCG Artifact execution_hash: sha256:4af2e9c7… policy_parameters: {…} output_payload: {…} audit_signature: {…} anchor_bindings: [✓] hash scope unchanged hash only Timestamp Authority Sigstore / DigiCert / Sectigo FreeTSA / GitHub TSA OpenTimestamps (Bitcoin) signs hash, not file signed TST anchors.json type: "rfc3161-tst" anchored_hash: sha256:4af2… log_origin: "digicert.com" gen_time: 2026-07-03T… policy_oid: 2.16.840… proof: <base64 DER TST> signer_cert_chain: […] verifiable offline appended as anchor_bindings (outside hash scope)
execution_hash exits artifact → TSA signs it → receipt embedded as anchor_bindings · integrity scope unchanged
🔒
Outside the hash scope
Integrity is preserved
anchor_bindings sits outside the execution_hash preimage. Adding it after the fact does not change the hash — §4 verification passes on the same artifact before and after anchoring. The two checks are fully independent.
⏱️
When, not what
Proof of existence in time
The TSA's signed timestamp proves the hash existed before the receipt was issued. Combined with the artifact's execution_hash, you have proof of both the computation's content and the moment it occurred.
📄
Offline verifiable
No server required
A DER receipt verifies with openssl ts -verify and the issuing CA's root certificate. No network call, no account, no expiry. The receipt is self-contained evidence that survives any server going offline.
⛓️
Transitivity
One receipt covers a chain
Anchor the terminal node's artifact and the full provenance graph is covered. Every prior node's hash sits in parent_hashes, so the timestamp receipt anchors the whole chain by transitivity.

Supported binding types in §20:

rfc3161-tstCertificate-backed timestamp. DigiCert, Sectigo, Sigstore TSA, FreeTSA, or GitHub TSA. DER-encoded TimeStampToken; confirmed immediately. Verifiable with openssl ts -verify and the issuing CA's root certificate, which the standard pins.
opentimestampsBitcoin-anchored proof. Hash is batched into a Bitcoin transaction by the OTS calendar network. No fee, no wallet. Proof is pending for a few hours after stamping; once confirmed the block timestamp is the permanent evidence.

To anchor an OCG artifact, drop it on the Anchor page at anchor.ainumbers.co. The page reads the execution_hash field directly — no re-hashing of the raw file — and emits the artifact with anchor_bindings appended per §20. The anchor_document_integrity MCP tool exposes the same operation for use inside multi-step workflows.

Frequently Asked Questions

Questions we keep hearing

Beginner

Fifteen questions that come up every time someone meets OpenChainGraph for the first time, covering the plain-language basics, the core standard, the v0.4 additions, v0.5 Proof Binding, and the AIN Bridge integration layer.

Is this a blockchain?

No. There is no network to join, no coin, no miners, and no shared ledger that strangers have to agree on. Each tool runs on its own and stamps its result with a fingerprint. Trust comes from re-doing the math yourself, not from a crowd voting on what is true.

If you want the longer, more technical comparison to blockchains, Git, and supply-chain attestations, see the "Isn't this basically a blockchain?" question further down.

What does "chain" mean here?

Two different things share the word, so it is worth separating them. The "chain" in the name refers to the way one result cites the fingerprint of the result it used, so decisions link into a tamper-evident line you can trace end to end. That is the mechanism.

Separately, when several tools are wired together to run as one repeatable, multi-step process, we call that a workflow in plain language. So a "workflow" is a named recipe you can run, and the "chain" is the fingerprint trail it leaves behind. When this page says run a workflow, it means the runnable recipe; when it says the chain, it means the linked trail of hashes.

Who is this for?

Three audiences, reading the same page from different doors. A compliance officer or auditor gets a decision trail that proves what ran and that nothing was altered after the fact, without having to trust a vendor's word. An engineer gets a small, precise standard with real gates and one canonical way to build a hash. An AI agent gets tools it can discover, call, and verify on its own over MCP.

The Beginner, Practitioner, and Advanced badge on each stage marks the natural entry point for each reader, so you can skim to your level and go deeper only where you need to.

Isn't this basically a blockchain? You're literally chaining hashes together.

The surface similarity is real, both use hash pointers to link data objects into a DAG. But the resemblance ends there. A blockchain requires distributed consensus: a network of nodes that must agree on a shared, append-only ledger. OpenChainGraph has none of that. Each vendor runs their own tool and publishes their own artifact. There is no shared ledger, no mining, no validators, no network to join.

The closer analogy is Git's object model, a directed acyclic graph of content-addressed objects where trust comes from recomputing the hash yourself, not from a consensus mechanism. Or in-toto / SLSA supply chain attestations: hash the artifact, sign it, let anyone verify it independently. OpenChainGraph applies that pattern to financial decision artifacts instead of software build artifacts.

What happens to old artifact hashes if a tool is updated or the model changes?

Old hashes remain permanently valid for the inputs and outputs they were computed over, the hash doesn't "expire." But if a tool changes its computation logic (say, a risk model update) and you re-run the same policy_parameters, the new output_payload will differ, producing a new, different execution_hash. That's correct behavior, it's a different decision.

The recommended practice is to version your tools explicitly: tool_version: "1.2.0" inside the artifact envelope. A downstream tool that cites an artifact from v1.1.0 is permanently linked to that exact version's output. Auditors can distinguish "the credit model on 14 March 2026" from "the updated model on 1 April 2026" by comparing the parent hashes. Version drift is a feature, not a bug, it makes model changes auditable by design.

Can I use OpenChainGraph without MCP? We're not running an AI agent stack yet.

Yes, MCP is an optional integration layer, not a requirement. The core of OpenChainGraph is just a JSON envelope and a SHA-256 hash function. Any tool that emits a JSON artifact with execution_hash and chain.parent_hashes is conformant, regardless of how that artifact is transported, REST API, message queue, file drop, email attachment, or a direct database write.

MCP becomes relevant in Stage 4 (cross-vendor chaining) when you want agents to autonomously discover, call, and chain tools from a chaingraph.json Graph Index. For teams that aren't there yet, the value is simpler: tamper-evident audit trails across your existing pipeline, with no new infrastructure. Add MCP when you're ready, the artifacts are already compatible.

How does this relate to AP2, ACP, x402, and the other agentic payment standards?

Those standards govern payment execution, the mechanics of how an AI agent authorizes and settles a transaction. OpenChainGraph governs decision provenance, the verifiable record of why a decision (including a payment decision) was made, what inputs drove it, and which prior decisions it depended on.

They're complementary layers of the same stack. An AP2-conformant agentic mandate might cite an OpenChainGraph artifact as its authorization evidence: "This payment was authorized because the liquidity stress tool (hash: a3f9…) determined headroom was sufficient, which itself cited the FX hedge optimizer (hash: 7c2b…)." The payment rails handle settlement; OpenChainGraph handles the audit trail upstream of it. Neither standard competes with the other.

The spec says DRAFT, is OpenChainGraph stable enough to implement now?

The DRAFT label is a candid characterization of ecosystem readiness, not technical readiness. The hash construction, the artifact envelope, and the verification procedure are stable and implementable today, the reference implementation exists and works. What isn't ready is the ecosystem: most MCP tool catalogs don't yet exist, most vendors don't yet emit structured JSON artifacts at all, and cross-vendor chaining requires two parties who both follow the spec.

The recommended posture: implement the artifact envelope now in any tool that produces decisions your team (or regulators) will need to audit later. The lift is small, one SHA-256 call and a JSON wrapper. When the ecosystem catches up, agentic payment stacks go mainstream, MCP tool catalogs proliferate, regulators start asking for machine-verifiable decision trails, you'll already be producing conformant artifacts. Standards that arrive late to adoption cycles rarely win.

What's the difference between a Policy Mandate (.policy.json) and an OCG artifact? Both seem to carry an execution_hash.

They serve different layers of the stack. An OCG artifact is the canonical provenance record, the tamper-evident envelope whose execution_hash is the SHA-256 of {policy_parameters, output_payload}. It's designed for auditors, regulators, and downstream tools that need to independently verify a decision. The artifact is the source of truth.

A Policy Mandate (.policy.json) is a browser-side handoff format. AIN Bridge produces one when a tool finishes, it packages the tool's inputs and key outputs into a file the user can drop into the next tool's intake zone. The execution_hash field in the mandate is inherited from the artifact; it's there for traceability, not for the mandate itself to be hashed. Mandates are ephemeral transit containers. Artifacts are the permanent record. If they conflict, the artifact wins.

If Excel and PDF exports are excluded from the execution_hash preimage, how do I know the exported file wasn't tampered with after it left the server?

The export itself doesn't carry a hash of the export, but it embeds the original execution_hash as metadata. That's enough to anchor it. If someone alters the numbers in the Excel file, the execution_hash in the Provenance sheet no longer matches what you get when you re-run the tool with the recorded policy_parameters and verify the output. The mismatch is the tamper signal.

For high-stakes auditing, the correct workflow is: go back to the canonical JSON artifact (not the xlsx), re-run verify_execution_hash, confirm the output_payload matches what the exported file shows. The export is a rendering for humans. The artifact is the thing that's actually tamper-evident. This is the three-layer model: provenance-out (canonical JSON) → knowledge-in (OKF) → rendered-for-review (exports). Only the first layer is in the verification chain.

Does compute_mode:"server" change how I verify the hash? Do I need access to the original server or kernel to reproduce it?

No, compute_mode is completely outside the hash preimage. The hash computation hasn't changed since v0.1: SHA-256 over the RFC 8785 canonical serialization of {policy_parameters, output_payload} with keys sorted. It doesn't matter whether a server ran the kernel, a browser ran the tool, or someone computed the artifact by hand. The math is the same.

What compute_mode: "server" tells you is how the tool was executed, not what was hashed. A verifier that ignores the field entirely will still compute an identical hash. This is intentional: every v0.4 field outside the preimage is strictly informational, it annotates the artifact without affecting its verifiability. A v0.1 verifier from 2025 produces the same result on a v0.4 artifact from 2026.

Is OpenChainGraph only for financial decisions? We're building in healthcare, logistics, or legal.

No. The core spec is entirely domain-agnostic. The mandate_type field is a free string, you can use "diagnostic_result", "routing_decision", "eligibility_check", or anything else. The hash construction, the chain model, the MCP integration layer, and Compute Binding work identically regardless of domain.

The ISO 20022 semantic profile (Stage 8) and the LEI / did:key identity model (Stage 9) are optional addenda for payment tool vendors, they don't affect the core hash preimage and aren't required for conformance. The fintech examples throughout this explainer reflect where the spec authors work, not a constraint on who can implement it. If your tool takes structured inputs, runs a deterministic computation, and produces outputs that someone might later need to audit or dispute, OpenChainGraph is applicable.

Can I adopt Compute Binding (§12) without Export Profiles (§13), or vice versa? Do I need both for v0.4 conformance?

They're fully independent. §12 and §13 address different integration points, §12 is about where computation runs (server vs. browser); §13 is about how verified results are rendered for human consumption. You can ship a gpu:false server-side kernel without ever implementing export_artifact, and you can implement the xlsx/pdf/xbrl export profiles for browser-computed tools without touching Compute Binding.

Capability discovery in chaingraph.json is per-node: compute_capability: "server" and export_capability: ["xlsx","pdf"] are separate fields. An agent calling list_ainumbers_tools sees exactly which capabilities each node advertises and routes accordingly. The chaingraph_version: "v0.4" field in the artifact envelope just signals that the emitting tool understands the v0.4 schema, it doesn't imply both features are implemented.

Does Proof Binding make OpenChainGraph artifacts PII-laden?

No — Proof Binding is default-off, and inputs (policy_parameters) remain PII-free by the standard zero-egress contract. What changes is that the signer’s key identity becomes linkable to the run. The artifact itself carries no personal data. Tools that offer signing MUST clearly communicate that opting in de-anonymizes at the key level — not the payload level.

The zero_pii_verified semantics are unchanged. If you sign with a did:key generated fresh for each session and never published, the run remains practically unlinkable. If you sign with an institutional did:web anchored to your domain, the signer becomes publicly known — which is exactly the point for regulated institutions seeking auditor-grade attestation.

What’s the difference between audit_signature.signatures[] (v0.2 / §4) and audit_signature.proof (v0.5 / §16)?

signatures[] (§4, v0.2) is a DSSE/in-toto envelope — it signs over a payload field that is a base64url encoding of the artifact without audit_signature. It is the v0.2 signing mechanism, optimized for in-toto and Sigstore toolchain compatibility.

proof (§16, v0.5) is a W3C Data Integrity proof using the eddsa-jcs-2022 cryptosuite. It signs over the whole artifact minus proof itself, using the same JCS canonicalizer as the §4 hash construction — no second canonicalization path. The two mechanisms co-exist in the same audit_signature object, are independent, and serve different verifier ecosystems: in-toto/Sigstore consumers use signatures[]; W3C VC / Data Integrity verifiers use proof. Both are optional. A maximally signed v0.5 artifact carries both.