Who can check what: three vantage points
The same records, checked from three places: your own node, the other party to the exchange, and anyone holding the evidence file. Each place adds a party who can check without trusting the one before, and each check is reported on its own, with what it does not show.
1What it is
A vantage point is a place a record is checked from: the node that sealed it, the other party to the same exchange, or a relying party who was in neither seat.
Each one holds different material (its own log; the other side's half with its proof; a file with no account behind it), so each can run a different set of checks.
Every check says what it shows and what it does not, and none of them, at any distance, says whether an answer was right.
2Design choices
docs/VERIFICATION-CHAIN.md: "Each link is independent" under "The whole chain, as one offline check"; "History is evidence, not a score" in the closing list of what the chain leaves open)record_push_receive.rs step 7)exchange_id; each node mints its own, so the two would never meet. (capsules docs/VERIFICATION-CHAIN.md, opening section, which joins the two halves for display by the shared client nonce; the request fingerprint is the receiver's lookup for its own record)record_push_receive.rs, steps 1–9 and "What is kept")witness_status.rs; VERIFICATION-CHAIN Link 7)3What it shows / what it does not
Shows
- Local: this exact record has not changed since it was sealed; this node's key signed it; it is in the log under a signed checkpoint; each checkpoint this node holds extends the one before it.
- Bilateral: the other side's half is signed under the key it announced and is in its own signed log; a server a served half names is its sender, and a model it names does not contradict my own record of the same request fingerprint, when I hold one.
- Bilateral: a sender whose checkpoint gives another root for a size that a checkpoint I already hold signed is caught (
checkpoint_equivocation). - Relying party: from an evidence bundle, offline: record and checkpoint signatures, coverage, each record's place in the log, disclosed text against its digest; with a witness named, that the checkpoint existed outside the node by a time.
- Relying party: which key signed a verdict, and which key signed a refusal, when one was given.
Does not show
- Local: that the content is true, or that the node keeps only this one history; that needs someone outside it.
- Bilateral: which side is right when the two differ, or that the two sides did not collude.
- Bilateral: who a key belongs to; the key is node-generated, so it shows continuity, not identity.
- Relying party: that a key is one they already trust: the signatures verify under keys the file itself carries.
- Relying party: that every event was logged, or that the witness is honest on its own; one witness is only as neutral as its operator.
- Relying party: the receiver-side checks of the bilateral ring, which are not in the bundle; and, for a mesh node's records, the bundle verifier is not joined yet.
- Any ring: who withheld a record by silence; that is a recorded absence, not a refusal.
- Any ring: whether the answer was right for you. That is judgment, and is named as a gap, never rounded away.
4Example
What the bilateral ring receives: one node's sealed half of a served exchange, pushed as a bundle with its inclusion proof and the signed checkpoint it sits under. The plugin's own generator test writes this vector; trimmed here.
{
"record_push_bundle": 1,
"capsule": {
"spec_version": "draft-mih-scitt-agent-action-capsule-05",
"format_version": "4",
"capsule_id": "ddd8685c1b578b39c9163a5c748ac7148108663719227f7636b2a113a1dd34dc",
…
"effect": {
"type": "inference_completion",
"request_digest": "6d139f1403cd84518768857efed6c375c0e3fe1af3f250cd3a5c59ea87a0323c",
"response_digest": "a8461110d26a1ceb91765128a3f8a648e86238810f4bdf27a330deb8681f9d87",
…
},
"chain": {
"parent_capsule_id": "6f1165b4e8f487815ea9bae5674c61ebe50862efa903ba8b0733c227f5303a1e",
"relation": "follows"
},
"signature": "d284584ca3012703…",
"key_id": "9e4480104975505a70ec6fc913efff2884a93af380a657adf39babf91fbe1fe1"
},
"inclusion": {
"leaf_index": 1,
"proof": { "v": 1, "kind": "inclusion", "size": 3, "leaf_index": 1,
"witness": ["8ec22eba289ccb94b3a7f9504ae4e648f91b4518bee10bb9b0da1e9a38d2af84"],
"peaks_left": [], "peaks_right": [] }
},
"checkpoint": {
"v": 1, "kind": "mmr_checkpoint", "log_id": "rust-node",
"mmr_size": 3,
"root": "f85629f081a79ba7b416e4ea5f1dec66c73bed90fb19e4c2b2af5e4df432f524",
"prev_size": 0, "prev_root": "",
"key_id": "9e4480104975505a70ec6fc913efff2884a93af380a657adf39babf91fbe1fe1",
"timestamp": "2026-09-30T03:38:00.000Z",
"signature": "802a4a60a953709b…"
}
}
| Field | Type | Meaning |
|---|---|---|
| record_push_bundle | integer | Marks a bundle (version 1), not a bare half. Plugin-internal, not a standardized wire. |
| capsule.capsule_id | hex | SHA-256 of the record's JCS form without capsule_id, signature, key_id. The local integrity check. |
| capsule.effect.request_digest | hex | The request fingerprint the receiver looks its own record up by. |
| capsule.chain | object | The previous record in the sender's own log; committed in format 4, so a forged parent changes the id. |
| capsule.key_id | hex | The sender's key. Must be the key the sender announced, and the signature must verify under it. |
| inclusion.proof | object | Sibling hashes from this leaf up to its peak, in an MMR of size 3 nodes (two records). |
| checkpoint.root | hex | The log's root at mmr_size 3 nodes, signed under the same key. The proof must reach it. |
| checkpoint.prev_size / prev_root | int / hex | The checkpoint this one extends; 0 and empty here, as this is the log's opening checkpoint. |
Recomputed for this page: the record's sorted, compact JSON without those three members hashes to ddd8685c…, its stated capsule_id. The leaf hash is SHA-256(0x00 ‖ capsule_id); SHA-256 of the node position (2, 0-based, written as 3 in eight bytes), then the witness hash on the left and the leaf on the right, gives f85629f0…, the checkpoint's signed root. That is the bilateral ring's inclusion check (step 9 of record_push_receive.rs), by hand.
Source: Mesh-LLM/capsules:vectors/record_push_bundle_rust.json @ efcada74026a2e18b9e62d77432888a31bbe9de4 (written by writes_the_cross_language_bundle_fixture, vectors/SOURCES.md); hashes per action-state-group/checkpointed-local-log:rust/checkpointed-local-log/src/mmr.rs @ 40dabd74508d0f8649c8754873e316badef1057d
5Status
Checked today against the plugin's release tag v0.1.4 (b4e24453f572b2d9fe8f2cefbd0f35a5eb54b0ad) and its main (efcada74026a2e18b9e62d77432888a31bbe9de4, eleven commits later); each plugin row's claim holds at both, though the code under some rows changed in between. The verifier rows are checked against their own repositories. live is in a release and on by default; built is in the code and tested, but off by default, pre-release only, or not yet joined end to end; designed is specified, with no checking code on this path.
| Check | Status | Evidence |
|---|---|---|
| Local: integrity, signature, checkpoints, inclusion and consistency | live | Each node seals its own record of every exchange; the log's checkpoints and integrity checks work. README.md "What works today"; docs/VERIFICATION-CHAIN.md Links 1 and 3–6 (Link 2, disclosed text, is the designed row below). |
| Bilateral: receive the other side's half and check key, signature, claims, proof, checkpoint | built | Off by default; needs mesh-llm 0.78 or later (which names the peer that asked and the peer that served, mesh-llm#2138) and record push turned on at both ends. README.md; record_push_receive.rs steps 1–9. |
| Bilateral: shared text hashes to the sealed digest | designed | Blocked on the host: mesh-llm sends no exchange bodies today, so the plugin's opt-in text keeping (off by default) has nothing to keep, and there is no digest-match check on this path. exchange_text.rs. The disclosure format is draft-mih-zhang-agent-disclosure-bundle-00. |
| Relying party: verify a bundle offline, no account | built | Pre-release CLI. capsulectl verify --bundle checks checkpoint signature, interval coverage, each record's place, citation closure, record signatures and disclosed payloads. action-state-group/capsule-cli:README.md @ 551b5c616641d15089eb0aac747f5c90aa29bf69. |
| Relying party: the same, on a mesh node's records | built | Not joined yet: a mesh-plugin profile asks a node's book over its evidence-request tool, but its bundles are carried, not verified. Same README, "A mesh-plugin profile". |
| Witness receipt (RFC 9942) | built | No default witness, and none contacted until the operator names one; a receipt counts only once it checks offline under the witness's key, configured by the operator or, when none is, pinned from the witness itself. witness_status.rs; scitt-cose-receipt pinned at 8833281c11d33e3c1e289cf74f11d25ee7f3c6dc in Cargo.toml. |
| Several witnesses: a split history is detectable | designed | VERIFICATION-CHAIN Link 7. What is built is one receiver's check: a checkpoint contradicting one already held is refused checkpoint_equivocation (record_push_receive.rs step 9). |
| Verdict under the referee's key | built | Off by default; the verdict must verify under the referee's announced key before a node holds it. README.md; referee/hold.rs check 1. |
| Signed refusal | live | Refusals of an evidence request and of a pushed record are signed and bind the digest of the request bytes as received (evidence_answer.rs, record_push_receive.rs). Two replies are not signed: the record-push bridge's own citing_record_seal_failed reply (record_push_bridge.rs) and refusals on the record-lookup channel (ledger_fetch_bridge.rs). capsulectl book accepts a refusal only if its signature verifies offline; that shows which key refused, not who holds it (capsule-cli README). |
Sources: Mesh-LLM/capsules @ efcada74026a2e18b9e62d77432888a31bbe9de4 and tag v0.1.4 @ b4e24453f572b2d9fe8f2cefbd0f35a5eb54b0ad (paths under crates/evidence-plugin/src/ unless shown); action-state-group/capsule-cli @ 551b5c616641d15089eb0aac747f5c90aa29bf69
6Specs
- Internet-Draft draft-mih-scitt-agent-action-capsule-05 — the record, its capsule_id and Producer Envelope: the local ring.
- Internet-Draft draft-mih-scitt-checkpointed-local-log-02 — append, signed checkpoints, inclusion and consistency proofs.
- Internet-Draft draft-mih-agent-bilateral-attestation-02 — both sides' records of one exchange, and the verifier states when they differ.
- Internet-Draft draft-mih-agent-evidence-request-00 — asking for a record; artifact, signed refusal or recorded absence.
- Internet-Draft draft-mih-agent-evidence-layer-00 — the commitment-substrate properties (append order, inclusion, consistency, checkpoint identity).
- Internet-Draft draft-mih-zhang-agent-disclosure-bundle-00 — carrying disclosed text that hashes to a sealed digest.
- RFC RFC 9052 — COSE; each record and checkpoint signature.
- RFC RFC 9942 — COSE Receipts; a witness's receipt for a checkpoint.
- RFC RFC 9943 — SCITT architecture; a Transparency Service as the witness.
- RFC RFC 8785 — JSON Canonicalization Scheme, the bytes under each capsule_id.
- Code Mesh-LLM/capsules — the plugin: sealing, record push and its receive checks, witness status.
- Code action-state-group/capsule-cli —
capsulectl verify --bundleand thebookverbs.