Ivaronix

How a private review becomes a public receipt.

Seven explainers — one per moving part of the system. Read them in any order. The home page links here from each module card; jump straight to the section you came for.

Four small lights tell you what was checked.

Every receipt page renders the same four-pill row. Each pill goes green only when the corresponding check passes against live data, not against a cached flag. The same row sits next to the Run button before submission: pending, then in-progress, then verified or mismatch.

The actual component, rendered with all four verified:
StorageverifiedComputeverifiedTEEverifiedChainverified

Storage

0G Storage

Green when: The receipt body has been fetched back from 0G Storage and its keccak256 matches the receiptRoot recorded inside the receipt itself.

Amber when: The blob is not reachable, or the bytes returned by the indexer do not hash to the receiptRoot. Either is a tamper signal worth surfacing.

Compute

0G Compute provider

Green when: The inference ran on a 0G Compute provider whose router_flag was set, or whose attestation was confirmed post-hoc through broker.processResponse.

Amber when: The run used an external provider (NVIDIA NIM · OpenAI · local Ollama). The output is still signed and chain-anchored, but it is not TEE-attested. We render this amber by design.

TEE

Provider TEE attestation

Green when: The verificationMethod field is one of router_flag or compute_sdk_process_response. Re-running the broker check from a separate machine returns the same attestation.

Amber when: verificationMethod is external-signed. The plaintext was visible to the operator of whichever model served the request.

Chain

0G Chain registry

Green when: A read of the on-chain registry at chainAnchor.registryAddress confirms the receiptRoot is stored against chainAnchor.onChainId, signed by the recovered agent.ownerWallet.

Amber when: The on-chain row does not match the off-chain JSON. Usually means the receipt JSON was edited after anchoring, or the wrong receipt id was looked up.


Four locations. Different visibility at each.

A receipt is the record of a transit. The plaintext moves from your browser into a hardware enclave, then leaves only as ciphertext and as a signed summary. Each ring is a different trust boundary; reading them inward, sensitivity rises and audience shrinks.

Interactive sovereignty diagram — coming with the next visual pass.
  1. RING 01
    Your browser

    Content: Plaintext of the document, plus the session key used to encrypt it.

    Reads: You. The key is generated client-side and never written to disk.

  2. RING 02
    A 0G Compute TEE

    Content: Plaintext, for the duration of the inference run only.

    Reads: The TEE itself. The provider operator does not see the inside of the enclave.

  3. RING 03
    0G Storage

    Content: The encrypted blob (when the run wrote one) plus the signed receipt JSON.

    Reads: Anyone with the storage root can fetch the ciphertext; only key-holders can decrypt.

  4. RING 04
    0G Chain

    Content: The receiptRoot, the agent address, the receipt type code, the timestamp.

    Reads: Everyone. The chain is the part designed to be publicly readable.

After the run, ring one is empty. The session key is zeroed in memory and its fingerprint is the only artifact retained. See §06 — Burn mode for what that fingerprint proves and what it cannot.


Two tiers. Both are honest. One is stronger.

Not every model lives behind a TEE today. We sign and anchor anyway, but we draw the line in the receipt itself. The single field verificationMethod decides which tier renders, and the colour follows from the value — green for TIER 1, amber for TIER 2. The page refuses to render any other combination.

TIER 1

TEE-verified

verificationMethod
router_flag · compute_sdk_process_response
Provider
0G Compute provider
Plaintext visible to
The provider TEE only. Operator-side disclosure is out of scope.
Independent replay
Re-run broker.processResponse against the recorded provider address on any machine.
TIER 2

External-signed

verificationMethod
external-signed
Provider
NVIDIA NIM · OpenAI · local Ollama
Plaintext visible to
The provider operator. We do not pretend otherwise.
Independent replay
Signature recovery and chain anchor still verify. The TEE chip stays grey.

TIER 2 exists because some skills do not yet have a TEE-hosted equivalent, and we would rather ship a signed amber receipt than no receipt at all. The receipt page surfaces the tier in three places: the header chip, the four-light TEE pill, and the model attribution block. A judge can read any of the three and reach the same conclusion.

Honest amber beats a green light that does not check out.


One schema. Thirteen slots. One canonical hash.

A receipt is a JSON object validated against a single Zod schema. The type field picks one of thirteen slot codes; the chain rejects anything else. Across all slots, the recipe for the on-chain identity of the receipt is the same: a deterministic byte serialization, hashed with keccak256, signed by the agent wallet.

# canonical hash derivation
1. drop signature, id, chainAnchor
2. sort all object keys recursively · arrays preserve order
3. serialize to UTF-8 JSON · no whitespace · per RFC-8785 JCS
4. receiptRoot = keccak256(bytes)
5. sign receiptRoot with agent.ownerWallet (eth_personal_sign)
6. anchor receiptRoot + signature on 0G Chain

The reason this list is in this order is that step three — RFC-8785 JCS — pins the byte sequence across languages. A verifier written in Go or Rust reaches the same receiptRoot from the same JSON. That property is what lets a third-party auditor run their own verification without our code.

The thirteen slots

Slot codes are part of the on-chain row. The slot was promoted from 10 to 13 by ReceiptRegistryV3 on testnet; V2 admits 0-9, V1 admits 0-9.

doc_askslot 0
auditslot 1
consensusslot 2
burnslot 3
memory_accessslot 4
skill_execslot 5
code_changeslot 6
passport_updateslot 7
swarmslot 8
subscription_skill_execslot 9
doc_room_createslot 10
doc_room_readslot 11
memory_consolidationslot 12

Today the chain holds 44 anchored receipts and 4 minted agent passports. Both numbers are read from the public chain at the moment this page loaded; no cache, no synthetic data.

For the full field-by-field map and the slot mapping across V1, V2, and V3, see docs/RECEIPT_SCHEMA.md.


One role, three, five, or six. Pick the depth the work deserves.

Consensus is monotone: each higher tier strictly extends the one below it. The judge role is always last. The composition is set in code, not in a manifest field a skill author can fudge.

TierRolesWhen to use it
Quick
Lowest latency · single role
analyst
Single-pass answer. Fastest path. Use when the question has one defensible answer and you trust the model on the topic.
Standard
Three roles · one objection cycle
analystcriticjudge
Analyst writes an answer; critic objects; judge resolves. Adversarial review for everyday work where you want a second opinion baked in.
High-stakes
Five roles · longer chain
analystcriticrisk-reviewerevidence-checkerjudge
Legal, contract, financial review. Risk-reviewer and evidence-checker join the standard tier. Use this for term sheets and indemnity clauses.
Audit
Six roles · longest chain
analystcriticrisk-reviewerevidence-checkerred-team-criticjudge
The premium adversarial tier. A red-team-critic sits on top of high-stakes, trying to break the case the other roles built. Use this when the receipt has to survive a hostile reader.

Convergence between roles is scored with a tokenized Jaccard plus an embedding-cosine pass. Below a default threshold of 0.6, the receipt records "no convergence" rather than a fake agreement. A skill manifest can raise the threshold for the high-stakes and audit tiers via og.consensus.threshold.


The session key dies at the end of the run.

Burn mode is a specific, narrow promise: at the end of an inference run, the symmetric key that encrypted the document is overwritten with zeros, and its sha256 fingerprint is captured beforehand so the receipt can attest the destruction. The blob on 0G Storage stays but is no longer decryptable by anyone, including us.

What burn mode defends

  • Operator-side disclosure after the run. A subpoena to us cannot produce plaintext we no longer hold the key for.
  • Long-tail re-reads. A storage-layer breach in 2028 returns ciphertext nobody can decrypt.
  • Vendor lock-in panic. The receipt is intact even if our service is offline; the document under it is unreadable.

What burn mode does not defend

  • A compromise of your local machine before or during the run. Plaintext sits in your browser memory while you draft the prompt.
  • A side channel inside the TEE itself. Burn mode is upstream of the enclave guarantees; if the enclave leaks, burn mode does not patch that.
  • A copy you made and stored elsewhere. Burn mode acts on the canonical blob, not on screenshots you took.

The cryptographic invariants

  • AES-256-GCM. 256-bit session key from crypto.randomBytes(32).
  • 96-bit GCM nonce from crypto.randomBytes(12). Never derived from time or content.
  • Blob layout: nonce (12) ‖ ciphertext ‖ tag (16). Self-contained.
  • Fingerprint sha256(key) is captured before the buffer is zeroed. The order matters.
  • The fingerprint, the destruction timestamp, and the algorithm tag land in the receipt's burn block.

Source: packages/og-storage/src/burn.ts. Read the threat-model JSDoc; it is the canonical statement.


Hard questions, short answers.

A receipt says "FULLY VERIFIED". What was actually verified?
The four checks named in §01: the stored blob hashes to the recorded root, the inference ran on a 0G Compute provider, the TEE attestation re-checks, and the chain row matches the off-chain JSON. The label does not claim the answer inside the receipt is correct. It claims the process that produced the answer is what the receipt says it was.
Does the chain see my document?
No. The chain stores receiptRoot, the agent address, the type code, and the timestamp. The document content is encrypted at rest on 0G Storage; the chain has no copy.
Why is some receipt amber and not green?
The TEE pill is amber when the inference ran on an external provider — NVIDIA NIM, OpenAI, or a local model — instead of a 0G Compute TEE. Signature and chain anchor still verify, but the operator of that external provider had visibility into the plaintext for the duration of the call. See §03 for the precise field that decides this.
Can I verify a receipt without trusting your code?
Yes. The canonical hash is RFC-8785 JCS over the receipt body minus three fields. Any implementation in any language reaches the same root from the same JSON. We ship a CLI verifier and a public proof page, but you do not need either; a third-party auditor can write their own and reach the same answer.
What happens when burn mode runs and the storage indexer is later offline?
The receipt JSON still verifies — signature, hash, chain anchor — even if 0G Storage cannot return the ciphertext. The four-light row would show Storage amber and the others green; the proof page tells you exactly which leg is unavailable.
What is a passport, and why do I need one?
The passport is an ERC-7857 INFT that binds your agent identity to the wallet that signs receipts. Trust score accrues to the passport, not to the operator. Without a passport, a receipt cannot be signed by an identity the chain recognises. See /agents for what is live today.
How is this different from a vendor data room?
A data room produces an access log on the vendor's servers, under the vendor's subpoena schedule. A receipt is signed by the wallet that ran the review and anchored on a public chain. The audit trail outlives the vendor relationship; you do not pay for the right to be audited by us.

Glossary

receiptRoot
The keccak256 of the canonical JCS-serialized receipt body (minus signature, id, chainAnchor). The signature is over this value. The on-chain anchor stores this value.
verificationMethod
The single field that picks TIER 1 (router_flag or compute_sdk_process_response) vs TIER 2 (external-signed). Lives at teeVerification.verificationMethod.
agent.ownerWallet
The EVM address recovered from the receipt signature. Must match the wallet that owns the passport at agent.passportId.
keyFingerprint
sha256 of the burn-mode session key, captured before the key buffer is zeroed. Lives at burn.sessionKeyFingerprint.
convergence
A tokenized Jaccard plus embedding-cosine score across consensus roles. Below 0.6 by default, the receipt records "no convergence" rather than a fake agreement.
four-light row
The Storage · Compute · TEE · Chain pill set. Each pill is verified, pending, mismatch, or amber. Renders on the run panel and on every receipt page.
TEE-independent
A second-machine re-run of broker.processResponse against the recorded 0G Compute provider. Available via "ivaronix receipt verify <id> --tee-independent".