The app must prove that a person is allowed to vote, but it must not reveal how that person voted. That's the hardest and most important part of the entire system. Here's how it works.
True Anonymity isn't a form you submit — it's a wizard you advance through. Every page in the operator console shows the same six-step progress bar, with the current step pulsing and completed steps marked done. Here's what each step actually does.
The operator fills a short form: campaign title, briefing text (with full Markdown support — headings, lists, images, links), eligible-voter count, and two deadlines (one for the briefing window, one for voting). The system generates two separate one-time codes per voter — a briefing code and a voting code.
Voters receive their briefing code. They click the link, read the briefing (rendered as proper formatted content — not a wall of text), and tap "I've read this" or "Skip". Both choices are anonymous; the system records the action without ever connecting it to identity.
While the briefing window is open, the operator watches a live dashboard: acknowledged, skipped, never seen, and overall engagement percentage. They decide whether voters are informed enough to vote — or whether the briefing needs more time.
Now — and only now — the operator writes the questions. Four question types (Yes/No, multiple choice, ranking, rating). Each question can be abstained on with a structured reason from the "I choose not to vote" list. Clicking "Publish ballot" flips the campaign to the voting phase.
Voters use their separate voting code at their assigned link. They answer the questions or abstain with a reason. Submitting locks the vote. The system stamps each anonymous ballot with the voter's earlier briefing decision — but discards every link back to the voter themselves.
When voting closes, results unlock. Standard totals and percentages, plus the information audit: how many voters read the briefing, how many skipped, how many never visited — cross-tabulated with the "I wasn't informed enough" abstain reason. You learn whether your communication failed or whether voters chose not to engage.
Saying "it is anonymous" is not enough when the whole reason for this app is that people don't trust existing systems. Start with what we refuse to touch.
| Data point | Stored with the vote? |
|---|---|
| Voter name | No |
| Student ID number | No |
| Email address | No |
| IP address | No |
| Device information | No |
| Timestamp linked to identity | No |
The eligible voter list is separate from the vote pool. Admins know the list exists. They never see it joined to a ballot.
Only aggregated results. Never line-by-line responses tied to a voter.
Not even with full database access. The connection doesn't exist in any record.
The system can prove each person voted only once without revealing who they are. That's the whole trick.
Five steps. The link between the two is broken on purpose, before the vote is ever saved.
The school uploads a list of eligible voters for the poll.
Each voter receives a unique one-time code (email, printout, or school system).
The system checks: has this code been used? If not, the voter proceeds.
After submission, the code is marked used and discarded. The vote goes into a pool with no link back.
The code and the vote never exist in the same record. Even the system administrator can't reconstruct who voted for what.
Trust is built by letting voters check for themselves, not by asking them to take our word.
Planned
After casting a ballot, voters receive a confirmation hash they can look up in the public tally. The hash confirms their vote was counted — without revealing what they voted. This is the strongest known trust pattern for anonymous voting, and it's on the roadmap.
See the roadmap for what's built, what's planned, and what's broken →
This is the obvious worry. The one-time code system solves it — mostly. Here's what's handled, and what isn't yet.
| Edge case | How we handle it | Status |
|---|---|---|
| Someone tries to vote twice | Each code is single-use. After submission the code is permanently locked. | Built |
| Someone loses their code | Code can be resent. The original is invalidated. If a vote was already cast with the old code, it's removed and a fresh code is issued. | Planned |
| Someone wants to change their vote | Votes are locked after submission. No changes allowed. This is intentional. | Built |
| Someone shares their code with a friend | This is the biggest unsolved challenge in the spec. Possible mitigations: short code expiration, school-network requirement, delivery through a school portal. | Open problem |
We're being honest about this: code sharing is the hardest open problem in the system. We don't pretend it's solved. The full discussion lives on the Roadmap & Known Gaps page.
Student council, class president, club leadership. A few times per year.
Uniform changes, schedule changes, lunch rules. When a specific decision needs honest input.
School culture, bullying, teacher feedback. Monthly or quarterly check-ins.
Tuition, safety, scheduling. When the school needs honest parent opinion without the parent-teacher meeting awkwardness.
Polls can be scheduled in advance and set to close automatically. Results are only visible after closing — late voters can never be influenced by early results.