feat(elections): Convex schema for elections, races, candidates, voters, ballots
Open
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 33
- Forks
- 104
- Avg merge
- 12h 3m
- Merged PRs (30d)
- 10
Description
Summary
Define the Convex schema that backs the entire elections domain. This is the foundation for admin UIs, ballot submission, and tabulation.
Part of #1933.
Requirements
- `elections` table: title, description, opensAt, closesAt, status (draft|open|closed|published), createdBy, createdAt
- `races` table: electionId, title, description, seats, method (irv|stv), order
- `candidates` table: raceId, name, bio, order
- `voters` table: electionId, email, name, status (invited|voted|revoked)
- `voterTokens` table: voterId, tokenHash, expiresAt, usedAt — stores only hashed tokens, never plaintext
- `ballots` table: electionId, raceId, rankings (ordered candidateId array), submittedAt — no voterId link (enforced by schema, not just convention)
- `tokenRedemptions` table: tokenHash, redeemedAt — separate table so ballot has no timing correlation with a specific voter
- `auditLog` table: electionId, actor, action, metadata, createdAt
- Add appropriate indexes for each common query pattern
- Seed script that creates a dev election with sample races/candidates/voters for local testing
- Document the ballot-secrecy guarantee in a schema-level comment
Context
- Epic: #1933
- Depends on the elections app scaffold issue
- This schema is the contract for every downstream issue — changes after this lands will cascade.
Implementation notes
- Enforce ballot secrecy in schema shape, not just code conventions — the `ballots` table should physically not have a column that could identify a voter
- Token hash: sha256 with a per-election salt stored in Convex env
- Consider whether `rankings` needs a separate `ballotEntries` table if we want per-rank queries later — probably not; arrays are fine
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.
Research direction
Start with the elections app scaffold from #1933 and the repository’s existing Convex schema conventions. Define the listed tables, indexes, seed data, and schema-level ballot-secrecy comment, then verify locally with the development election and downstream schema checks if available. Done means the required fields, secrecy constraints, token-hashing requirements, and sample records are represented.
Written by the indexing model from the issue text.
Assessment
- Domain
- backend, database, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100