RFC 6962 Merkle tree. Witness-cosigned.
The transparency log lifts the existing tamper-detection guarantee from "any client pulling from cursor=0 can detect modification" to "any pair of clients (or a third-party observer) can detect equivocation between divergent server views."
One tree per chain
Leaves are added in the order events are appended; the leaf index equals the event's seq. Leaf hash is SHA-256(0x00 || cbor(SignedPrefix)); internal nodes follow RFC 6962 §2.1. The server publishes a fresh SignedTreeHead on every accepted append, signed with its long-term Ed25519 cosign key.
SignedTreeHead = {
chain_id : tstr,
tree_size : uint,
root_hash : bstr .size 32,
timestamp_ms : uint,
signature : Signature, ; over fd0-translog-sth-v1 || cbor(prefix)
}Witness cosign
The witness binary fd0-witness runs on a host independent of the server. It polls the server's STH, verifies tree consistency against the previous head, and emits a Cosign if the head is honest — i.e. a strict extension of every prior head it has signed. Divergent heads are archived rather than cosigned, surfacing equivocation.
Cosign = {
witness_pub : bstr .size 32,
chain_id : tstr,
tree_size : uint,
root_hash : bstr .size 32,
observed_ms : uint,
signature : Signature, ; over fd0-witness-cosign-v1 || cbor(prefix)
}First-contact pinning
On first sync, the client pins the server's cosign public key. Subsequent STHs are rejected if signed under a different key. The witness pubkey is similarly pinned. Clients can verify each other's pins out of band via safety numbers, the same primitive used for identity-card verification.