Methodology
How VotersRight works — and how to check it
We would rather you verify us than trust us. This page explains exactly how the platform works, names every data source, and shows you how to confirm any number against the public Solana ledger yourself. Where something isn't finished, we say so.
Last updated May 2026
Section 01
How We Verify Identity
Every vote on VotersRight comes from a verified U.S. resident — not an anonymous click. To cast a vote you complete a three-step check: a one-time passcode sent to a U.S. mobile number, a residential address resolved to a Congressional district, and a Solana wallet provisioned to your account so your position can be recorded on a public ledger.
One phone number maps to one address; changing your address requires re-verification. We store a salted hash of your phone number, never the raw number, and we never sell or share it. What we can't promise is perfection: a determined individual could obtain multiple numbers. Section 06 describes how we detect the coordinated burst patterns that abuse at scale would produce.
Sources & verification
- Privacy Policy — what we store and why →
- District resolution uses the U.S. Census geocoder (see Section 03).
Section 02
How We Count Votes
A heartbeat is the live tally of verified constituents who have taken a Yes/No position on their senator, alongside the reason they cite. Each position is written to a Solana smart contract as an on-chain record — not a private number in our database that you have to take on faith. The heartbeat you see is a cached aggregate of those on-chain records, refreshed within seconds.
These constituent positions are distinct from a senator's official roll-call votes in Congress. Those come from Congress.gov (Section 03) and appear separately on each senator's page. You can verify any heartbeat count yourself against the chain — see Section 08.
Sources & verification
- The voting smart contract + how to query it (Section 08) →
-
Public RPC endpoint anyone can use:
https://api.devnet.solana.com
Section 03
How We Source Data
Everything we publish about a senator traces to a named public source, linked inline on their page. We ingest on a schedule, timestamp every capture, and cite the original record on every figure. A machine-readable sample export of what we publish — no account required — is available below, in JSON or CSV.
Download a sample export
Inspect exactly what we publish before you cite us — no account, no signup. The export carries senator metadata and the aggregate constituent heartbeat (vote counts only). It contains no user, voter, address, or wallet data of any kind. Cached at the edge for one hour.
- Schema
-
Per senator:
bioguide_id,full_name,party,state_code, term dates, official website, lifecycle state, and the heartbeat aggregate (heartbeat_yes_count,heartbeat_no_count,heartbeat_total_count, and the yes/no percentages). The JSON body adds a top-levelweekly_digestslist and agenerated_attimestamp. - Try it (FR52)
-
# JSON curl https://v2.votersright.org/api/v1/exports/sample.json # CSV curl https://v2.votersright.org/api/v1/exports/sample.csv - Open it directly
- Sample export (JSON) → Sample export (CSV) →
The export's weekly_digests list is intentionally empty
for now — the weekly-digest summaries populate it once the weekly-digest pipeline ships.
We do not fabricate digest rows in the meantime.
Sources & verification
- Congress.gov — voting records & sponsored bills →
- Federal Election Commission & OpenSecrets — campaign finance →
- USAspending.gov — federal district spending →
- U.S. Census Bureau & Bureau of Labor Statistics — state economic context →
- A no-account sample data export — see "Download a sample export" above.
Section 04
How We Handle Corrections
We treat errors as a public ratchet, not a private embarrassment. Anyone can report an error on any data point inline — no account required — and we triage within 24 hours. When we correct something, the original wording, the corrected wording, the date, and the reasoning are published permanently to the Public Correction Archive (Section 07). Politicians' offices have a separate, identity-verified correction channel.
Sources & verification
Section 05
Our Funding & Independence
VotersRight is independent. We are not affiliated with, funded by, or operated on behalf of any political party, candidate, campaign, or political action committee. We use no red/blue partisan framing anywhere on the platform — a senator's party appears only as a neutral letter label.
A full funding disclosure — who pays for VotersRight, and how — will be published here before public launch.
Section 06
Adversarial Test Results
Trust requires proof that we tried to break ourselves. Before public launch we will run adversarial "sybil" tests that simulate burner-phone farms and coordinated voting bursts, then publish the results — pass or fail, including methodology and detection thresholds — so you can judge the platform's detection posture rather than take our word for it.
See the published integrity-test results. If we ever detect a real coordination attempt in production, we commit to publishing it as a transparency report (Section 09).
Section 07
Public Correction Archive
Every correction we have ever issued is public and permanent — sorted most-recent first, each showing the original wording, the corrected wording, the date, and the reasoning for the change. Nothing is quietly edited away.
Section 08
Smart Contract Address & Audit Report
The voting smart contract is the source of truth for every heartbeat. It is currently deployed to the Solana devnet cluster for testing. The audited mainnet program and the independent security-audit report are in progress; both the mainnet program ID and the published audit will appear here before public launch.
Program & verification
- Program ID (devnet)
- 5zskwM6GtRXmhPMHjM5rzAwpJ5DejZN4n8zY6F6ebk2b
- Inspect on Solana Explorer
- https://explorer.solana.com/address/5zskwM6GtRXmhPMHjM5rzAwpJ5DejZN4n8zY6F6ebk2b?cluster=devnet →
- Query it yourself (FR54)
-
# Solana CLI solana account 5zskwM6GtRXmhPMHjM5rzAwpJ5DejZN4n8zY6F6ebk2b --url https://api.devnet.solana.com # JavaScript (@solana/web3.js) import { Connection, PublicKey } from '@solana/web3.js'; const conn = new Connection('https://api.devnet.solana.com'); const info = await conn.getAccountInfo(new PublicKey('5zskwM6GtRXmhPMHjM5rzAwpJ5DejZN4n8zY6F6ebk2b')); console.log(info); - Per-senator heartbeat verification
-
Every senator's heartbeat is verifiable on chain: copy a runnable CLI command or a
@solana/web3.jssnippet that derives their on-chain Poll account yourself. - Source code
- Smart contract source repository →
- Key rotation & operational security
- Key-rotation & operational-security runbook →
- Upgrade governance (design)
- Smart-contract upgrade-governance design doc →
Verify it yourself
Verify a Heartbeat on Chain →
Pick any senator and confirm their heartbeat against the Solana ledger — a
copy-to-clipboard CLI command and a @solana/web3.js
snippet that derives the on-chain account from first principles.
Section 09
Off-Platform Limitations
Honesty about what we cannot do builds more trust than overstating what we can. VotersRight cannot detect off-platform vote-buying, coercion, or offline organizing campaigns — activity that never touches our system is invisible to us. We verify that a vote comes from a real, district-resolved U.S. resident (Section 01); we cannot see what happened to that person before they arrived, who paid them, or who pressured them off-platform. We name that limit plainly rather than imply a completeness we don't have.
What aggregate-trend analysis would surface is a coordinated pattern: a sudden statewide flip with no corresponding news event, for instance, stands out against a normal trend line. To be clear about what this is and isn't — it is a detection posture, an approach we would apply, not a live anomaly-detection system we are claiming to run against your data today. We describe the approach so you can hold us to it, not so you'll assume it is already deployed.
If we ever detect a real coordination attempt in production, we commit to publishing it as a transparency report — what we saw, how we saw it, and what we did — rather than quietly handling it. The same commitment runs the other way: we will publish the adversarial "sybil" test results that exercise this posture before we claim it works (Section 06).
Detection posture & evidence
- Aggregate-trend analysis is described above as an approach, not a deployed capability. We do not claim to run live anomaly detection on your data today.
- The published adversarial sybil-test results — evidence that this posture actually surfaces coordinated bursts — appear on the dedicated integrity-tests page, cross-referenced from Section 06. They are forthcoming, published before public launch; we link nothing we have not yet run.
Section 10
Signed Broadcasts
Every weekly digest we publish is cryptographically signed with an Ed25519 key the moment it goes live. The signature covers the digest's exact content — its headline, summary, body, and the ranked movers — so anyone can confirm a number or a quote attributed to VotersRight actually came from us, unaltered. If someone doctors a screenshot of a digest and changes a figure, the signature no longer matches the content, and the forgery is detectable by anyone, not just us.
Verification needs nothing private. The signature and the public key travel with the published digest; you reconstruct the signed message from the public fields, then check the signature against the public key below. We never expose the private signing seed — only its public half is published here.
Authorized signing keys
-
- Key ID
- vrp-digest-2026a
- Public key (Ed25519, base64)
- 15Ptzwev6amKp0BIfrv4KBU5YkjSX1TiuDKIGsJMnak=
- Valid from
- 2026-06-09T20:02:32.214Z
- Valid until
- Current (open-ended)
The signed message format (v1)
The signature covers the UTF-8 bytes of a deterministic, canonical string you rebuild
from the digest's public fields. Line 1 is a fixed domain-and-version prefix; line 2 is
a single-line JSON object whose keys appear in this exact order, with explicit
null for absent optional values and the
movers sorted by ranking_metric ascending,
then rank ascending:
vrp-digest-signature/v1
{"slug":<string>,"week_start":<YYYY-MM-DD>,"week_end":<YYYY-MM-DD>,"had_movement":<bool>,"headline":<string>,"summary":<string>,"body_md":<string>,"movers":[{"bioguide_id":<string>,"ranking_metric":<string>,"rank":<int>,"total_delta":<number>,"net_supporter_delta":<number>,"yes_pct_delta":<number|null>,"top_reason_code":<string|null>,"top_reason_count":<int>}]}
Verify it yourself (Node.js, no dependencies beyond
@noble/curves):
import { ed25519 } from '@noble/curves/ed25519.js';
// 'sig' = published digest.signature (the self-describing blob).
// 'message' = the canonical v1 string above, rebuilt from the public digest.
const message = 'vrp-digest-signature/v1\n' + canonicalJsonBody; // see format above
const pub = Buffer.from(sig.public_key, 'base64');
const signature = Buffer.from(sig.signature, 'base64');
const ok = ed25519.verify(signature, new TextEncoder().encode(message), pub);
console.log('authentic:', ok); // true ⇒ the digest is unaltered VotersRight data
// Trust the key: confirm sig.public_key matches an authorized key above and
// that sig.signed_at falls within that key's valid_from / valid_until window. Key rotation
We rotate the signing key annually. When a new key is published, the
previous key stays authorized for a 30-day overlap window (its
valid_until is set to the new key's
valid_from plus 30 days). During that
window, signatures from either key verify — so a digest signed just before a rotation
stays checkable while the new key takes over. A signature is only ever trusted if its
key was authorized at the moment it was signed.