RosterVote What is this?

Verify a result — yourself.

Drop in a meeting's recount bundle and this page re-derives its signed Merkle roots and recomputes every tally, right here in your browser. It trusts nothing the server says — and nothing you load ever leaves your device.

How this proves a result wasn't changed
  1. Every event in a meeting — a ballot cast, a vote closed — is written as one leaf in an append-only ledger. Each leaf carries a fingerprint (a hash) of only its own contents.
  2. RosterVote signs a seal over the record each time a vote closes. The seal is a Merkle root: a single fingerprint standing for every leaf so far, signed with RosterVote's key. Change any sealed leaf and the root it's covered by no longer recomputes to match that signature — the tampering can't hide.
  3. This page re-derives every leaf's hash, recomputes each signed root, checks its Ed25519 signature, and checks that no seal number repeats and no seal covers fewer leaves than the one before it. That proves the bundle is internally consistent and signed by whoever holds the key the bundle carries. On its own, it doesn't yet prove which organization's record it is, or that the record wasn't changed and signed again: this page never compares the bundle with any other copy.
  4. A result is shown only for a vote this bundle proves was decided — its signed close is in the bundle. A vote that was still open, tabled, withdrawn or postponed when the bundle was exported shows its counts and Not decided in this bundle, never a result. A decided vote shows the result its close recorded, recounted from the ballots (a close that records no result shows the recount, labelled so); if the two disagree, it's flagged. A paper round shows its recounted hand counts, and is flagged if the counts its close recorded differ.
  5. The verifier checks each signature with the key in the bundle. To be sure the bundle is your organization's, compare its latest signed root with the one your organization published. This is the step that actually proves it's your organization's. The latest signed root is shown with the result below. Your organization's copy is on the results page or in the minutes. Match it character for character. Done by you, against something the organization put out independently of this file, that comparison is what anchors the result to an organization you trust.
  6. It also recounts every vote from the raw ballots and checks each decided vote's signed close record against itself and against that recount: the counts, the votes needed, the outcome, and exactly one close per decision. It flags a member counted twice in one round of voting. It also flags ballots cast before a vote was restarted (a re-vote, runoff, reconsidered vote, change of method or reopened nominations) that were counted together with those cast after it. That check reads only each entry's signed timestamp, so it needs no voter identity. It judges a restart only when a counted ballot comes more than two seconds before it, which allows for a server clock that steps backwards by up to two seconds. The rule has two limits: a server clock that ends up more than two seconds behind can still flag an honest vote, and a count packed within two seconds of its restart isn't checked by this rule.
  7. If the seal checks above pass, and the root matches, and the tallies recomputed here match what was published, the result is authentic.
  8. You don't have to trust RosterVote — or this page. The verification code is short and open, and you can download an offline copy that keeps working on your computer, with no server, for as long as you keep the file.

Drop a recount bundle here, or

A .json file from a meeting's Exports → Recount bundle.

The result you compute here should match what the meeting published — headline for headline, count for count.
Read the guide