Skip to content

electionRollDB — Voter Roll

The list of voters for an election: who is authorized to vote, how they were authenticated, whether they've submitted, and a pointer to their ballot. One row per roll-entry version. Versioned with the create_date / update_date / head pattern (see README).

  • Domain type: ElectionRoll (packages/shared/src/domain_model/ElectionRoll.ts)
  • Primary key: (election_id, voter_id, update_date)
  • Index: unique electionRollDB_unique_head on (election_id, voter_id) where head = true

Columns

Column Type Notes
voter_id varchar Voter id (part of PK).
election_id varchar Election this roll entry belongs to (part of PK).
email varchar Voter email (validated against email regex).
submitted boolean (not null) Whether the voter has submitted a ballot.
ballot_id varchar Points at the voter's head ballot; used to join ballotDBelectionRollDB.
ip_hash varchar sha256(req.ip); set when voter_authentication.ip_address is enabled.
address varchar LEGACY — never written or read by current code.
state varchar (not null) approved \| flagged \| registered \| invalid (ElectionRollState).
history json ElectionRollAction[]{ action_type, actor, timestamp, email_data? }.
registration json LEGACY — only set by the dormant registerVoterController; never read.
precinct varchar Voter's precinct.
email_data json { inviteResponse?, reminderResponse? }.
create_date varchar (not null) First-created timestamp.
update_date varchar (not null) This version's timestamp (part of PK).
head boolean (not null) true = current version.

History: originally keyed on voter_id alone with an ip_address column; 2024-01-27 swapped ip_addressip_hash, and 2024-01-29 moved to the composite PK + versioning columns.

ElectionRollResponse extends the stored row at API-response time with computed email_events (pulled from emailEventsDB): { event_type, event_timestamp, details? }[].

Purpose in the auth flow

electionRollDB is how BV enforces "one authorized voter, one ballot": the roll entry records the authentication mode (voter_id / email / ip_hash / registration), the submitted flag, and the ballot_id of the ballot the voter cast. create_date/update_date/head are generated by the model inside the write transaction — callers building a NewElectionRoll must not set them.