First-party, hardware-rooted, and able to prove that an answer is complete — not merely signed. Every response states what it establishes, on what evidence, and for how long that stays true.
/healthz on the node serving this page, on load and every 15 seconds. The service itself binds to 127.0.0.1; nginx is the only public listener. Point the field at any other node running this service to read that one instead.Each row is a separate claim with its own strength. Measured means we observed it. Relayed means someone else asserts it and we carry their evidence. Nothing collapses to a single boolean.
tpm2_checkquote against it before signing anything with it, and publishes the AK public key so you can run the same check rather than taking our word: tpm2_checkquote -u <akPublicKeyPem> -m <quote.message> -s <quote.signature> -f <quote.pcrs> -g sha256 -q <nonce>. Valid from the quote; PCRs are frozen until the next boot.fixedtpm|fixedparent. Holds until the key is destroyed.Published with the same weight as the claims above. Most attestation products ship a green check; the list of refusals is the part that can't be copied without accepting the same limits.
IBM, vendor string SW TPM. No EK certificate and no NV indices at all. A quote alone proves some TPM said so; only the Oracle certificate binds it to a real machine.bor is a userspace binary and is not in the measured set — IMA runs and PCR 10 is extended with 89 entries, but the client is absent from the log and PCR 10 is not in our policy. The attestation says how the box booted, not which client produced the view.A signed response proves custody of what was sent. It says nothing about what was left out — and an omitted row is undetectable by inspection, in an answer that is signed and therefore looks stronger.
| eth_getLogs window | Time |
|---|---|
| 1,000 blocks | 459 ms |
| 10,000 blocks | 4.1 s |
| 50,000 blocks | 18.4 s |
| 200,000 blocks | timed out (30 s cap) |
Checking an answer by re-querying the chain costs ~92 minutes for one year of history. The commitment has to do the work.
History is cut into fixed, aligned chunks, so which chunks cover a range is arithmetic the verifier computes — gaps become maths, not trust.
Within a chunk, keys are sorted. A present key returns its full event list and a Merkle path; an absent key returns the two neighbours that bracket it. That is what makes “there are none” a proof rather than a promise.
Ten adversarial cases were written into the spec before the code and all are refused: dropped events, dropped keys, false absence, coverage gaps, re-ordering, uncertified signers, scope violations, foreign nodes.
One port, four doors. Signature metadata rides in headers, so the body stays byte-identical to what Bor produced and an unmodified client keeps working.
# A signed chain read. The body is untouched; the proof is in the headers. curl -X POST https://node.rootz.global/ \ -H 'content-type: application/json' \ -H 'x-rootz-sign: v1' \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' # → x-rootz-sig the signed envelope (RFC 8785 JCS) # x-rootz-keyset the public keyset it was signed with # x-rootz-certification binds that keyset to the TPM root # x-rootz-certification-signature
# Ask the index a question, and get the proof with the answer. curl -X POST https://node.rootz.global/index/query \ -H 'content-type: application/json' \ -d '{"key_space":"rootz.v6.datawallet.notes", "key":"0x…","from_block":80600000,"to_block":80699999}' # Supporting endpoints GET /index/keyspaces what can be asked GET /index/coverage?key_space=… what is ACTUALLY indexed — gaps visible, not inferred GET /healthz head, and whether it admits being hardware-rooted GET /.well-known/rootz-node root key, certification, JWKS, DNS selectors
The same node in an agent's protocol, at POST /mcp. Stateless — a reconnecting agent gets the same answers because they come from the store, never from session state.
The strongest thing we can say about a proof is not that it exists, but that our own service stops working when it fails. These are places where the same check a reader would run is what prevents this node from serving something wrong.
| Element | Window | Consequence |
|---|---|---|
| Instance identity certificate | 2 hours | Captured at signing time and carried as evidence — never fetched later |
| Signing keyset | 1 hour | Rotated; the TPM signs rarely, the keyset signs constantly |
| Signed request | 5 minutes | Single-use nonce; replay refused |
| Response envelope | 5 minutes | ⚠️ Inherited default — wrong for an archival record, and logged as a defect |
| PCR baseline | until next boot | A firmware change moves PCR 0 and requires re-authorisation |
| Chunk commitment | immutable | Once built — but see the reorg gap above |
| Oracle intermediate | 1 year | Only the leaf churns |
/index/coverage from this node…Connect to POST https://node.rootz.global/mcp. Stateless streamable HTTP — no session to keep, no key to hold.
// 1. Ask what you are talking to, before relying on anything else. tools/call node_attestation {} // The reply tells you three things you must not discard: // hardware_rooted whether a TPM vouches for the signing key // anchor which OCI instance and tenancy, and for how long that holds // not_claimed what this node explicitly does NOT assert // 2. Every answer carries depth and window. Neither is decoration. depth "measured" we observed it "relayed" someone else asserts it; their evidence is attached "declared" we are simply stating it window how long the answer stays true — a liveness read is stale immediately // 3. An empty result is never an answer here. // "no events" and "I have not indexed that range" are DIFFERENT, and the node // says which. If you see status "NO INDEX SERVICE" or a coverage refusal, // that is not zero — it is unknown. Do not record it as zero. // 4. For an absence that matters — "has this identity been revoked?" — // demand coverage, do not accept a bare negative: tools/call v6_rivets { key, from_block, to_block, require_coverage_through } // The node REFUSES if its index does not reach that block. A stale // "no revocation" is honest and wrong, and that is the whole harm.
Kept here rather than in a private tracker, because a list of what is unfinished is part of what the node claims.
hardwareRooted: true was a boolean signed by a key that said so. tpm2_checkquote now runs in the same chain as the quote, and a quote that does not verify produces no attestation at all.NONE — committed without a finality check, permanently. It now refuses to build a chunk whose range is not yet checkpointed to Ethereum, and refuses to build at all when no finality source answers. Fallback to a confirmation depth is labelled as the weaker source, never substituted silently.nohup; now a systemd unit, enabled, ordered after the chain client with Wants so a restart of either does not cascade./usr/bin/bor and PCR 10 in the quote. The natural trigger is the next client upgrade — that is when the measurement moves, and a measurement nobody notices moving is not one.node.rootz.global and the service stays bound to 127.0.0.1 behind it. What makes exposure safe is the tiering: an unsigned caller is served slowly rather than refused, and there is no API key to leak because identity is the signature. This row said "the ports are closed" for several hours while serving over them — kept here rather than quietly edited, because an open-items ledger that flatters itself is worth nothing./skillIf you are an AI reading this page to work out how to use the node, stop and fetch
https://node.rootz.global/skill instead. It is the
operating manual, in markdown, in one request.
The routes are the easy part and you will discover them in a minute. The rules are
the part that matters and they are invisible from a route list: an empty result is not
an answer; an absence that matters must carry require_coverage_through
or the node's silence means nothing; absence_is_proved: false is not
"none found"; and without a pinned root a valid signature proves only that
some node signed.
The same file ships in the repo as a Claude skill, and a test fails if it drifts from the tool names, key spaces and query limits the service actually enforces — a manual that disagrees with its service is worse than none, because it is believed.
The serving surface is not the proof. Verification runs in the relying party, against the bytes it actually received, with the node's public material fetched from /.well-known/rootz-node.
# 1. Rebuild the covering chunk set from the range and chunk size — yourself. # 2. Check each signed chunk header chains to a certified keyset, and that keyset to a TPM quote, and that quote to the Oracle instance certificate. # 3. Recompute the leaf from the returned events and walk the Merkle path to the committed root. One dropped or re-ordered event changes it. # 4. For an absent key, check the two neighbours are adjacent — otherwise a key could be hidden between them. # 5. Confirm the response is bound to the request you actually sent.