feat(elections): audit log and election lifecycle state machine
Open
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 33
- Forks
- 104
- Avg merge
- 12h 3m
- Merged PRs (30d)
- 10
Description
Summary
Formalize the election lifecycle (draft → open → closed → published) as an explicit state machine, and make every admin-originated state change visible in an immutable audit log.
Part of #1933.
Requirements
- State transitions: `draft → open`, `open → closed`, `closed → published`; enforce in Convex mutations — no back-transitions
- Guardrails on opening: no open if races are empty, if voter roll is empty, or if opensAt/closesAt are missing
- Auto-transition `open → closed` via scheduled Convex job at `closesAt`
- Audit-log viewer in admin UI: filter by election, actor, action type
- Audit entries are append-only; no delete or edit mutation exists for `auditLog`
- Every admin mutation (election create/edit, race edit, voter import, token regen, email send, status change) writes an audit row with actor email, action, metadata, timestamp
- Export audit log to CSV for post-election records
- Document the state machine in `docs/elections/lifecycle.md`
Context
- Epic: #1933
- Depends on schema issue and admin UI issue
- This is the last piece of the trust story — with ballot secrecy on one side and a full audit trail on the other, the election is both private to voters and accountable to observers.
Implementation notes
- Model state transitions with a small XState machine or a typed discriminated union of transitions — either is fine; prefer whichever is simpler to read
- Scheduled close job: Convex cron or scheduled action; idempotent so it can safely re-run
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 by reviewing the dependent schema and admin UI issues, then read docs/elections/lifecycle.md. Map the requested lifecycle, guardrails, scheduled close, audit viewer, CSV export, and admin mutation coverage before implementation. Done means all listed transitions and audit requirements are covered, with lifecycle documentation updated.
Written by the indexing model from the issue text.
Assessment
- Domain
- backend, database, documentation, frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100