The protocol

BitGraph is a protocol with one operation: a measured trusted execution environment allocates an unpredictable, single-use position, signs it while it holds no digest, and later binds a SHA-256 digest to that position, consuming it and emitting a portable signed proof linked to its predecessor. Each position is opened on a public floor, a Base block the enclave binds into it. This page states that precisely, for readers who want the definitions rather than the story.

Five things, five words

Every claim on this site is made with these, and each has one name here: what stays on your machine, what crosses to the enclave, what exists there before it arrives, the step that binds the two, and what you keep afterward.

The record
Any file: a trust record, a log, an evaluation result, a model output. BitGraph never receives it.
The fingerprint
The record’s SHA-256 digest, 32 bytes. It becomes a leaf of a small tree, and only the hash of that tree’s root document is sent. Change one byte and the fingerprint changes.
The position
A place in a signed sequence, allocated by the enclave before it has received any fingerprint. The proof’s fields call an allocated position a slot (slotAllocation).
The commit
The single step that binds the fingerprint to the position, consumes the position, and signs the result. A position can be consumed once, and never reused.
The BitGraph
Also called the proof: the signed result of that commit, returned to whoever asked. It carries the signed position record, both counters, the signature, a hardware attestation and the floor. It travels in an export, one JSON file kept beside the record with SPEC.md.
1. UNUSEDposition #4,201a nonce from hardware entropy, a counter,the epoch, the enclave’s key. Signed.No fingerprint has been received.later2. CONSUMEDthe recordstays with youSHA-256 fingerprintposition #4,201 · commit #4,202fingerprint bound, position consumed, body signedand attested, in one stepNo partial state exists.
1. UNUSEDposition #4,201nonce, counter, epoch, key. Signed.No fingerprint has been received.2. CONSUMEDthe record stays with youSHA-256 fingerprintposition #4,201commit #4,202bound, consumed, signed, attested: one stepNo partial state exists.
Numbers are illustrative. Position 4,201 is allocated while it holds nothing. The commit that fills it is the next event in the sequence, 4,202, and it is the one step in which the fingerprint is bound, the position is consumed and the result is signed. The BitGraph carries both numbers, and the slot’s is always the smaller.

Terms

TermDefinition
ArtifactThe byte sequence a user records. Never transmitted to the protocol.
Exact bitsThe precise bytes, with no normalization or re-encoding. Byte identity is the unit of every claim.
DigestSHA-256 of the exact bits, standard base64. The only representation of the artifact the protocol handles. Fields: artifact.hashAlg, artifact.digestB64.
Position recordA signed record allocated inside the boundary: a fresh nonce, a counter, the epoch identifier, the boundary’s public key, and an optional chain identifier. It contains no artifact data, and no floor: the floor is fixed by the enclave at allocation and signed into the proof at commit as commit.slotFloor (commit.slotAnchor on earlier proofs). Schema bitgraph/slot/1, in the proof as slotAllocation.
Nonce32 bytes from the Nitro hardware random number generator, drawn at allocation. Its generation before any digest is received is the authorization event.
AllocationCreating and signing a position record. Advances the chain counter by one.
UnusedA position present in the boundary’s in-memory pending table and not yet consumed. Expires after 120 seconds.
BindingPlacing the digest and the hash of the position record in one canonical body, signed by the boundary’s Ed25519 key.
ConsumptionDeleting the position from the pending table, synchronously, at the start of commit handling. Irreversible within the epoch.
CommitBinding and consumption together with signing and attestation, as one indivisible step. Advances the counter by one more, so one recording spans two counter values.
CounterA per-chain monotonic integer carried as a decimal string and compared as a big integer.
Previous linkcommit.prevB64: SHA-256 of the canonical form of the entire previous proof on the same chain.
ChainAn ordered series of proofs sharing a chain identifier. The public sequence is bitgraph:main.
EpochOne enclave lifecycle: a fresh keypair at boot, a counter at zero, and a key that is destroyed at shutdown. One UTC day in production.
Epoch identifierepochId = base64(SHA-256(public key + ":" + boot nonce)).
ProofA bitgraph/1 object. See proof format.
TreeThe form of every recording since 2026-10-04, tree/1: one position for one or more artifacts, each a leaf named by its digest and placement; one artifact is a tree of one. Earlier forms (a single fused file, set/1, set/2) still verify. SPEC.md section 8.
Root document84 bytes: the domain bitgraph-tree/1, the leaf count, the Merkle root and the position commitment. Its SHA-256 is the signed artifact.digestB64. Echoed unsigned in metadata["bitgraph-tree/1"].
Spec pinThe signed marker attribution = { name bitgraph-fuse/3 (bitgraph-fuse/2 on earlier proofs), title tree/1, message base64 SHA-256 of SPEC.md }. A verifier that does not know the hash answers undetermined, never true.
ExportA bitgraph-export/1 JSON: the proof, the root document, one member’s leaf and path or the owner’s whole leaf list, and the floor header, the ceiling and the settlement when they exist. No copy of any file, no anchor proofs. SPEC.md travels beside it.
Recovery entryA sealed record of one member, stored under names derived from the artifact’s digest, which is never itself indexed. It lets the artifact alone find its proof again. SPEC.md section 13.
BoundaryThe AWS Nitro enclave process. Holds the signing key, the random number generator, the counters and the pending positions.
MeasurementThe enclave image identity, PCR0, signed into every proof as environment.measurement.
AttestationA document signed by the Nitro hardware whose user data is SHA-256 of this proof’s canonical signed body. Per proof, not per boot.
FloorThe newest Base block when a position opened. The enclave hashes its header itself, checks the time against Base mainnet’s schedule for its number and against its own clock, never lets floors go backwards, and signs the block into the proof at commit as commit.slotFloor; the position record itself does not carry it. A lower bound in time. Earlier proofs carry an Ethereum anchor instead, commit.slotAnchor.
AnchorEarlier proofs only: a proof on the same chain whose digest is derived from a recent Ethereum block hash, with the block number and hash signed into commit.anchor. The latest anchor when a position was allocated was that position’s floor.
Order afterThe next BitGraph in the chain, whose proof carries this proof’s hash. A bound in position; it does not convert to a clock reading.
Ceiling in timeThe Base block that includes a Merkle root over the record’s proof hash, written after the commit by a published writer. Carried beside the proof in a ceiling file, never inside it.
Anchor witnessEarlier proofs: an Ethereum block header, re-encoded and self-checked, that lets a verifier read a block’s time offline after confirming its keccak-256 equals the anchored hash.
VerifierAny party holding a proof, optionally the bytes, and a trust policy. Verification is offline and deterministic.
Enforcement tierstub, hw-key or measured-tee. Signed, self-reported, and not self-authenticating.

The lifecycle of one recording

Steps marked [boundary] run inside the enclave. Everything else runs on an untrusted machine.

  1. Initialization [boundary]The enclave boots, generates an Ed25519 keypair in memory, draws a boot nonce, computes the epoch identifier and reads PCR0. In production every boot is a fresh genesis; an epoch is never continued from a predecessor.
  2. Allocation [boundary]On request, the enclave advances the chain counter, draws a 32-byte nonce, and signs the position record: version, nonce, counter, epoch, public key, chain. Beside it, the enclave binds the newest Base block, from a header it hashes and checks itself, which it signs into the proof at commit as the floor. The position is stored as unused, keyed by nonce, with a 120-second lifetime and a ceiling of 1,000 pending positions.
  3. Digest computationOutside the boundary, the client derives the position commitment from the position record and the floor, builds each artifact’s committed bytes with it, hashes them, and makes one leaf per artifact. The leaves form a Merkle tree; the tree’s root, the leaf count and the commitment form the 84-byte root document, and its SHA-256 is the digest the commit carries. On this site, in the SDK and in the MCP server, the bytes never leave the client.
  4. Commit [boundary]The enclave looks the position up and deletes it before any asynchronous work, advances the counter again, assembles the signed body with the digest, both counters, the position record’s hash and the previous link, adds attestationFormat, canonicalizes, hashes, requests a Nitro attestation over that hash, and signs the same bytes with Ed25519. Attestation and signature therefore cover byte-identical input.
  5. Linking [boundary]The chain’s stored last-proof hash becomes the hash of this proof, so the next proof’s previous link names it.
  6. CeilingSeconds after the commit, a writer outside the enclave puts a Merkle root over the new proofs’ hashes into one Base transaction from a published address. Base later posts that block’s batch data to Ethereum. (Earlier, an external anchor service also submitted recent Ethereum block hashes, which the enclave committed as ordinary proofs on the same chain; those anchors were the floors of earlier proofs.)
  7. ExportThe client writes a bitgraph-export/1 JSON beside the artifact: the proof, the root document, this member’s leaf and path (or the owner’s whole leaf list), and the floor block header. It holds no copy of the artifact and no anchor proofs. SPEC.md, byte for byte the text the proof pins, travels beside it. The ceiling in time and its settlement are filled in later, with bitgraph export complete.
  8. RecoveryAfter the export exists, the client writes one sealed recovery entry per member under names derived from the artifact’s digest. A later holder of the artifact alone can find the proof again. A lookup that did not complete is unknown, and unknown is not new: no client records the artifact again unless the person asks regardless.
  9. VerificationAnyone repeats the checks offline, with the artifact and its export. See verification.

Two orderings cannot be rearranged. Steps 2 and 3 must complete before step 4 begins, and within step 4 the attestation must be taken over the same bytes the signature covers. Reordering either breaks the guarantee rather than weakening it.

Invariants

Each invariant names what enforces it in the published source and what its violation would look like. The verifier is packages/verify/src/verifier.ts; the enclave is server/commit-service/src/enclave/app.ts.

InvariantEnforced byA violation looks like
Allocation precedes the digestThe position record has no field for artifact data and is signed at allocation; the commit signature covers slotHashB64.A position record carrying artifact-derived data, or a commit whose position-record hash does not match the embedded record.
Position freshness32 bytes from the hardware RNG per position.Two positions sharing a nonce.
Single consumptionThe position is deleted synchronously after lookup; the event loop is single-threaded.Two proofs sharing commit.nonceB64 in one epoch.
Digest bindingartifact.digestB64 is inside the signed body; verifiers recompute and compare in constant time.A digest mismatch, or a verifier that reports valid without comparing.
Signature integrityEd25519 over deterministic canonical JSON: recursive key sort, compact, UTF-8.Any divergence between the signed body and the body a verifier reconstructs.
Ordering within an epochA per-chain counter and the previous-proof hash chain.A broken previous link, or two proofs naming the same predecessor.
Epoch isolationA new keypair per boot; the counter resets; the epoch identifier is in the signed body.A proof under a destroyed key, which cannot exist.
Exact-bit identitySHA-256 over raw bytes; no canonicalization of artifact content anywhere.A verifier that decodes, re-encodes or strips metadata before hashing.
No transformation inside the boundaryThe commit path receives a digest and cannot transform anything.An output digest that differs from what the caller believes it recorded.
Portable verificationverify() performs no network calls; the floor header, the ceiling and the settlement travel in the export.A verification step that silently requires a lookup.
Explicit time semanticsThe floor is a public block signed into the proof; the ceiling is a public write after the commit; each is stated as the bound it is.A one-sided bound presented as a timestamp.
Content claims separated from path claimsNo field asserts anything about content. attribution is a claim; metadata is unsigned.Copy or a label implying verified truth or authorship.

Counter gaps are normal. Allocation advances the counter, and a position that expires unused leaves its value with no proof behind it. Ordering rests on the previous link, not on counter contiguity, so a gap never indicates a missing record. A missing record can only be shown against an external expectation of what should be there.

Deployment choices, not protocol rules

These are current values and could change without changing the protocol.

  • Two counter increments per recording (allocation and commit).
  • The 120-second lifetime of a reserved position and the ceiling of 1,000 pending positions.
  • Base as the floor and ceiling chain (Ethereum for floors on earlier proofs).
  • AWS Nitro as the boundary. Another attested environment could serve; the schema names no platform.
  • The daily restart at 23:59 UTC, which makes an epoch one calendar day.
  • BitGraph’s public copy of proofs, earlier anchors and floor headers, under a ten-year compliance lock. A strong operational property, and a deployment property rather than a protocol guarantee.

Enforcement tiers

TierKey locationCommit gateMeaning
measured-teeEnclave memoryInside the measured boundaryFull causal enforcement. Production, and the only tier bitgraph.ing issues.
hw-keyHSM or secure elementOutside the boundaryHardware-bound identity without causal enforcement: the host feeds digests to the key.
stubProcess memorySoftwareDevelopment and testing only.

The tier is signed, which prevents downgrade in transit, but it is self-reported. A verifier that needs enclave guarantees pins measurement to a known image and validates the attestation, which a software tier cannot produce.

Structural properties of the commit path

One route
Every proof corresponds to exactly one commit through the boundary. Bytes that did not pass through it cannot acquire a valid proof, however they were made.
Closure
The set of proofs is exactly the set produced by commits. There is no second route into it.
Atomicity
Consumption, binding, signing and attestation are one indivisible transition. There is no observable state in which a position is partly consumed or a body is bound but unsigned.
Uniqueness
Each commit produces a distinct proof. The same bytes committed twice occupy two different positions, neither of which outranks the other.

Where next

  • Proof formatEvery field of a bitgraph/1 proof, with what is signed and what is not.
  • SPEC.mdThe normative text for tree/1, the export, recovery entries and verification: the file every proof pins by hash.
  • Trust modelWhat is assumed, what is prevented, what is detected, and what is neither.
  • VerificationThe checks a verifier runs and what each result means.
  • The sourceThe enclave, the verifier and the audit tool, readable and reproducible.