feat(elections): build elections.us-rse.org to replace ElectionBuddy [epic]
Open
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 33
- Forks
- 104
- Avg merge
- 12h 3m
- Merged PRs (30d)
- 10
Description
Summary
Build a ranked-choice voting application at elections.us-rse.org that replaces our dependency on ElectionBuddy. The app will live in this repo alongside the marketing site, share the design-system, and support both single-winner (IRV) and multi-winner (STV) races used by US-RSE elections.
Goals
- Eliminate recurring ElectionBuddy cost and give US-RSE full control over the election platform.
- Support ranked-choice voting (IRV for single seats, STV for multi-seat board elections).
- Preserve ballot secrecy: voter identity is separated from the submitted ballot.
- Provide a trustworthy audit trail for each election.
- Meet WCAG 2.2 AA accessibility for the voter-facing ballot.
Architectural decisions
- Monorepo tooling: Turborepo (apps/web for marketing, apps/elections for the voting app, packages/design-system for shared CSS tokens).
- Backend: Convex (reactive DB, serverless functions, scheduled jobs, built-in auth helpers).
- Voter authentication: Emailed unique voting tokens. Admin uploads voter roll; each voter receives a one-time magic link. Ballot anonymized on submission.
- Tabulation: Both IRV and STV implemented as configurable race types.
Scope (child issues)
Foundation
- #1934 — chore(repo): migrate to Turborepo monorepo
- #1935 — feat(elections): scaffold elections app + Convex backend
- #1936 — build(elections): deploy elections.us-rse.org (DNS, hosting, CI/CD)
Data & admin
- #1937 — feat(elections): Convex schema for elections, races, candidates, voters, ballots
- #1938 — feat(elections): admin UI for election and race configuration
- #1939 — feat(elections): admin voter roll CSV import and token generation
- #1940 — feat(elections): transactional email delivery for voting tokens
Voting experience
- #1941 — feat(elections): accessible ranked-choice ballot UI
- #1942 — feat(elections): token-gated voting route with one-time-use and ballot secrecy
Tabulation & results
- #1943 — feat(elections): IRV tabulation engine with test fixtures
- #1944 — feat(elections): STV tabulation engine with test fixtures
- #1945 — feat(elections): results UI with round-by-round visualization
Trust & ops
- #1946 — feat(elections): audit log and election lifecycle state machine
Suggested sequencing
- Foundation: #1934 → #1935 → #1936
- Data: #1937 → #1938 → #1939 → #1940
- Voting: #1941 in parallel with #1942
- Tabulation: #1943 → #1944 → #1945
- Trust: #1946 (can start once #1937 and #1938 land; finalize after #1940)
Out of scope (for now)
- Multi-org/tenant support (only US-RSE elections).
- Live streaming / real-time result broadcasting during open voting.
- Voter identity verification beyond token possession.
- Importing historical ElectionBuddy results.
Non-negotiables
- Ballot secrecy is preserved end-to-end — no admin query can map a submitted ballot back to a voter identity.
- One-person-one-ballot is enforced at the token layer.
- Every state change on an election (config, open, close, publish) is recorded in an audit log.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.