Skip to main content

Module verify

Module verify 

Source
Expand description

SYNC.md’s checks over a served log page. SYNC.md’s three checks over one served page, as a function (D17).

Pure and node-free on purpose. The verification logic is the part worth being certain about, and a check that can only be exercised against a live node can only ever be exercised against a correct one — so the cases that matter, a flipped hash and a broken parent link, would never run. Mutations proved exactly that: removing the recomputation and removing the continuity check both left the end-to-end test green, because nothing ever handed it a bad page.

§What each check establishes

  1. Continuity — the page is a contiguous run and each entry’s parent is the previous entry’s hash. Catches a page that begins in the wrong place or has an entry dropped from the middle.

  2. Recomputation — the hash the node claims is the hash of the entry it was attached to. Needs nothing but the page.

  3. Authorship — the actor named actually signed it, and was still trusted at that position (D44). For an ed25519 entry this is the only check that needs things the page does not carry: the public key, and the revocation positions. An entry whose key the caller does not hold is reported unverified, never verified; an entry signed at or after its key’s revocation is a failure, because that is a claim the log itself contradicts rather than one this client cannot check.

    A passkey entry carries its own credential key (D45) and so needs nothing external — but for the same reason it establishes only half of what the ed25519 path does. See crate::verify::Report::integrity_only.

§What still cannot be verified forever

For an ed25519 entry the log records a key idhash(pubkey) — never the public key itself. So those signatures are checkable only while somebody still holds the key material, and an operator who deletes a revoked key’s line from the trusted-keys file makes that key’s history permanently unverified. Revocation no longer causes that decay; deletion still does. Retaining revoked keys’ public material is an operator responsibility nothing in the code can enforce.

D45 fixed that for passkeys by a route not open to ed25519 keys: a WebAuthn signature is useless without the authenticator data anyway, so the entry already carried scheme-specific material and the credential key joined it. An ed25519 signature carries nothing, and adding the public key to every one of them would grow every entry to re-state what a one-line file already says.

What no passkey entry can establish, before or after D45, is that the credential belonged to the channel. That binding lives in the accounts store, which is server state, is not in the backup set, and is deliberately erasable. An entry admitted on a credential now withdrawn looks exactly like one admitted on a credential still enrolled, and neither this client nor any other can tell them apart.

D46 widens that split to every scheme, and it is a property given up on purpose. The channel an entry names is an opaque handle, so verification still needs nothing but the page and a key, while attribution — which person that handle was — needs the accounts store and gets no answer once the account is revoked. “These bytes are genuine” is permanent; “this was alice” is deletable. A handle this client cannot resolve is the expected state for a deleted account, not a fault in the log.

Structs§

Report
What one page’s verification found.

Functions§

page
Runs the three checks over entries, in order.
rebuild
Rebuilds the hashed form from the fields /api/log serves.

Type Aliases§

Revocations
Actor id (hex, as author_key carries it) → the log position its binding was revoked at, from /api/view’s bindings[].revoked.at.