OpenTrustGraph v0

OpenTrustGraph is the open, vendor-neutral data format Harn uses to log agent autonomy decisions as an append-only, hash-chained event stream. This page is the mdbook view of the canonical artifact at opentrustgraph-spec/ in the Harn repo.

The full normative content lives in three places, each linked below:

At a glance

  • Record schema: opentrustgraph/v0.1. One record per autonomy or control-plane decision. Records carry agent, action, approver, outcome, trace_id, autonomy_tier, timestamp, cost_usd, chain_index, previous_hash, entry_hash, and an extensible metadata bag. v0.1 reserves three keys at the metadata layer — effects_grant, effects_used, and parent_record_id — so chain validators can prove that a child agent's effects_used stayed inside the parent's effects_grant. opentrustgraph/v0 records still validate for one patch release window per opentrustgraph-spec/CONFORMANCE.md §5.
  • Chain export: opentrustgraph-chain/v0. Wraps an ordered record list with chain.topic, chain.total, chain.root_hash, chain.verified, chain.generated_at, and chain.producer.
  • Hash contract: SHA-256 over a canonical JSON form of the record with entry_hash removed and object keys sorted lexicographically at every nesting level. Stored as sha256:<hex>.
  • Wire formats: JSON is canonical; Protobuf is provided as a mirror for streaming runtimes.

Why an open spec

Strategic positioning aside, the practical reasons:

  1. Receipts are portable. A Harn Cloud receipt, a Burin supervision UI screenshot, and a third-party auditor's offline verifier all read the same JSON envelope.
  2. Multi-runtime adoption. Other schedulers (Temporal histories, Inngest events, Kafka topics) can project the same record into their substrate without inventing a parallel audit shape.
  3. Spec, schema, fixtures, verifier in one tree. The artifact under opentrustgraph-spec/ is small enough to vendor today and direct- publish as burin-labs/opentrustgraph-spec later without changing the format.

Producing a chain export

Inside Harn, emit the canonical envelope with:

harn trust-graph export --output chain.json
harn trust-graph export | python3 opentrustgraph-spec/examples/python/verify_chain.py

The export envelope has its chain.verified flag set from the underlying chain verification result, so a downstream consumer can short-circuit on a failed export instead of re-running verification.

Consuming a chain export

External consumers (Python, Go, TypeScript, …) follow CONFORMANCE.md §2:

  1. Validate against the chain JSON Schema.
  2. Validate every record against the record JSON Schema.
  3. Recompute every entry_hash and compare to the stored value.
  4. Compare each previous_hash to the prior entry_hash.
  5. Compare chain.total and chain.root_hash to the record list.

The reference Python verifier at opentrustgraph-spec/examples/python/verify_chain.py implements all five checks in ~150 lines using only the standard library, and it is exercised against every fixture in opentrustgraph-spec/fixtures/.

Fixtures and test vectors

FixtureStatusWhat it exercises
fixtures/valid/decision-chain.jsonacceptTwo-record chain with a control-plane promotion
fixtures/valid/tier-transition.jsonacceptThree-record chain ending in an approved action
fixtures/invalid/tampered-chain.jsonrejectSelf-consistent record but broken previous_hash
fixtures/invalid/missing-approval.jsonrejectapproval.required = true with no approver

These fixtures are normative test vectors. The Harn runtime parses them in crates/harn-vm/src/trust_graph.rs::tests::opentrustgraph_* so the spec artifact and the runtime contract stay in lockstep.