OpenChainGraph v0.3 · Integration How-To

Using OpenChainGraph with W3C PROV-DM

If you're already working with W3C PROV-DM (building provenance graphs, querying triple stores, or running ProvToolbox pipelines), this guide shows you exactly how OpenChainGraph artifacts fit into your existing workflow. No rearchitecting required: OCG artifacts are PROV entities by construction, and the @context URL makes them natively readable by any JSON-LD/PROV-aware processor.

§1

The @context field is the bridge

Every OpenChainGraph v0.3 artifact includes a "@context" field set to "https://ainumbers.co/chaingraph/context/v0.3". This is a JSON-LD context document that maps OCG field names to their W3C PROV-DM equivalents. The implication is direct: you don't need to transform OCG artifacts before feeding them to PROV-aware tools. They are already PROV entities.

The mapping is one-to-one at the semantic level. Each OCG field corresponds to a well-defined PROV-DM term:

OCG Field PROV-DM Term Meaning
artifact itself prov:Entity The artifact is a provenance entity, a thing with identity that can be derived from other things
tool_id prov:wasAttributedTo The tool that produced this artifact is the attributed agent
policy_parameters prov:used The inputs consumed during computation
output_payload prov:wasGeneratedBy The outputs produced by the computation
parent_hashes[] prov:wasDerivedFrom Each parent hash is a derivation edge: this artifact was derived from those prior artifacts
execution_hash prov:hadPrimarySource The canonical, cryptographically verifiable identifier for this entity

Below is an annotated OCG artifact showing the PROV-DM mapping inline. The @context field is what enables a JSON-LD processor to resolve these mappings automatically.

json Annotated OCG v0.3 artifact with PROV-DM field mapping
{
  "@context": "https://ainumbers.co/chaingraph/context/v0.3",    // makes this a PROV entity
  "tool_id": "detect_anomalies_v3",                       // prov:wasAttributedTo
  "mandate_type": "risk_control",
  "policy_parameters": {                                   // prov:used
    "threshold": 0.05,
    "window": "30d"
  },
  "output_payload": {                                      // prov:wasGeneratedBy
    "anomaly_score": 0.82,
    "flag": true
  },
  "execution_hash": "sha256:3f9a1b2c8d7e4f0a...",          // prov:hadPrimarySource
  "chain": {
    "parent_hashes": ["sha256:7c2e4d8f..."],               // prov:wasDerivedFrom (one per parent)
    "depth": 1,
    "chain_name": "fraud_detection_chain"
  },
  "buildType": "https://ainumbers.co/chaingraph/context/v0.2#WebCryptoSHA256"
}
Key point

A root artifact (depth 0) has an empty parent_hashes array and maps to prov:Entity with no prov:wasDerivedFrom edges: it is the provenance root. Every downstream artifact in the chain adds one or more derivation edges.

§2

Processing OCG artifacts as PROV entities

Because OCG artifacts carry a JSON-LD @context, any JSON-LD processor can expand them into full PROV-DM triples with no custom mapping code. The jsonld npm package and pyld Python library both handle this in a single function call.

Once expanded, the output can be serialized to N-Quads and loaded directly into any RDF triple store: GraphDB, Virtuoso, Apache Jena, or an in-memory store like rdflib. From there, SPARQL queries traverse the chain natively.

javascript Expand OCG artifact to PROV triples using jsonld npm package
import jsonld from 'jsonld';

const artifact = { /* OCG artifact object from tool output */ };

// Expand: resolves @context and returns full PROV-DM URI form
const expanded = await jsonld.expand(artifact);
// expanded[0]['http://www.w3.org/ns/prov#wasDerivedFrom'] → parent_hashes
// expanded[0]['http://www.w3.org/ns/prov#hadPrimarySource'] → execution_hash
// expanded[0]['http://www.w3.org/ns/prov#wasAttributedTo'] → tool_id agent

// Serialize to N-Quads for import into any RDF triple store
const nquads = await jsonld.toRDF(artifact, { format: 'application/n-quads' });
// Now importable into GraphDB, Virtuoso, Apache Jena, or rdflib
python Expand OCG artifact to PROV triples using pyld
from pyld import jsonld

artifact = { # OCG artifact dict loaded from JSON
    "@context": "https://ainumbers.co/chaingraph/context/v0.3",
    "tool_id": "detect_anomalies_v3",
    # ... remaining fields
}

# Expand to full PROV-DM URI form
expanded = jsonld.expand(artifact)

# Serialize to N-Quads
nquads = jsonld.to_rdf(artifact, {'format': 'application/nquads'})

# Load into rdflib for local querying
import rdflib
g = rdflib.ConjunctiveGraph()
g.parse(data=nquads, format='nquads')

# Or POST to an Apache Jena Fuseki endpoint
import requests
requests.post(
    'http://localhost:3030/ocg/data',
    data=nquads,
    headers={'Content-Type': 'application/n-quads'}
)
§3

SPARQL: querying the chain

Once OCG artifacts are loaded into a triple store as PROV entities, SPARQL property paths can traverse the prov:wasDerivedFrom links to reconstruct the entire provenance chain from any artifact back to the root. This works because each parent_hashes entry becomes a separate prov:wasDerivedFrom triple, which SPARQL's * path operator traverses recursively.

sparql Reconstruct full chain from a given artifact hash to root
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX ocg:  <https://ainumbers.co/chaingraph/vocab/>

SELECT ?artifact ?parent ?depth WHERE {
  ?artifact prov:wasDerivedFrom* ?parent .
  ?artifact ocg:execution_hash ?hash .
  ?artifact ocg:chain_depth ?depth .
  FILTER(?hash = "sha256:3f9a1b2c8d7e4f0a...")
}
ORDER BY ASC(?depth)
Note on multi-parent artifacts

The parent_hashes array becomes multiple prov:wasDerivedFrom triples, one per parent. SPARQL traverses these naturally with property paths (*), so diamond-shaped provenance graphs (where two chains converge) are handled without special-casing.

A second useful query pattern is finding all artifacts produced by a specific tool, useful for auditing a tool's complete decision history across all chains:

sparql Find all artifacts attributed to a specific tool
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX ocg:  <https://ainumbers.co/chaingraph/vocab/>

SELECT ?artifact ?hash ?chain_name WHERE {
  ?artifact prov:wasAttributedTo ?agent .
  ?agent ocg:tool_id "detect_anomalies_v3" .
  ?artifact ocg:execution_hash ?hash .
  ?artifact ocg:chain_name ?chain_name .
}
ORDER BY DESC(?chain_name)
§4

Using ProvToolbox and PROV-N

PROV-DM has a human-readable textual notation called PROV-N. If your team uses ProvToolbox (the W3C reference implementation in Java) for validation, visualization, or format conversion, OCG artifacts translate directly into PROV-N representation. Below is how a single artifact link in a chain would appear:

prov-n PROV-N representation of one OCG artifact and its chain link
// Two entities: the artifact (depth 1) and its parent (depth 0)
entity(ocg:3f9a1b2c, [prov:hadPrimarySource="sha256:3f9a1b2c8d7e4f0a..."])
entity(ocg:7c2e4d8f, [])

// Attribution: produced by detect_anomalies_v3
wasAttributedTo(ocg:3f9a1b2c, agent:detect_anomalies_v3)

// Derivation: child was derived from parent
wasDerivedFrom(ocg:3f9a1b2c, ocg:7c2e4d8f)

// Activity: the computation run that consumed the parent and generated the child
used(run:r1, ocg:7c2e4d8f)
wasGeneratedBy(ocg:3f9a1b2c, run:r1)

ProvToolbox's Java library (org.openprovenance.prov) supports round-tripping between PROV-N, PROV-JSON, PROV-XML, and RDF. Use it to validate your OCG artifact graphs against PROV constraints before storing them in a compliance archive.

Activity nodes

OCG does not require prov:Activity records: the tool itself acts as both Activity and Agent in the simplified model. If your PROV schema requires explicit Activity nodes, add synthetic run:r1 activity nodes keyed on (tool_id, execution_hash); these are stable, deterministic identifiers that won't conflict across runs.

§5

Verifying the chain using PROV constraints

W3C PROV-CONSTRAINTS (a W3C Recommendation) defines formal validity rules for provenance graphs. OCG's directed acyclic graph (DAG) structure is always a valid PROV derivation graph by construction: the spec enforces this through the depth rule.

The key OCG invariant that maps to PROV's acyclicity requirement is:

text OCG depth invariant (enforced by all conformant tools)
depth(artifact) = max(depth(parent) for parent in parent_hashes) + 1

Root artifact:  depth = 0,  parent_hashes = []
Child artifact: depth = 1,  parent_hashes = [root.execution_hash]
Grandchild:     depth = 2,  parent_hashes = [child.execution_hash]

Consequence: no artifact can reference a descendant as a parent.
This is structurally equivalent to PROV's acyclicity constraint.

When validating OCG artifact graphs with a PROV-CONSTRAINTS validator (e.g., via ProvToolbox or the W3C online validator), the following constraints are automatically satisfied:

PROV Constraint OCG Guarantee
Acyclicity Depth monotonicity: child depth always strictly exceeds parent depth
Entity identity execution_hash is a globally unique, content-addressed identifier: no two different computations can produce the same hash
Attribution completeness tool_id is always present; every entity has exactly one attributed agent
Generation uniqueness Each artifact is generated by exactly one computation (its own tool execution); the hash encodes both inputs and outputs
Verification procedure

Any party can independently verify an OCG artifact's integrity: re-sort the policy_parameters and output_payload keys recursively, serialize with JSON.stringify, compute SHA-256 via crypto.subtle.digest, and compare to execution_hash. This is the same check ProvToolbox's validator would run against prov:hadPrimarySource. No trusted third party is required.

§6

Integration checklist

Five steps to integrate OpenChainGraph artifacts into an existing W3C PROV-DM toolchain. Each step can be verified independently before proceeding.

Step Action Verified by
1 Confirm tool emits v0.3 artifacts with @context field set to https://ainumbers.co/chaingraph/context/v0.3 JSON schema validation: check @context key presence and exact URI value
2 Load artifacts into a JSON-LD processor (jsonld.expand() or pyld.expand()) jsonld.expand() returns objects with prov: URIs as keys; confirm wasDerivedFrom and hadPrimarySource appear
3 Import N-Quads into your triple store (GraphDB, Virtuoso, Jena, rdflib) SPARQL SELECT COUNT(*) WHERE { ?s ?p ?o } returns expected artifact count
4 Run prov:wasDerivedFrom* property path query to traverse chain Chain reconstruction query (§3) returns all ancestors down to depth 0 root
5 Optional: export PROV-N via ProvToolbox for human-readable audit trail ProvToolbox provconvert validate command exits cleanly with no constraint violations
What you don't need to do

You do not need to build a custom OCG-to-PROV mapper, define new SPARQL ontology predicates, or restructure your existing provenance graph. OCG artifacts drop in as additional PROV entities alongside whatever your existing tools already emit. The @context handles semantic alignment automatically.