Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The election package contains all of the information that defines an election. VxAdmin is configured by inserting a USB drive and selecting an election package from the drive.
After VxAdmin is configured, the election package can then be digitally signed and exported onto a USB drive in order to configure VxScan, VxCentralScan, and VxMark. The digital signature verifies that the election package is legitimate. The other devices require that the signature is present. As a result, an election package from outside the system cannot be used to directly configure VxScan, VxCentralScan, or VxMark.
The election package is a zip archive (a .zip
file). The zip archive contains 6 files:
Election Definition (election.json
)
App Strings (appStrings.json
)
Audio IDs (audioIds.json
)
Audio Clips (audioClips.jsonl
)
System Settings (systemSettings.json
)
Metadata (metadata.json
)
The election definition file includes the information that defines the election and ballots, including but not limited to definitions for contests, ballot styles, precincts, parties, multi-lingual ballot translations, and ballot layouts. The system accepts two formats - the VxSuite Election Definition format or the Ballot Definition CDF. When using the Ballot Definition CDF, some features are not available.
The election definition file is required to be present in the election package.
The app strings file contains all voter-facing strings in the user interface and their translations. For example, at the beginning of the voter flow in VxMark there is a button labelled, by default, "Start Voting." If the voter has set VxMark to another language, however, the button will display the translation for that language specified in the app strings file. Additionally, the default English text can be overridden by specifying a different English value in the app strings file.
In the case of specifying a Spanish translation and overriding the English translation for "Start Voting", which has an internal key of buttonStartVoting
, the following values and overall structure would appear in the app strings file:
Notes:
Voter-facing strings that appear on ballots (contest names, candidate names, the name of the jurisdiction, etc.) are not included in the app strings file because they are already included in the election definition.
The language codes in the app strings file are the IETF language tags for supported VxSuite languages: English, Spanish, Simplified Chinese, and Traditional Chinese.
The keys for the various user interface app strings (e.g. buttonStartVoting
) are defined in VxSuite's app strings catalog.
The app strings file is optional. If not provided, default English strings will be used.
The audio IDs file is a JSON file structured identically to the app strings file except that instead of containing text values for each voter string, it contains audio IDs for each voter string. Each audio ID corresponds to an entry in the audio clips file.
Each row of the audio clips file contains one audio clip with relevant metadata. The audio itself appears as an MP3 file encoded in base 64. For example, a row representing an audio clip for the "Start Voting" button would appear as:
Together, the two files allow specifying audio playback for any text read to a voter in audio mode, including both non-English translations and English overrides.
The audio IDs and audio clips files are optional. If they are not provided, audio playback will be disabled.
The system settings file contains settings which are not specific to an election definition but do impact machine behavior.
Authentication Settings
arePollWorkerCardPinsEnabled
- When set to true
, poll worker cards are created with PINs which are then required when authenticating.
inactiveSessionTimeLimitMinutes
- Sets the number of minutes after which machines automatically lock due to inactivity.
numIncorrectPinAttemptsAllowedBeforeCardLockout
- Sets the number of times that a PIN can be entered incorrectly before the user has to wait extra time to retry.
overallSessionTimeLimitHours
- Sets the maximum number of hours for any session, regardless of activity.
startingCardLockoutDurationSeconds
- Sets the number of seconds that the user is locked out from retrying a PIN after the number of failed attempts specified by numIncorrectPinAttemptsAllowedBeforeCardLockout
. Each subsequent failed attempt triggers a lockout double the length of the previous lockout.
Scanning Thresholds
definite
- Specifies the percentage of a bubble that needs to be filled in for the tabulators to consider it a mark.
writeInTextArea
- Specifies the percentage of the write-in area that needs to be filled in for the tabulators to consider it a write-in. This is only relevant for jurisdictions that allow unmarked write-ins i.e write-ins without an accompanying mark.
Adjudication Reasons
precinctScanAdjudicationReasons
- Specifies the reasons that a ballot scanned at VxScan should be flagged for adjudication. Supported reasons are overvotes, undervotes, blank ballots, or unmarked write-ins.
centralScanAdjudicationReasons
- Specifies the reasons that a ballot scanned at VxCentralScan should be flagged for adjudication. Supported reasons are overvotes, undervotes, blank ballots, or unmarked write-ins.
disallowCastingOvervotes
- When set to true
, scanners will always reject overvoted ballots. When set to false
, VxScan will allow a voter to choose whether to reject or cast an overvoted ballot, and VxCentralScan will allow an election manager to choose whether to reject or tabulate an overvoted ballot.
allowOfficialBallotsInTestMode
- When set to true
, official ballots will not be rejected in test mode. The setting is for jurisdictions where testing must take place on official ballots.
Other
precinctScanEnableShoeshineMode
- When set to true
, VxScan will run in "shoeshine mode," which will scan the same ballot repeatedly. Instead of ejecting the ballot after scanning it, VxScan will move it back to the input tray and scan it again. This mode is used only for internal testing and certification testing.
castVoteRecordsIncludeOriginalSnapshots
- When set to true
, scanners will include "original" snapshots in the CVR export for each ballot. This includes extra information about the marks on the ballot before contest rules are applied as specified in the CVR CDF. This extra information increases the size of the CVR export, degrading performance.
castVoteRecordsIncludeRedundantMetadata
- When set to true
, scanners will include election and system metadata in each ballot's CVR as specified in the CVR CDF, rather than just including it once for the entire export. This extra information increases the size of the CVR export, degrading performance.
disableVerticalStreakDetection
- Disables the warning when streaks are detected when scanning ballots (which indicates that the scanner needs to be cleaned). Used as a failsafe in case of erroneous warnings.
The system settings file is optional. If not provided, the following default settings will be used:
The metadata file is a JSON file that contains a single key, version
. In the current software version, the value will only ever be "latest"
. In other words, the metadata file is a JSON file with the contents:
In future software versions, the "version"
value will be used to differentiate versions of the election package that correspond to different software versions. For example, if a user flow is updated, a new app string may be added and the "version"
value will indicate which app strings to expect.
There are two hashes for each election which are both critical to operation and security of each election.
The ballot hash is the SHA256 hash of the election definition file and represents a snapshot of all election-specific data which determines the ballot, including contest definitions and ballot layout. Ballots must include a machine-readable version of the ballot hash (e.g. a QR code or a pattern of timing marks). When a ballot is scanned, the scanner checks to make sure the ballot has the expected ballot hash. The ballot hash from the ballot must match the ballot hash from the scanner's configured election definition.
If any election content changes, the ballot hash will change, meaning the system will consider it to be a new election definition, and any ballots with a different ballot hash will not scan. The system's strict checking of the ballot hash prevents situations where a change to the election definition leads to ballots being miscounted (for example, if the order of two candidates is swapped). As a result, any changes to the election definition require reprinting all ballots.
The election package hash is the SHA256 hash of the entire election package, which includes both the election definition and all other files. The election package hash is displayed on screen to election managers and system administrators. It allows the user to ascertain which election package was used to configure a machine. The election package hash is not used during ballot scanning.
For example, imagine that an election administrator wants to change the audio clip for candidate's name. The audio clip is not a part of the election definition but it is a part of the election package, so the ballot hash remains the same while the election package hash changes. The election administrator can reconfigure VxMark with an updated election package but does not have to reprint ballots.
The election ID shown on screen and included in printed reports contains a shortened version of both the ballot hash and the election hash in the format: {ballot hash}-{election hash}
. For example, with ballot hash 083e2e0afbb19191a4d2850562ddef050ff860b0d61acee15d3bb26954932941
and election hash db5c379b71accbf991e42ab23d26202f88b2539b6c69b814a0d3c8dc9f4072dc
, the election ID would be: 083e2e0-db5c379
. This enables identification of both the specific election package and election definition that a machine is configured with.
The election definition within the election package can be a JSON Ballot Definition CDF Version 1.0 file. The full specification is defined by NIST and can be accessed on their website.
VxSuite accepts the Ballot Definition CDF Version 1.0 as defined by NIST without any data extensions. VxSuite requirements differ from the NIST CDF schema only in the following respects:
Some fields not required in the NIST CDF are required in VxSuite
Some enumeration values are more restricted in VxSuite than in the NIST CDF
Some classes and attributes are ignored in VxSuite
The exact VxSuite schema is defined as a JSON schema in the vxsuite repository which is derived from the original NIST schema. The differences between the two are documented in the below tables.
BallotDefinition
BallotFormat, Election, GpUnit, and Party are required
BallotFormat and Election must have a length of 1
GpUnit must have a minimum of length 1
BallotMeasureContest
BallotTitle, ContestOption, and FullText are required
ContestOption must have a length of 2
BallotStyle
ExternalIdentifier is required and must have a length of 1
Language must have a minimum length of 1
CandidateContest
BallotTitle and ContestOption are required
ContestOption must have a minimum of length 1
PrimaryPartyIds must have a length of 1 if it exists
CandidateOption
CandidateIds must have a length of 1
Election
BallotStyle, Contest, and ExternalIdentifier are required and all must have a minimum length of 1
GpUnit
At least one GpUnit must be defined with the type "state"
At least one GpUnit must be defined with the type "county"
Office
Term is required
OptionPosition
Sheet is required
OrderedContest
Physical is required and must have a minimum length of 1
Party
Abbreviation is required
PhysicalContest
PhysicalContestOption is required and must have a minimum length of 1
PhysicalContestOption
ContestOptionId is required
ReportingUnit
Name is required
Term
Label is required
ElectionType
general, primary
ReportingUnitType
county, precinct, split-precinct, state, other
ActivationContest
ActivationOption
AnnotatedString
AnnotatedUri
BallotMeasureType
CandidatePreElectionStatus
Coalition
ContactInformation
DayType
ElectionAdministration
GeoSpatialFormat
Hours
LatLng
OfficeGroup
OfficeTermType
OrderedHeader
PartyContest
PartyOption
PartyPreferenceContest
PartyRegistration
Person
RetentionContest
Schedule
ShortString
SpatialDimension
SpatialExtent
StraightPartyContest
StraightPartyRuleset
TimeWithZone
VoteVariation
BallotDefinition
IsTest, Notes, OfficeGroup, Person, TestType
BallotMeasureContest
Abbreviation, BallotSubTitle, ContStatement, EffectOfAbstain, ExternalIdentifier, HasRotation, InfoUri, OtherType, OtherVoteVariation, PassageThreshold, ProStatement, SequenceOrder, SummaryText, TotalSubUnits, Type, VoteVariation
BallotMeasureOption
ExternalIdentifier, SequenceOrder
BallotStyle
ImageUri, Purpose
Candidate
CampaignSlogan, ContactInformation, ExternalIdentifier, FileDate, IsIncumbent, IsTopTicket, PartyId, PersonId, PreElectionStatus, ReadName
CandidateContest
Abbreviation, BallotSubTitle, ExternalIdentifier, HasRotation, NumberElected, NumberRunoff, OtherVoteVariation, RanksAllowed, SequenceOrder, TotalSubUnits, VoteVariation
CandidateOption
ExternalIdentifier, SequenceOrder
Election
ContactInformation, OtherType
Office
ContactInformation, Description, ElectionDistrictId, ExternalIdentifier, FilingDeadline, IsPartisan, OfficeHolderPersonIds
OrderedContest
OrderedContestOptionIds
Party
Color, ContactInformation, ExternalIdentifier, IsRecognizedParty, LeaderPersonIds, LogoUri, PartyScopeGpUnitIds, Slogan
ReportingUnit
AuthorityIds, ContactInformation, ElectionAdministration, ExternalIdentifier, IsDistricted, IsMailOnly, Number, OtherType, PartyRegistration, SpatialDimension, TotalSubUnits, VotersRegistered
Term
EndDate, StartDate, Type
When importing a Ballot Definition CDF file, attributes will be mapped to the VxSuite Election Definition and used across the system in the exact same way.
Election.ExternalIdentifier
Election.id
Election.Type
Election.type
Election.Name
Election.title
Election.StartDate
Election.date
GpUnit.id
County.id, Precinct.id, District.id
GpUnit.Name
Election.state, County.name, Precinct.name, District.name
Party.id
Party.id
Party.Name
Party.name
Party.Name
Party.fullName
Party.Abbreviation
Party.abbrev
Contest.id
Contest.id
Contest.BallotTitle
Contest.title
Contest.ElectionDistrictId
Contest.districtId
CandidateContest.VotesAllowed
CandidateContest.seats
CandidateContest.ContestOption.IsWriteIn
CandidateContest.allowWriteIns
CandidateContest.PrimaryPartyIds
CandidateContest.partyId
Office.Term.Label
CandidateContest.termDescription
Candidate.id
Candidate.id
Candidate.BallotName
Candidate.name
CandidateOption.EndorsementPartyIds
Candidate.partyIds
BallotMeasureContest.FullText
YesNoContest.description
BallotMeasureContestOption.id
YesNoContestOption.id
BallotMeasureContestOption.Selection
YesNoContestOption.label
BallotStyle.ExternalIdentifier.Value
BallotStyle.id
BallotStyle.GpUnitIds
BallotStyle.districts, BallotStyle.precincts
BallotStyle.PartyIds
BallotStyle.partyId
BallotStyle.Language
BallotStyle.languages
BallotFormat.ShortEdge
BallotLayout.width
BallotFormat.LongEdge
BallotLayout.height
OrderedContest.ContestId
GridPosition.contestId
PhysicalContestOption.OptionPosition.Sheet
GridPosition.sheet
PhysicalContestOption.OptionPosition.Side
GridPosition.side
PhysicalContestOption.OptionPosition.X
GridPosition.column
PhysicalContestOption.OptionPosition.Y
GridPosition.row
PhysicalContestOption.ContestOptionId
GridPositionOption.optionId
PhysicalContestOption.ContestOptionId
GridPositionWriteIn.writeInIndex
PhysicalContestOption.WriteInPosition.X
GridPositionWriteIn.writeInArea.x
PhysicalContestOption.WriteInPosition.Y
GridPositionWriteIn.writeInArea.y
PhysicalContestOption.WriteInPosition.W
GridPositionWriteIn.writeInArea.width
PhysicalContestOption.WriteInPosition.H
GridPositionWriteIn.writeInArea.height
Most attributes in the Ballot Definition CDF that could require translation are defined with the CDF InternationalizedText
class which allows specifying variants for each language. InternationalizedText
maps directly onto VxSuite's ballot strings. When an InternationalizedText
attribute is mapped to a ballot string, the English version is used as the default which will appear on reports and administrator interfaces while the translations are maintained in the election definition for multi-language experiences on voter devices.
The Ballot Definition defines all geographies as GpUnit
s, whereas the VxSuite Election Definition defines various geographies.
Some geographies must exist in the Ballot Definition CDF file to be used in VxSuite. There must be one GpUnit
of type state
and one of type county
to populate the relevant metadata on the Election.
Any GpUnit
of type precinct
is mapped to a Precinct.
Any GpUnit
with an associated contest is mapped to a District.
Because VxSuite does not utilize any data extensions to the Ballot Definition CDF, some information cannot be included when using the Ballot Definition CDF. The missing information creates some limitations when using the Ballot Definition CDF when compared to the VxSuite Election Definition format:
Contest term descriptions (e.g. “2 years”) will always show up in English because there is no field in the CDF for internationalized term descriptions
The full party name will be displayed for each candidate on VxMark (e.g. “Democratic Party” instead of “Democrat”) because the CDF only has one attribute for party name. In contrast, the VxSuite format supports two separate fields, one for the full name and one for showing on the ballot.
When adjudicating write-ins, the highlighted contest option area will be set to a default because there is no field in the CDF for this parameter.
Seal images are not supported in the CDF, so no seal will be shown in association with the election.
VxSuite can tabulate a wide variety of ballot designs as long as they conform to the following requirements:
Ballot size must be one of the available system options
Ballot must include correctly formatted timing mark borders
Ballot must include an appropriately positioned metadata QR code
Ballot must use a specific bubble shape
Ballot must adhere to system limits
There are six valid ballot sizes. All are 8.5 inches in width, but vary in height:
Letter
11"
8.5"
Legal
14"
8.5"
Custom 17"
17"
8.5"
Custom 18"
18"
8.5"
Custom 21"
21"
8.5"
Custom 22"
22"
8.5"
These lengths correspond to the length specified in the Ballot Layout within the election definition.
Every ballot must have timing mark borders on both front and back. The timing marks and page margins are strictly defined:
Timing Mark Width
3/16 in.
Timing Mark Height
1/16 in.
Page Margin (Top, Bottom)
12pt (1/6 in.)
Page Margin (Left, Right)
5mm
As for number of timing marks, there are always 34 in the top and bottom borders. The number of marks in the left and right borders varies based on the length of the ballot, and should be calculated by the formula (# inches * 4) - 3. For example, a letter-sized ballot (11 inches) should have 41 left and right timing marks whereas a legal-sized ballot (14 inches) should have 53 left and right timing marks.
The timing marks must be aligned to the margins of the page and evenly spaced.
The ballot must include a QR code which contains key metadata about the ballot.
The QR code includes ballot metadata:
Precinct Index - corresponds to a precinct in the election definition
Ballot Style Index - corresponds to a ballot style in the election definition
Page Number - page number within the ballot style
Test Ballot Flag - indicates whether the ballot is a test ballot or an official ballot
Ballot Type (Precinct, Absentee, or Provisional)
In addition, the QR code includes the ballot hash. The ballot hash ensures that the ballot was generated from the same election definition that will be used to interpret the ballot.
For full specifications on how to generate readable QR codes, view the ballot encoder documentation.
The interpreter looks for ballots in the bottom-left corner of the ballot. The detection area is a square whose sides are 1/4 of the ballot width.
In order to be interpreted correctly, bubbles must meet the following dimensions:
Width
0.20"
Height
0.13"
Border Radius
0.7"
Line Thickness
1px (0.265mm)
The timing mark borders define an abstract grid that VxSuite uses to assign coordinates to positions on the ballot. In the election definition, bubble positions and other ballot regions are specified using these grid coordinates. The ballot grid is an XY grid with the origin in the top-left corner. For example, the coordinate (5, 3) would correspond to the following position on the ballot:
Notes:
Coordinates correspond to the center of each timing mark
Coordinates specify the center of each bubble
Fractional coordinates are allowed
Below is a complete ballot that, when paired with the appropriate election definition, could be interpreted within VxSuite:
The VotingWorks voting system (a.k.a. VxSuite) consists of four primary components:
VxAdmin: election setup and election results manager
VxMark: ballot-marking device (BMD)
VxScan: precinct scanner
VxCentralScan: batch scanner
Using VxSuite for an election begins with generating an election package and hand marked ballots using an external system.
VxAdmin is where the election administrator performs election setup tasks and manages election results. At the beginning of an election, the user configures VxAdmin with an election package. Once configured, VxAdmin is used for two key election setup tasks:
Exporting a copy of the election package to USB drives with a digital signature. The election package is used to configure VxMark, VxScan, and VxCentralScan, and it must be digitally signed by VxAdmin.
Programming role-based smart cards that will be used to authenticate on all machines. While the "System Administrator" role is election-agnostic, the "Election Manager" and "Poll Worker" roles are election-specific and cards must be programmed for every election.
VxAdmin is later used to load, store, and tabulate cast vote records from the scanners. The results are available for review or export in several results formats. Once tabulation is complete, election administrators can mark results as official, after which no new results can be added.
VxMark is the system's ballot-marking device (BMD) that provides an accessible voting experience. At the beginning of an election, it is configured with an election package from VxAdmin. Once configured, a voter can make vote selections in various interaction modes according to their needs.
The following input modes are supported:
Touch, using the touchscreen
Tactile, using the accessible controller
Limited Dexterity, using a sip-and-puff device or other dual-switch input
The following output modes are supported:
Visual, with options to change color contrast and text size
Audio, with navigation instructions and contest details read to the user over headphones
The voter can also adjust the language based on translations included in the election package.
After the voter finishes their vote selections, VxMark prints a machine marked ballot and presents it to the voter. The ballot is scanned (but not cast) so the interpreted results can be presented to the voter on-screen. After reviewing the ballot and confirming their selections, the ballot is cast and ejected into the attached ballot box. At a later time, depending on election procedures, the ballot will be removed from the ballot box and tabulated at one of the system's scanners.
VxScan is the system's precinct scanner. At the beginning of an election, it is configured with an election package from VxAdmin. The election package specifies the ballot layouts. The polls are opened by a poll worker after which casting ballots is allowed. Opening polls prints a tally report which is empty because no ballots have been scanned, a.k.a. the zero report.
Voters cast ballots by inserting their ballots into the scanner in any orientation. After interpreting the scanned ballot, the scanner will drop the ballot into the ballot box and inform the voter that their ballot was successfully cast. During voting, VxScan continuously exports cast vote records to an attached USB drive.
If the election is configured to support second-chance voting and the ballot triggers a configured adjudication reason (e.g. it has an overvote), the scanner will hold the ballot while the voter is notified of the issues on their ballot. The voter then chooses whether to cast their ballot or return it to update or spoil.
When polls are closed, the CVR export is completed and a polls closed report prints. The polls closed report includes the vote tallies of all ballots cast at the scanner while polls were open. Unlike the vote tallies eventually exported from VxAdmin, the vote tallies at VxScan do not contain any post-voting adjudication information such as write-in adjudication. The CVR export on the USB drive is then taken to VxAdmin for adjudication, aggregation, and reporting.
VxCentralScan is the system's batch scanner, often used to scan absentee or provisional ballots. At the beginning of an election, it is configured with an election package from VxAdmin. The election package specifies the ballot layouts.
Ballots are inserted in the batch scanner's hopper and a batch scan is triggered from VxCentralScan. The ballots are scanned and interpreted in succession until the hopper is empty. If a ballot triggers a configured adjudication reason (e.g. it has an overvote), scanning will pause and the ballot will be displayed on screen, at which point the user can choose to tabulate the ballot anyway or remove it, untabulated.
After scanning is complete, the user can export the cast vote records to a USB drive and take the USB drive to VxAdmin for adjudication, aggregation, and reporting.
The VxSuite Election Definition is a data format for defining an election that is specific to VxSuite. It is a JSON file which defines the essential features of an election - metadata, contests, parties, precincts, districts, ballot styles, candidates, and more. In addition to defining that basic structure of the election, the format contains translations for any text which may appear on the ballots and ballot layouts to map the bubbles on each ballot to contest options.
The Election
entity is the top-level entity that contains all other entities.
ballotLayout
Physical ballot metadata
ballotStrings
ballotStyles
All ballot styles
contests
All contests
gridLayouts
county
County metadata
date
string
- YYYY-MM-DD
Date of the election
districts
All districts
id
string
Unique identifier
parties
All parties
precincts
All precincts
seal
string
- SVG file format
Seal for the election
state
string
Name of the state
title
string
Title of the election
type
string
- "general" or "primary"
Type of the election
The ballot layout entity includes basic information about the physical ballots used for the election.
paperSize
string
Indicates physical length of the ballot
metadataEncoding
string
Indicates how the ballot metadata will be encoded on the ballot
The paperSize
attribute accepts the following valid options:
The metadataEncoding
attribute must be "qr-code".
Each ballot style corresponds to a single- or multi-sheet ballot. The contests on a ballot style are determined by its associated districts - every contest belonging to an associated district is considered a part of the ballot style. A ballot style may be used in multiple precincts, one ballot style might correspond to multiple ballot PDFs that have identical contest layouts but different precinct labels.
id
string
Unique identifier
precincts
The IDs of all precincts which use the ballot style
districts
The IDs of all districts whose contests are included in the ballot style
partyId
Optional. The ID of the party to which the ballot belongs, if a primary
languages
array
- string
Optional. The language codes for the languages covered by the ballot style
There are two types of contests - candidate contests and yes-no contests. Both types share core attributes:
id
string
Unique identifier
districtId
The associated district of the contest such as a state, county, or ward
title
string
Title of the contest
type
string
- "candidate" or "yesno"
Type of the contest
In a candidate contest, the voter makes a selection between pre-defined candidates or write-in options. The following attributes extend the shared Contest attributes:
seats
number
The number of selections a voter can make
candidates
Candidate options for the contest
allowWriteIns
boolean
Whether the contest allows write-ins
partyId
Optional. The ID of the party to which the contest belongs, if a primary
termDescription
string
Optional. Description of the term of the position, such as "For three years"
id
string
Unique identifier
name
string
Name as it appears on the ballot
partyIds
Optional. The IDs of the parties associated with the candidate. The party name will appear next to the candidate
In a yes-no contest, also known as a ballot measure, the voter makes a selection between two options. The following attributes extend the shared Contest attributes:
id
string
Contest description
yesOption
"Yes" option
noOption
"No" option
id
string
Unique Identifier
label
string
Label e.g. "Yes" or "No"
One and only one county is associated with each election.
id
string
Unique Identifier
name
string
Name e.g. "Choctaw County"
Districts are used to define levels at which a contest takes place. For example, an election may have districts defined for the state, county, town, and ward levels. Different contests can be associated with each of those levels.
id
string
Unique Identifier
name
string
Name e.g. "State of Mississippi"
Parties are used in the data model either to associate candidates with a party, associate ballot styles with a party for a primary, associate contests with a party for a primary
id
string
Unique Identifier
name
string
Short name which will appear on the ballot besides candidates e.g. "Republican"
fullName
string
Full name which will appear in reports and in the titles of ballots e.g. "Democratic Party"
abbrev
string
Abbreviation for a party e.g. "R"
id
string
Unique Identifier
name
string
Name e.g. "Fire Station"
The ballotStrings
object contains the translations for any text which may appear on the ballot. The text falls into one of two categories: instructional text or election-specific text.
Examples of instructional ballot text include:
"To vote, completely fill in the oval next to your choice."
"Vote for up to 3",
"Official Absentee Ballot"
Although the system does not use the hand marked ballot instructional text for any purpose, it must be included in the election definition for security purposes. When included, it becomes a part of the ballot hash and cannot be changed without invalidating older ballots.
The core data model already includes names and labels. For example, the Precinct entity already has a name
attribute. The names within the data model are used by default in the system in reports and administrative menus. The translations for all of these names are within the ballotStrings
and are important for two main reasons:
The language-specific strings are used to accommodate multi-lingual voting on VxMark
Including the translations in the election definition means they are included in the ballot hash and cannot be changed without invalidating older ballots.
The election-specific ballotStrings
recognized by the system are the following:
Ballot Language
ballotLanguage
string
Ballot Style IDs
ballotStyleId
Candidate Names
candidateName
Contest Descriptions
contestDescription
Contest Option Labels
contestOptionLabel
Contest Terms
contestTerm
Contest Titles
contestTitle
County Name
countyName
string
District Names
districtName
Election Date
electionDate
string
Election Title
electionTitle
string
Party Full Names
partyFullName
Party Names
partyName
Precinct Names
precinctName
State Name
stateName
string
The language codes used are the IETF language tags for supported VxSuite languages: English, Spanish, Simplified Chinese, and Traditional Chinese.
Grid layouts describe where the bubbles and write-in areas exist on each ballot style. They must correspond exactly to the ballots used for the election in order for interpretation to succeed. For more information on the acceptable ballot format and its relationship to grid coordinates, see Hand Marked Ballots.
gridLayouts
is an array
which contains entities with the following attributes:
ballotStyleId
Identifies the ballot style
optionBoundsFromTargetMark
Describes where the entire contest option area sits relative to the bubble
gridPositions
Describes bubble and write-in positions on the ballot
The optionBoundsFromTargetMark
field specifies an Outset
entity. The purpose is to give the distance from the bubble to edges of the entire contest option e.g. the area that includes the bubble, the corresponding candidate's name, and some padding. The system uses this area during write-in-adjudication to highlight specific contest options for review.
top
number
Distance from center of bubble to top of option bounds
right
number
Distance from center of bubble to right of option bounds
bottom
number
Distance from center of bubble to bottom of option bounds
left
number
Distance between center of bubble to left of option bounds
Grid positions are defined positions on the ballot corresponding to bubbles that can be marked by a voter. The row
and column
coordinates of each grid position denote where the bubble is printed within the abstract "grid" created by the timing marks on the outer edges of the ballot. There are two types of positions - a standard option position corresponding to a candidate or option in the election definition or a write-in position corresponding to a write-in bubble and area on the ballot.
type
string
- "option"
Indicates this is a standard option position
sheetNumber
number
1-indexed sheet number within the ballot style
side
string
- "front" or "back"
Indicates side of the sheet
column
number
Column position of the bubble in the timing mark grid
row
number
Row position of the bubble in the timing mark grid
contestId
Contest identifier
optionId
Option identifier
type
string
- "write-in"
Indicates this is a write-in option position
sheetNumber
number
1-indexed sheet number within the ballot style
side
string
- "front" or "back"
Indicates side of the sheet
column
number
Column position of the bubble in the timing mark grid
row
number
Row position of the bubble in the timing mark grid
contestId
Contest identifier
writeInIndex
number
An index of the write-in position within the list of write-in positions for a contest (zero-indexed)
writeInArea
Area of the ballot to scan for a write-in
In some jurisdictions, a write-in can only be counted if the associated bubble is filled in as for any other option. In other jurisdictions, a write-in must be counted even if the bubble is not filled. In order to detect these write-ins, a writeInArea
is defined for each write-in grid position. The Rectangle
specifies the area.
x
number
Column start of the rectangle
y
number
Row start of the rectangle
width
number
Width of the rectangle
height
number
Height of the rectangle
Election definition examples are located in the vxsuite
repository, such as here.
After a voter is done making vote selections with VxMark, the machine will print a ballot representing the selections. The voter reviews the ballot, after which it is deposited into the attached ballot box. Eventually, those ballots are scanned at VxScan or VxCentralScan.
The ballot displays information about the election, metadata about the ballot, and the voter's selections. The selections are both displayed and encoded in the QR code.
Election Seal
The seal included in the election definition
Ballot Title
The title is either "Unofficial Test Ballot" or "Official Ballot" depending whether VxMark is in test mode
Election Metadata
Includes the election title, election date, state, and county
Ballot Metadata
Includes the precinct name, the ballot style identifier, and the ballot identifier. The ballot identifier is a random UUID assigned by VxMark.
QR Code
Contest Title
The contest title
Selection
The name of the candidate or label of the yes-no contest option that the voter selected
Party
The short party name associated with the selected candidate
The blank space at the top of the ballot is included so that all of the ballot content is visible when VxMark presents the ballot for the voter to review (since the top part of the ballot is held in the machine).
If VxMark is being used in a language other than English, the resulting ballot will be multi-lingual and feature the other language. All pieces of text that appear on the VxMark ballot may have translations specified in the election definition's ballot strings, which will then be used when printing the ballot.
The QR codes on VxMark ballots are different than the QR codes on hand marked ballots in that they actually contain voter selections in addition to the ballot metadata. For full specifications on how metadata and selections are encoded, view the ballot encoder documentation.
The write-in adjudication report includes the results of all write-in adjudication organized by contest:
The values in the contest table above are as follows:
Before adjudication, write-ins are treated as votes for a generic write-in candidate and will appear in tally reports as "Unadjudicated Write-In." After adjudication, the new value will be reflected on tally reports:
When adjudicated for an official candidate, the write-in will be added to the official candidate count just as a regular vote for the candidate would be
When adjudicated for a write-in candidate, either:
The write-in will appear in the adjudicated write-in bucket if it is not relevant to the results
When invalid, the write-in becomes an undervote
Unmarked write-ins behave differently in relationship to the tally results because they cannot be considered a valid vote before adjudication. As a result, they are considered undervotes before adjudication. If an unmarked write-in is adjudicated as invalid, then tally results will not change. If an unmarked write-in is adjudicated for a candidate, the unmarked write-in is no longer an undervote and is added to the vote total for that candidate.
Also note that, because the write-in adjudication report includes unmarked write-ins, the "Unadjudicated Write-In" count on tally reports may be less than the "Not Adjudicated" count on the write-in adjudication report. The initial difference is the count of unmarked write-ins.
A cast vote record is a record of voter selections based on the system's interpretation of a scanned ballot. Each cast vote record corresponds to a single scanned ballot sheet. Multi-sheet ballots produce multiple cast vote records.
Cast vote records are exported from VxScan and VxCentralScan onto USB drives and then imported into VxAdmin. Each cast vote record export is created with a digital signature. VxAdmin verifies this signature when importing cast vote records to ensure that the export has not been tampered with.
In order to export cast vote records efficiently and without compromising voter privacy, every cast vote record is generated individually. The structure of a cast vote record directory is as follows:
The cast vote record export contains a directory for each cast vote record, labelled with its UUID. Each specific cast vote record directory contains:
Cast Vote Record Report - Contains information about the election and the ballot interpretation in the Common Data Format. The information in the report is used as the basis for tabulation by VxAdmin.
Images - Ballot images to be used in write-in adjudication or auditing
Interpreted Ballot Layouts - Metadata for the position of ballot features such as contests, contest options, and bubbles in the ballot image. The interpreted layout data is used to properly crop and highlight ballot images for write-in adjudication.
In addition, there is a metadata file that applies to the entire export at the root of the directory, metadata.json.
The v4 UUID (universally unique identifier) for each cast vote record is generated when the ballot information is first stored in the database in VxScan or VxCentralScan. It is generated with the node package uuid
which uses the system's underlying FIPS-complaint OpenSSL implementation to generated random bytes.
In VxScan, ballot images and layouts are always included. In VxCentralScan, ballot images and layouts are only included in the cast vote record export if the ballot has write-ins that may require adjudication. When exporting a backup from VxCentralScan, however, ballot images and layouts are included for all ballots.
Layouts are not included for machine marked ballots.
In VxScan, images of rejected ballots are always included. In VxCentralScan, images of rejected ballots are not included in the cast vote record export but are included in the backup. There are no layout files or cast vote record report for rejected ballots because they are often uninterpretable. When rejected ballots are included, they will appear in the directory with the prefix rejected-
, as in the following example:
Because VxAdmin requires a VxSuite digital signature on all imported cast vote records, it's not possible to import a cast vote record from outside of VxSuite. The goal of using CDF is to help external systems consume VxSuite cast vote records for audit or analysis.
Only one ReportingDevice
is ever listed:
Each cast vote record includes a set of ballot metadata attributes:
The CVR.BallotImage
attribute exists when there are images accompanying the cast vote record. If it exists, it always contains images for both sides of the ballot. Its attributes are as follows:
Hashes of the ballot image and ballot layout files are included in the cast vote record report so that the hash (and digital signature) of the cast vote record export will reflect any change to the image or layout files.
The CDF specification allows detailing multiple versions of the same cast vote record as "snapshots."
For hand marked paper ballots, there are both "original" and "modified" snapshots. The "original" snapshot contains mark thresholds for every single bubble on the ballot and is included purely for auditability. The "modified" snapshot contains only the marks that were detected as definite marks and counted as valid or invalid votes.
For machine marked ballots, there is only an "original" snapshot.
The snapshot is referenced in the CVR.CurrentSnapshotId
field by it's identifier, which will be the unique identifier of the cast vote record along with its type, such as
The CDF specification does not have any allowance for a ballot type such as "absentee" or "precinct" at the metadata level, so it is added as information to each snapshot:
The CVRContest
class within each snapshot contains a list of vote records by contest. The fields are used as follows:
Ballot images are .jpg
files. They are included in the cast vote record in order to be used for write-in adjudication or auditing. Ballot images are generated by the scanning hardware and then normalized to reduce skew and enforce a consistent orientation. Images from VxCentralScan are in grayscale while images for VxScan are in black and white.
Ballot layouts are JSON files which describe the discovered position of ballot content within interpreted ballots, including where each contest and contest option appears. Although the layout of ballot content within the ballot grid is specified by the election definition, the ballot content may be positioned in a slightly differently location in each scanned ballot image due to offset or skew of the ballot during scanning. As a result, the layouts are included in order to have accurate image highlights and crops for write-in adjudication.
The metadata file includes data that applies to all cast vote records in the export. There is only one per export. The relevant attributes are:
Each cast vote record is associated with a batch via its BatchId
metadata field. The CDF doesn't have a place within the cast vote record report to include batch metadata, so it is included here.
array
-
array
-
array
-
array
-
array
-
array
-
array
-
array
- IDs for
array
- IDs for
string
- ID for
string
- ID for
array
-
string
- ID for
array
- ID for
key-value pairs, IDs mapped to names
key-value pairs, IDs mapped to names
key-value pairs, IDs mapped to descriptions
key-value pairs, IDs mapped to labels
key-value pairs, IDs mapped to term descriptions
key-value pairs, IDs mapped to titles
key-value pairs, IDs mapped to names
key-value pairs, IDs mapped to their full names
key-value pairs, IDs mapped to their short names
key-value pairs, IDs mapped to names
string
, ID for
string
- ID of
string
- ID of or
string
- ID of
See
The write-in will be individually listed if it is
VxSuite does not use any data extensions beyond the NIST specification, but some fields are made required that are not required in the original NIST specification. The two specifications can be compared by comparing the with the . The additionally required fields are listed in a table below.
The CDF specification includes many metadata fields that might help a consumer make sense of the cast vote record data. For example, you may define the candidates that are referenced as contest selections. VxSuite cast vote records all include this metadata to conform to the CDF, but nearly none of it is actually utilized when imported into VxAdmin. VxAdmin already has that information from the . The only data that is utilized by VxAdmin is the GeneratedDate
and the indication of whether or not the report is a test report in ReportType
and OtherReportType
.
The list of parties in the cast vote record report is mapped directly from the list in the election definition:
GpUnit
s are created for each in the election, for the , and for the state:
The Election
class has values mapped to it directly from the :
Total Write-Ins
The count of all write-ins. If unmarked write-ins are being adjudicated, they will be included in this count
Not Adjudicated
The count of all write-ins that have not been adjudicated in the write-in adjudication interface yet
Official Candidate Counts
The count of all write-ins that have been adjudicated for official candidates in the election definition
Write-In Candidate Counts
The count of all write-ins that have been adjudicated for write-in candidates added at VxAdmin
Invalid
The count of all write-ins that have been marked as invalid
CVR
BallotStyleId, BallotStyleUnitId, BatchId, CreatingDeviceId, UniqueId
CVRContest
CVRContestSelection
CVRContestSelection
ContestSelectionId
SelectionPosition is limited to length 1
CVRSnapshot
CVRContest
Version
Fixed to "1.0.0"
ReportType
Always includes "originating-device-export". If a test report, also includes "other"
OtherReportType
If a test report, "test", otherwise undefined
GeneratedDate
The generated date in Date Time String Format
ReportGeneratingDeviceIds
The scanner serial number
@id
The scanner serial number
SerialNumber
The scanner serial number
Manufacturer
Fixed to "VotingWorks"
@id
The party identifier from the election definition
Name
The full name of the party, e.g. "Democratic Party"
Abbreviation
The abbreviation of the party, e.g. "R"
@id
Precinct: The precinct identifier from the election definition
County: Fixed to "election-county"
State: Fixed to "election-state"
Type
Precinct: "precinct"
County or State: "other"
Name
The precinct, county, or state name
@id
The election's ballot hash
Name
The title of the election
ElectionScopeId
Fixed to "election-state"
Candidate.@id
The candidate identifier from the election definition
Candidate.Name
The candidate name
Contest.@id
The contest identifier from the election definition
Contest.Name
The contest title
CandidateContest.VotesAllowed
The contest's number of seats
CandidateContest.PrimaryPartyId
The party identifier of the associated party, if a primary contest
CandidateSelection.@id
The candidate identifier from the election definition
CandidateSelection.CandidateIds
The candidate identifier from the election definition
CandidateSelection.IsWriteIn
Whether the selection represents a write-in bubble
BallotMeasureSelection.@id
The option identifier from the election definition
BallotMeasureSelection.Selection
The option label that appeared on the ballot
BallotSheetId
The index of the sheet within the ballot. For the second sheet of a multi-sheet ballot, it would be 2
BallotStyleId
The ballot style identifier from the election definition
BallotStyleUnitId
The precinct identifier from the election definition
Batch
The batch identifier
CreatingDeviceId
The scanner serial number
ElectionId
The election's ballot hash
PartyIds
The party identifier from the election definition, if for a primary ballot
UniqueId
The UUID for the ballot generated by the scanner
BatchSequenceId
When using VxCentralScan, contains the index of the sheet within the batch. 1-indexed.
BallotAuditId
When using an imprinter on VxCentralScan, contains the UUID imprinted on the ballot
Location
Location of the image file relative to the report, such as:
Hash.Type
Fixed to "sha-256"
Hash.Value
No Images: Undefined
Images & Layouts: {SHA256 hash of image}-{SHA256 hash of layout}
Images Only: SHA256 hash of image
CVRSnapshot.Status
Fixed to ["other"]
CVRSnapshot.OtherStatus
JSON blob representing the ballot type. The possible values are "absentee", "precinct", or "provisional".
CVRContest.ContestId
The contest identifier from the election definition
CVRContest.Overvotes
The number of overvotes for a contest. The number can only be 0 or the maximum number of votes in the contest
CVRContest.Undervotes
The number of undervotes for a contest
CVRContest.WriteIns
The number of write-ins for a contest
CVRContest.Status
The list of applicable contest statuses:
"not-indicated" - no votes cast in contest
"undervoted" - fewer than allowed votes cast in contest
"overvoted" - more than allowed votes cast in contest
"invalidated-rules" - applies if overvoted
CVRContestSelection.ContestSelectionId
The option identifier from the election definition
CVRContestSelection.OptionPosition
The index of the contest position within the contest
CVRContestSelection.Status
The list of applicable contest selection statuses:
"invalidated-rules" - mark is part of an overvote
"needs-adjudication" - mark corresponds to a write-in
SelectionPosition.HasIndication
"yes" or "no" depending on whether a mark in the bubble passed the mark threshold. In the original hand marked paper ballot snapshots, this may be either value. In the modified snapshot, it is always "yes" except for unmarked write-ins.
SelectionPosition.NumberVotes
Fixed to 1
SelectionPosition.IsAllocable
"yes" except:
"no" if an overvote
"unknown" if an unmarked write-in
SelectionPosition.MarkMetricValue
The mark score, a decimal between 0 and 1.00 such as 0.23. Only included in the original snapshots.
SelectionPosition.Status
"invalidated-rules" if an overvote
"needs-adjudication" if an unmarked write-in
SelectionPosition.OtherStatus
"unmarked-write-in" if an unmarked write-in
CVRWriteIn.WriteInImage
The BallotImage
data for the side of the sheet on which the write-in occurs
arePollsClosed
For VxScan exports, the flag indicates whether polls where closed at the time of export. If polls were not closed, that may indicate an incomplete export
castVoteRecordReportMetadata
The cast vote record report without any specific cast vote record data. In other words, only data about the election and its contests
castVoteRecordRootHash
A hash of all cast vote record files in the export. Including the hash here, which rolls up into the digital signature, ensures that cast vote records cannot be added or removed from the export
batchManifest
The list of batches on the originating scanner, see below
id
The UUID of the batch generated by the scanner
label
The label for the batch
batchNumber
The sequential number of the batch, e.g. 2 for the second batch
startTime
The time a batch was started in ISO 8601 format
endTime
The time a batch ended in ISO 8601 format
sheetCount
The number of sheets (i.e. cast vote records) in a batch
scannerId
The serial number of the scanner
VxSuite has four authenticated user roles. Authentication is performed with JCOP4 Java Cards, a security-oriented type of smart card. Each card is programmed with a single role and, in most cases, a PIN for two-factor authentication. Details of the authentication system can be found here: Access Control.
The poll worker role is the lowest privilege role for election day tasks at the precinct.
The poll worker role allows a user to manage the polls on the precinct equipment, VxScan and VxMark. On both devices, the poll worker card is used to open and close polls on election day. On VxMark, the poll worker card is used to enable voter sessions. There are a few other actions enabled by the poll worker card - reprinting reports, powering down the machine, or checking the software hash - but overall the role is quite limited.
All poll worker cards are programmed at VxAdmin and are programmed for a specific election. They must be reprogrammed for every election. Poll worker cards may or may not require PINs depending on the value of arePollWorkerCardPinsEnabled
flag in the system settings file within the election package.
The poll worker role has no purpose on the central equipment, VxAdmin and VxCentralScan, and poll worker cards will be ignored on those devices.
The election manager role is a broad role for election officials to setup and operate the election.
On the precinct equipment, an election manager card is used to configure the machines at the beginning of each election. This includes loading the election package, selecting a precinct for the device, and checking on consumables such as thermal paper for VxScan. At the end of an election, the election manager card can be used to unconfigure machines, re-export results, and export logs. In addition, system functions like setting date and time, turning on and off certain features, and accessing system diagnostics are available to election managers. The election manager card is not usually required at the precinct on election day, however, where the poll worker card should be sufficient for all election day tasks.
On the central equipment, an election manager card is used to access core election management features. On VxAdmin, it is used to load, adjudicate, review, and export results. On VxCentralScan, it is used to operate the scanner and export results.
All election manager cards are programmed at VxAdmin and are programmed for a specific election. They must be reprogrammed for every election. They alway have PINs, which change after reprogramming the cards for a new election.
The system administrator role is a powerful role for initial election setup and machine management. Unlike the poll worker and election manager roles, they are not tied to specific elections.
On VxAdmin, a system administrator card is necessary to initially load an election package from an external system. System administrators can then program poll worker cards and election manager cards for a specific election. In that sense, the system administrator role is the gatekeeper for loading elections and creating users, and is strictly necessary for every election.
On all devices, the system administrator role allows accessing a menu with powerful system actions. Many actions are shared with election managers - unconfiguring a machine or setting the date and time. Others are unique to the system administrator. For example, on precinct devices a system administrator can reset polls from a "closed" state to a "paused" state in case a poll worker accidentally closes polls prematurely.
Additional system administrator cards can be programmed by a system administrator at VxAdmin. System administrator cards always have PINs. Because a system administrator card is necessary to program cards or set up elections to begin with, at least one pre-programmed card is initially provided with the voting system to bootstrap the jurisdiction's authentication.
The vendor role is a role that only VotingWorks itself has access to. It allows booting into an administrative menu with options to update various system configuration files.
While the authentication model only includes the four aforementioned roles, one can conceptually describe a "voter mode" on the precinct devices. On VxMark, a poll worker must authenticate in order to initiate a voting session. Once initiated, the voter is able to make selections, navigate menus, and print their ballot. Once done voting, the machine leaves voter mode and once again requires authentication to start a voting session. On VxScan, voter mode is any time the polls are open and no other role is authenticated, during which a ballot can be inserted for tabulation.
The basic structure of the tally reports printed from VxAdmin is similar to the polls opened and closed reports printed from VxScan.
In addition to the full election report, VxAdmin exports reports filtered or grouped by the following dimensions:
Ballot Style
Precinct
Voting Method
Scanner
Batch
District (filtering only)
When a report is grouped, the report is broken up into multiple sections each with their own filter. For example, if you were to group by "Voting Method," the resulting report would have a section filtered for precinct ballots only and a section filtered for absentee ballots only:
The filter for a given report section is indicated in the title of the report. If the report has more than one filter applied to it, the full details of the filter will be specified in a box below the title:
Note that filters and groups can be combined.
If manual results have been added, they will be included in the tally report alongside the scanned results. For each contest, there will be three results columns: "scanned", "manual", and "total".
In order to prevent a long list of write-in candidates from making contest results difficult to read, VxAdmin tally reports consolidate write-in candidates if they're not relevant to the contest outcome. Relevant write-ins are included as "<Name> (Write-In)". Irrelevant write-ins are consolidated as "Write-In" or, if there are relevant write-ins in the list, "Other Write-In". Unadjudicated write-ins are always consolidated as "Unadjudicated Write-In."
A write-in is deemed relevant if it must be listed for the reader to determine the winner(s) of the contest. In the middle example below, the single adjudicated write-in is consolidated because Natalie Portman is the winner regardless of the identities of the write-ins. In the last example, however, there are 31 adjudicated write-ins so it's possible that a write-in got more votes than Natalie Portman. The report then enumerates the write-ins with the highest vote totals until the "Other Write-In" count is smaller than the counts for all winners.
Both tally reports and ballot count reports can be exported in comma-separated values (CSV) format.
In the CSV tally report, the vote total for each candidate or contest option is listed in a single row. In addition, there are rows for overvote and undervote totals for a contest.
For example, here is an excerpt of a tally report including the results for one contest:
The "Precinct" and "Precinct ID" columns are metadata fields that are included because this example export groups results by precinct. The other fields are standard fields:
Contest
The title of the contest
Contest ID
The internal identifier of the contest in the election definition
Selection
The candidate name for candidate contests, the option label for yes-no contests, or "Overvotes" or "Undervotes"
Selection ID
The internal identifier of the contest option, or "overvotes" or "undervotes"
Total Votes
The vote count for the selection
If manual results were entered, two additional columns will be added - "Scanned Votes" and "Manual Votes." These columns denote which votes for each selection came from the scanners vs manual entry.
The results of write-in adjudication are always included in the CSV exports. All write-in candidates will appear with their adjudicated name and a UUID assigned by VxAdmin. Unadjudicated write-in candidates will appear as "Unadjudicated Write-In" with the ID "write-in". Unlike in the printed reports, write-in candidates are never consolidated.
The ballot count report CSV is the same as the table presented in the printed ballot count reports. For example:
The "Precinct", "Precinct ID" and "Voting Method" columns are metadata fields that are included because this example export groups results by precinct and voting method. The other fields are standard fields:
BMD
The count of machine marked ballots
HMPB
The count of hand marked paper ballots. In a multi-sheet election, this is just the count of the first sheet
HMPB Sheet {N}
The count of a particular ballot sheet. The count of the second sheet of all ballots would be "HMPB Sheet 2"
Manual
The count of manually entered ballots
Total
The total ballot count
Any filters or groupings which apply to each row will be indicated in the row itself by metadata columns. For example, in the example export above, the "Precinct" column lists which precinct group each row represents.
If a row is filtered by a single attribute value (e.g. represents one precinct rather than multiple precincts) then the following basic metadata fields are used:
Precinct
The name of the precinct
Precinct ID
The identifier of the precinct from the election definition
Party
The short name of the party e.g. "Republican". Included by default if the ballot style is included, in a primary.
Party ID
The identifier of the party from the election definition
Ballot Style ID
The identifier of the ballot style
Voting Method
"Absentee", "Precinct", or "Provisional"
Scanner ID
The serial number of the scanner. Included by default if the batch is included.
Batch
The label of the scanned batch
Batch ID
The scanner-assigned UUID of the scanned batch
If a row is filtered by multiple attribute values, the following columns may be used:
Included Precincts
The precinct identifiers separated by commas
Included Parties
The party identifiers separated by commas
Included Ballot Styles
The ballot style identifiers separated by commas
Included Voting Methods
The voting method labels ("Precinct", "Absentee", or "Provisional") separated by commas
Included Scanners
The scanner serial numbers separated by commas
Included Batches
The batch identifiers separated by commas
In cases as above, where a row value includes comma-separated values, those values will be wrapped in quotation marks per typical CSV formatting in order to allow consumers to properly differentiate columns.
VxAdmin and VxCentralScan are both laptops that connect to peripherals as needed. The laptop is a custom configured HP Elitebook 840 14" G11.
The relevant hardware interfaces are:
Smart Card Reader - Enables reading and writing to smart cards, which is the basis for authentication in VxSuite
USB Ports - Allows connecting to the peripherals for scanning or printing
While not strictly necessary, VxAdmin and VxCentralScan are bundled with a mouse and a USB hub for ease of use. A USB A-B cable is included to connect to the peripherals.
VxAdmin connects to a printer for the purposes of printing reports. The printer includes an RJ45 (ethernet) port which is blocked by a port blocker because network connectivity is not required by the system.
VxCentralScan connects to a batch scanner for batch scanning. The scanner is either the smaller Ricoh fi-8170 or the larger Ricoh fi-7600. Ballots are loaded into the hopper and then, after a scan is triggered from the application, the scanner processes the ballots one-by-one, sending images to the application for interpretation.
Both batch scanners can be used with Ricoh imprinters (not pictured) which allow printing an identifier on each ballot as it's exiting the scanner, which can be useful for certain types of post-election audits.
The batch scanner is powered through an Anker Solix C300 LFS (Lithium Ferrite System) UPS (Uninterruptible Power Supply) to ensure that the scanner can operate in variable power environments.
The fi-8170 includes an RJ45 (ethernet) port which is blocked by a port blocker because network connectivity is not required by the system.
All components for VxAdmin and VxCentralScan are commercial-off-the-shelf (COTS) components. Data sheets and related documentation are available in the documentation repository.
HP
Elitebook 840 11" G11 Laptop
B43P6UP#ABA
High
Tripp Lite
4-Port Ultra-Slim USB Hub
U360-004-SLIM
Medium
Logitech
B100 Mouse
910-006061
Medium
Monoprice
USB-A to USB-B 2.0 6ft Cable
5438
Medium
HP
LaserJet Pro 4001dn Printer
2Z600F#BGJ
Medium
Lindy
RJ45 Port Blocker
40471
Low
VxCentralScan can be used with either the Ricoh fi-8170 or the Ricoh fi-7600, but does not need both. Each scanner can be paired with one of the two imprinters listed below.
Ricoh
fi-8170 Small Desktop Scanner
PA03810-B055
High
Ricoh
fi-819PRB Imprinter (for fi-8170)
PA03810-D201
Medium
Ricoh
fi-7600 Large Desktop Scanner
PA03740-B505
High
Ricoh
fi-760PRB Imprinter (for fi-7600)
PA03740-D101
Medium
Anker
Solix C300X Portable Power Station
A1723
Low
Lindy
RJ45 Port Blocker
40471
Low
The laptop is a custom configuration of the widely available HP Elitebook 840 14" G11 laptop. B43P6UP#ABA is the HP SKU of the VotingWorks configuration, which includes the following:
Processor
Intel® Core™ Ultra 5 Processor 125U
Memory (RAM)
8GB (1x8GB) DDR5 5600 SODIMM Memory
Storage (SSD)
256GB PCIe NVMe Solid State Drive
Display
14" WUXGA UWVA LED (300 nits)
Battery
56Wh Capacity
Webcam
None
Near Field Communication
None
WWAN (Cellular)
None
WLAN (Wi-Fi)
None
Fingerprint Sensor
None
Smart Card Reader
Included
Country of Origin
TAA Designated
As listed in the bill of materials above, the high criticality components are as follows:
HP Elitebook 840 11" G11 - As the processor and data store for ballot data and other tallies, the laptops are one of the most critical components in the entire system. HP is the only manufacturer. VotingWorks is an official OEM partner of HP in order to work closely together to ensure the quality and configuration of the laptops.
Ricoh fi-7600 & fi-8170 - As the source of ballot images for VxCentralScan, the Ricoh scanners are highly sensitive and critical components.
The medium criticality components and the reasons for their classification are as follows:
Tripp Lite Ultra Slim USB Hub - Manages flow of data between laptop and peripherals.
Logitech B100 Mouse - Does not directly handle election data but does plug into a USB port, thus it could still pose a USB attack vector.
Monoprice USB A-B Cable - Manages flow of data between laptop and peripherals.
HP LaserJet Pro 4001dn - The VxAdmin printer is responsible for printing reports from VxAdmin and therefore handles highly sensitive election information. All reports from VxAdmin can be exported as PDFs and printed elsewhere, so it is not strictly necessary for the operation of the system and thus is not the highest criticality.
Ricoh fi-760PRB & fi-819PRB - The imprinters that pair with the Ricoh scanners are not involved in generating ballot data, so they cannot influence the interpretation of ballots when used according to instructions. The imprinted identifiers are important for post-election audits, however, so the imprinters are security-sensitive components.
Ballot count reports contain ballot and ballot sheet counts, not contest results.
The ballot counts are broken down by ballot type - "HMPB" (for hand marked ballots), "BMD" (for machine marked ballots), and "manual" (for manually entered results, if applicable).
If there are multi-sheet ballots, the hand marked ballot counts may have sheet counts specified. The ballot count is determined by counting the first sheet of each ballot style.
When grouping is applied in a ballot count report, each group corresponds to a row in the table. In the following example, the ballot counts are grouped by both precinct and voting method:
The following metadata columns may appear in a ballot count report table in order to specify groupings:
Filters apply to the entire report. Simple filters are shown in the title, while complex filters are listed in a box below the title.
When polls open or close on VxScan, a tally report is printed. The tally report contains the tally results (pre-adjudication) of all ballots scanned at the scanner.
The tally report header contains the following information:
Title - Includes the type of the polls report and the name of the precinct, or "All Precincts" if VxScan is configured to accept ballots from all precincts
Subtitle - For primary elections, includes the full party name or "Nonpartisan Contests"
Election Info - The title, date, and location of the election
Timestamps - The first timestamp indicates when the poll status changed and the second indicates when the report was printed. In most cases these times are the same, but in some cases the report may be printed later.
Election ID - The election ID on the report is a concatenation of the and specifies exactly which election definition and election settings that the report corresponds to
Certification Signatures - The space is provided for poll workers or election officials to sign the report in accordance with local statute.
The ballot counts table provides the count of hand marked vs. machine marked ballots. For elections with multi-sheet ballots, it provides counts per sheet.
Each candidate or contest option appears in a row below the contest header. Because results at VxScan are not yet adjudicated, all write-ins are grouped under the "Write-In" bucket (except unmarked write-ins, which are reported as undervotes until adjudicated at VxAdmin).
As a rule, the sum of the number of votes for all candidates, the number of undervotes, and the number of overvotes will equal the number of total possible votes for the contest, which is the number of ballots times the number of selections allowed.
When voting is paused or resumed, VxScan prints a report containing the ballot count. Tally results are never included. The header is structured in the same way as the polls opened and closed reports.
The full election tally reports can be exported as JSON Election Results Reporting CDF results. The feature is only available for the full election results and not grouped or filtered results. The export follows the CDF specification without extensions. The CDF fields are used as follows:
VotingWorks software is open-source, which means that the code is free and publicly available. All code written by VotingWorks and almost all dependencies are open-source, with the notable exception of third-party firmware for various hardware components.
All system components - VxAdmin, VxCentralScan, VxMark, VxScan - run different application code but have fundamentally the same software architecture. The rest of this document applies to all system components unless otherwise noted.
The system uses 12 as the base operating system. Debian is a free and open source Linux distribution developed by the Debian Project. The operating system is first installed with the minimally required dependencies and then any additional packages required by the system are installed during build time.
Due to the extensive security measures, users are limited to using the application software and will not have access to Debian's typical set of features.
All machines are completely disconnected from any network and have network capabilities disabled, but the frameworks and architecture employed are borrowed from web-based development. The user interacts with a restricted browser which communicates with a server that provides the web-content and another server that provides application data and hardware status.
The hardware peripherals are polled and managed through the application backends. For example when detecting the status of the card reader, the browser polls the backend server which in turn polls the hardware itself and returns a status to the browser. In order to manage changing states of more complex hardware such as scanners, the backends use state machines.
The exact layer between the application backend and the hardware varies by hardware. Some run in-process whereas others run as a separate process with which the backend communicates. For the accessibility peripherals - the accessible controller and the sip-and-puff interface - the backend starts and manages a daemon which surfaces user input directly to the browser as keyboard commands.
In many cases VotingWorks has written custom drivers that interface directly with the USB device. In other cases, VotingWorks leverages open-source middleware layers installed as Debian packages:
Firmware for embedded devices such as screens and speakers is bundled with the operating system.
On hand marked paper ballots, voters fill in bubbles next to their selections. Because voter indications are made and reviewed directly by the voter, they are inherently voter-verified. The software interprets the image of the ballot for tabulation but, of course, the paper ballot persists after scanning.
For machine marked paper ballots, voters make selections on screen at VxMark. After the voter has made all their selections, the ballot is printed and presented to the voter. The ballot displays a textual representation of the selections and a QR code with the selections encoded. The voter reviews the ballot and, once accepted, the voter-verified ballot is ejected into the attached ballot box. VxMark's machine marked ballots are not actually tabulated until they are scanned at a scanner.
Ballots are never modified by the system after voter verification in any way that could affect voter selections or the ability to perform an audit. The only modification to ballots is the possible use of an imprinter on VxCentralScan, which prints only an identifier along the outside margin of the ballot.
Because all voter selections are recorded on paper, voter-verified, and unmodified, the election results can always be re-tabulated or audited.
There are four code repositories relevant to the voting system:
The VotingWorks codebase is written in TypeScript and Rust, two widely used languages with well established coding conventions. We make use of automatic code linters to enforce these conventions. Details about our best practices and tooling used to enforce those best practices can be found here:
Through the above best practices, tooling used to enforce those best practices, and peer code review of every change, we guarantee that we meet the following requirements:
2.3: Voting system logic is clear, meaningful, and well-structured
2.4: Voting system structure is modular, scalable, and robust
2.5: The voting system supports system processes and data with integrity
2.6: The voting system handles errors robustly and gracefully recovers from failure
Subsequent articles will describe the particular software design of each application, but some software patterns are common across all applications and described here.
All VxSuite components require a USB drive at some point in their operation for configuration or for the import or export of results. The application is polling for attached USB drives multiple times per second. If a USB drive with a FAT32 partition is detected, the application will attempt to mount the USB drive to a known mount point. Once mounted, the USB drive will be available for use by the application.
The USB drive should be ejected before removing it. Most critical operations also make sure to sync the data to the USB drive before allowing the user to continue, however, so removing the USB drive without ejecting will normally not result in problems.
Only one USB drive can be used at a time and additional USB drives inserted after the first USB drive will be ignored.
All VxSuite components must generate documents for printing or export. VxAdmin and VxScan must generate tally and ballot count reports. All components must generate diagnostic readiness reports.
In order to do so, the applications have a headless browser (specifically Chromium) launched by the backend. Exported documents are all defined in terms of HTML (using React), so the headless browser is able to load the documents and render them as PDFs. The PDFs can then be sent to printer or saved to a USB drive.
The date and time is set on the machine in during initial configuration before the machine is sent to a customer. There is some amount of "clock drift" over time for all computers, however, so eventually the clocks may be wrong. This may cause problems with authentication due to mismatched timestamps and will cause reports to have incorrect timestamps.
All machines allow system administrators and election managers to edit the date, time, and time zone in order to address clock drift or, in rare cases, to set up machines for use in a part of the jurisdiction with different time settings.
Ballot interpretation begins with the front and back images of the ballot transmitted from the scanner. Once the images are available to the application, it starts by trying to interpreting the ballot as a .
Before trying to make sense of the ballot, the interpreter checks the images for vertical streaks. Vertical streaks likely indicate some sort of smudge or debris in the scanner that could interfere with the ballot image. The interpreter looks for columns of black without gaps, excluding the edges of the ballot which may be black simply from the way the scanner creates images.
If a streak is detected, the interpreter exits and surfaces the error to the application which will alert the user.
The interpreter then identifies the timing mark grid. It begins by finding all shapes in the image. It then narrows the list of shapes down to ones that look like timing marks and then further narrows the list down to timing mark shapes that fall along the edges of the image in a line.
In the example above, the interpreter found all the timing marks correctly. Sometimes, it may not. In that case, it infers any missing timing marks. Once it has all the timing mark borders, it identifies the corners in order to construct a complete timing mark grid. If at any point the interpreter does not have enough information to confidently find the complete mark grid or if the detected grid is too rotated or skewed, it causes the application to reject the ballot.
Next the interpreter will search the bottom left and top right corners of the image for a QR code. Since ballots have QR codes in the bottom left corner, the location of the QR code determines the correct orientation of the ballot and the interpreter can flip the images right-side up if necessary:
Now the interpreter inspects the locations of all ballot bubbles to see how filled they are. Note that bubbles are not necessarily aligned with timing marks because they can be defined in fractional grid coordinates. Each bubble is compared with a bubble template to distinguish voter marks from the bubble itself and is scored accordingly. In the images below, the orange score is the "match score", or the confidence that the bubble was found correctly. The greenish score is the "mark score", or the amount that the bubble's area is filled in. An empty bubble would receive a mark score of 0% or close to it–typically less than 1%.
The bubble mark scores are later compared against the definite mark threshold in the system settings and used to determine whether the voter made an indication that should be counted. The recommended default threshold is 7%. Setting too low of a threshold may result in stray marks or ballot folds to be considered as marks. Setting too high of a threshold may result in reasonable voter marks not being detected. While ballot instructions should recommend voters fully fill in the bubbles, at a threshold of 7% the system will detect most voter marks that pass through the bubble.
After bubbles are scored, the interpreter will then determine the location of the contest options relative to the grid. The write-in areas are defined in the election definition relative to the contest option areas. The write-in areas are then scored, similarly to the bubbles. This step only occurs in jurisdictions allowing unmarked (unbubbled) write-ins because otherwise a write-in is valid based only on the bubble. Write-in areas that cross the write-in area threshold set in the system settings will be shown in the write-in adjudication flow in VxAdmin. The system's default write-in area threshold is 5%.
After all bubbles and write-in areas are scored, interpretation is complete and the images are saved to disk. The votes are inferred from the bubbles based on the mark thresholds and eventually exported to cast vote records.
VxMark exposes various hardware interfaces for various modes of voting. The touchscreen displays the ballot and allows making selections with touch. It tilts forward and backwards for easier viewing and for storage. An accessible controller sits on the left side of the screen held in place with light magnetic force. Beneath the accessible controller is the headphone input and above the accessible controller is a recess for resting headphones. On the lower right corner, there is another input jack for a PAT (Personal Assistive Technology) device such as a sip-and-puff.
The right side of the machine is the paper path. Paper is inserted into the printer-scanner by feeding it forward on the front paper input. When the ballot is cast, it is ejected to the rear into the attached ballot box. In case of paper jams, the printer-scanner cover can lift to expose the printer-scanner. If the cover is opened while polls are opened without authentication, an alarm will be triggered through the onboard speaker.
The primary modification made by VotingWorks to the original Smartmatic hardware is adding a smart card reader for authentication. The smart card reader is positioned beneath the accessible controller:
Power is controlled by a button in the back left of the machine. When activated, an LED will illuminate the power button. Between the power button and the power port is an additional headphone input which is not used by VxMark.
VxMark is shipped and stored in large hardshell cases with custom foam cutouts. The first case, accented in blue, is for the BMD itself, its headphones, and its power supply. The second case, accented in yellow, is for the other peripherals - legs, power supply holder, privacy shield, and ballot box.
The BMD itself must be padded as shown below for transport and vibrational testing. Padding is used to protect the screen and hold it in place, to hold the accessible controller in place, to hold the printer-scanner cover in place, and to further secure the BMD within the enclosure.
The VSAP system provided by LA County is the primary component and the highest criticality component. The entire system runs on it. The embedded computer and the printer-scanner are both responsible for the printing of ballots and the interpretation of ballots. The various interaction interfaces - touchscreen, accessible controller, and PAT input - can all affect voter selections. VotingWorks and Los Angeles County have a robust partnership that includes the sale of the hardware itself, documentation transfer, and alignment on access control and quality assurance procedures.
The only other critical component, with medium criticality, is the HID smart card reader. As it is responsible for communicating with smart cards and facilitating authentication, it is a sensitive component.
VxScan is the system's precinct scanner into which voters cast their ballots directly.
VxScan includes an embedded A4 thermal roll printer which is used to print polls reports. The application communicates with the printer via a custom driver developed by VotingWorks. The application is regularly polling the printer for status, which is one of the following:
During a polls transition, a polls report is and gradually sent to the printer. Documents are A4 width but of indefinite length depending on the number of contests on the ballot styles at the precinct. If the printer encounters an error or runs out of paper in the middle of a print, the poll worker will be prompted to wait or to replace the thermal roll in order to continue printing. The previous document will reprint from the beginning. In most cases, poll workers do not have to install the thermal paper roll.
Election managers normally install the thermal paper rolls via a guided flow. They will be prompted to remove the platen, install the paper, and re-install the platen. Whenever an election manager installs a thermal paper roll, they are also prompted to print a test page. The main goal of the test print is to ensure that the election manager installed the roll in the correct orientation as it is one-sided and, if reversed, will not print anything.
The printer roll can be loaded at any time, including when VxScan is off. It only requires opening the access door which may be sealed.
User Manual Reference:
VxScan scans ballots with an embedded A4/Letter document scanner which produces double-sided ballot images. The application communicates with the scanner through a custom driver developed by VotingWorks. The application sends and receives events to and from the driver, managing its transitions between scanning states (waiting, accepting, etc.) and controlling when it will or will not accept ballots.
The embedded scanner includes a multi-sheet detector (MSD) which allows the application to reject cases of voters feeding in multiple ballots at a time. The multi-sheet detection must be calibrated at the beginning of an election based on the thickness of the ballot paper. The double sheet detection calibration flow is exposed in the election manager menu. The election manager can choose to disable double sheet detection, but it is enabled by default.
The scanner's cover can be opened for cleaning, during which scanning will be disabled and the application will show a warning on screen if the polls are open.
VxScan makes noises whenever a ballot is accepted or rejected. The ballot accepted sound is a pleasant chime and the ballot rejected sound is a jarring beep. Election managers can toggle sounds on or off.
VxScan is not fully configured until the election manager selects a precinct for the device. When polls are open, VxScan will only accept ballots for the configured precinct. If ballots for other precincts are cast, they will be rejected. The election manager may configure VxScan to "All Precincts" in which case ballots for all precincts will be accepted.
If the election definition only has one precinct, the precinct will be automatically selected.
Once polls are opened and ballots are cast, the precinct can no longer be changed. If polls are opened but ballots have not yet been cast, the precinct can still be changed but it will result in the polls resetting to closed. Resetting the polls to closed forces a poll worker to re-open the polls, which reprints the polls opened report with the new, correct precinct configuration.
Switching between ballot modes clears all scanned ballot data and resets the polls to closed. The election manager can switch from test ballot mode to official ballot mode at any time. When in official ballot mode after ballots have been scanned, the election manager can only switch back to test ballot mode if the CVRs have been synced to the USB drive.
VxScan can be unconfigured by an election manager or system administrator. If ballots have been scanned in official ballot mode, an election manager can only unconfigure the machine after scanned ballot data has synced to a USB drive. System administrators can unconfigure the machine at any time.
After configuration, polls are initially closed. When polls closed, ballots cannot be cast.
Poll workers open the polls to allow casting ballots. Once polls are opened, polls can only return to the initial polls closed state while remaining configured in two ways. First, switching from test ballot mode to official ballot mode will reset the polls. Second, in cases where the polls are open but no ballots have been cast, the precinct can still be changed which will also reset the polls to closed. Both of these actions can be performed by election managers but not poll workers. While polls are open, ballots can be inserted by voters, scanned, and tabulated.
Poll workers close the polls when ballots should no longer be cast. After polls have been closed, the scanner will not accept ballots and the polls cannot be opened again. Polls are closed until VxScan is unconfigured or switched from one ballot mode to another, with one exception discussed below.
VxScan also allows poll workers to pause voting a.k.a. suspend the polls. While voting is paused, the scanner will not accept ballots. Voting can be resumed, after which the polls are back in the standard polls opened state. Pausing voting might be used in an early voting model between voting days or, in the case of an emergency, to pause voting while the emergency is resolved. The poll worker may chose to close polls directly from voting paused instead of resuming voting.
If the polls have been closed, the only possible way for the polls to be re-opened is if a system administrator resets the polls to paused. Only the system administrator may do this - poll workers and election managers cannot - per the allowance in VVSG 2.0 1.1.7-E. Once polls have been reset to paused by the system administrator, voting may be resumed by a poll worker. The goal of this flow is to allow voting to continue after a poll worker has prematurely closed the polls.
Scanning can begin once VxScan is fully configured and polls are open. If any user authenticates, scanning will be disabled until they remove their card. If CVRs are not synced to the USB drive, or no USB drive is inserted, scanning will be disabled. Scanning will be enabled again once a USB drive with synced CVRs is detected. If the election manager has disabled continuous export then scanning will be enabled without a synced USB drive present.
If the precinctScanAdjudicationReasons
includes adjudicating unmarked write-ins, which are marks in the write-in space with the associated bubble unmarked, those unmarked write-ins will be included when determining whether a contest contains an overvote. At the same time, it will be considered an undervote. For example consider a vote for one contest. If the voter only fills in an unmarked write-in, it will be considered an undervote. If the voter fills in a bubble and a separate unmarked write-in, it will be considered an overvote when warning the voter. Warning in both these cases encourages the voter to clarify their ambiguous marks. When it votes are tallied, however, unmarked write-ins are always considered undervotes at VxScan.
Once the ballot is cast, whether immediately after interpretation or after the voter confirms to cast a ballot with errors, the image and interpretation are both saved to disk and exported to the inserted USB drive as a CDF CVR. The sheet count shown on screen will increment accordingly.
The voter interface can be tuned to be more accessible to different voters:
Text size can be adjusted to four different sizes (VVSG 2.0 7.1-G)
Contrast mode can be adjusted from the default medium contrast (VVSG 2.0 7.1-C) to a high-contrast white background, high contrast black background, or low contrast (VVSG 2.0 7.1-D)
Language can be adjusted to any language supported by the election package
After the voter casts their ballots, settings will automatically reset to the default (VVSG 2.0 7.1-A). There is also a voter option to reset settings (VVSG 2.0 7.1-B).
VxScan exports cast vote records to the inserted USB drive continuously, after every ballot is cast, in order to avoid a lengthy export at the end of the day. All cast vote records include ballot images and images of rejected ballots are also included. If there is no USB drive in VxScan, ballots cannot be cast. If the CVRs on the USB drive are not in sync with record of ballots on disk, VxScan requires a poll worker or election manager to sync the CVRs to the USB drive. This normally occurs when a USB drive is swapped out after ballots have already been scanned.
Continuous export can be disabled by an election manager if need be, for example if a USB drive turns out to be slow or no USB drive is available. If continuous export is disabled, VxScan can be used without a USB drive inserted.
CVRs can be exported directly from the election manager menu, in which case they export all at once.
On polls open, polls closed, voting paused, and voting resumed, VxScan prints a report via the thermal printer. The poll worker has the option to reprint additional report as many times as they need. The latest polls report can be cast as long as no ballots have since been cast. For example, the polls opened report can be printed as long as zero ballots have been cast. The polls closed report can be printed indefinitely, because no ballots can be cast after polls are closed. Reports will have both the timestamp of the polls transition and of the report printed, so reports printed at a later time are distinguishable.
For polls opened and polls closed reports, the vote interpretations of all ballots are tallied together. In the case of polls opened reports, the tallies should always be zero forming a zero report. It is impossible to have any ballots scanned already at the time of polls are opened, because the scanner is disabled until polls are opened. Pursuant to VVSG 2.0 1.1.3-B, however, in the impossible event that non-zero totals are detected on the machine when the poll worker attempts to open the polls, an error will be presented to the poll worker, and logged, and they will be unable to open the polls.
Tallies for the polls closed report are created by iterating through the data store's table of cast vote records and forming totals of votes for contest options, undervotes, overvotes, and total ballots cast. The process is the same as on VxAdmin but with far fewer steps because there are no write-in adjudication results to consider and no manual tallies. All marked write-ins are grouped as a generic "Write-In" count in reports. All unmarked write-ins are considered as undervotes.
For voting paused and voting resumed reports, only a total ballot count is included as opposed to vote tallies.
VxMark is the system's ballot marking device. It allows all voters to make selections in various interaction modes, print their ballot, verify their ballot, and cast their ballot independently. VxMark is not a tabulator, and the cast ballots must be later tabulated at VxScan or VxCentralScan.
VxMark is configured with a signed exported from VxAdmin. The election definition defines the ballot styles that will be available to voters. The election definition also includes the translations defined for text on the ballot, while the file contains the translations for other text shown on screen. The election package's are played for the voter in audio-mode.
User Manual Reference:
VxMark is not fully configured until the election manager selects a precinct for the device. When polls are open, VxMark will only allow marking ballots in the ballot styles for the configured precinct. The election manager may configure VxMark to "All Precincts" in which case all ballot styles are available.
If the election definition only has one precinct, the precinct will be automatically selected.
The precinct selection can always be changed on VxMark by an election manager, even while polls are opened.
After initial configuration, VxMark is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, the ballots printed at VxMark will be official ballots. In test ballot mode, the ballots printed at VxMark will be test ballots.
Switching between ballot modes clears the printed ballot count and resets the polls to closed. The election manager can switch from test ballot mode to official ballot mode at any time.
VxMark can be unconfigured by an election manager or system administrator.
After configuration, polls are initially closed. When polls closed, voting is not allowed on VxMark.
Poll workers open the polls to allow voting. Once polls are opened, polls can only return to the initial polls closed state while remaining configured by switching between test and official ballot mode.
Poll workers close the polls when voting should no longer be allowed. Polls are closed until VxMark is unconfigured or switched from one ballot mode to another, with one exception discussed below.
VxMark also allows poll workers to pause voting a.k.a. suspend the polls. While voting is paused, no voting sessions can be started. Voting can be resumed, after which the polls are back in the standard polls opened state. Pausing voting might be used in an early voting model between voting days or, in the case of an emergency, to pause voting while the emergency is resolved. The poll worker may chose to close polls directly from voting paused instead of resuming voting.
If the polls have been closed, the only possible way for the polls to be re-opened is if a system administrator resets the polls to paused. Only the system administrator may do this - poll workers and election managers cannot - per the allowance in VVSG 2.0 1.1.7-E. Once polls have been reset to paused by the system administrator, voting may be resumed by a poll worker. The goal of this flow is to allow voting to continue after a poll worker has prematurely closed the polls.
When polls are opened, poll workers can enable voting sessions on behalf of voters. The poll worker selects one of the available ballot styles and loads a blank piece of thermal paper into the front input tray.
The voter navigates through the contests on their ballot style sequentially, with controls to advance to the next contest or go back to the previous contest. The contest information presented to the voter includes the contest title, the contest district, the number of selections allowed, the number of selections remaining, the contest options, the candidates' parties if applicable, and the descriptions of any ballot measures (VVSG 2.0 7.3-C).
Voters may leave contests blank or undervoted but are prevented from overvoting contests. If the voter attempts to mark an overvote, they will be presented a warning and instructed to deselect another selection if they want to make the new selection (VVSG 2.0 7.3-H). Previous selections are never automatically deselected.
If the contest allows write-ins, they may input a write-in name via a virtual keyboard.
After working through the entire ballot, the voter will then review all their selections. Any undervotes will be flagged for the voter (VVSG 2.0 7.3-I) but may be ignored. If the voter does want to make any changes, they can navigate back to any contest, make changes, and return to the review stage (VVSG 2.0 7.3-F). Once the voter is satisfied with their selections, they may print their ballot.
The thermal printer prints a ballot, presents it to the voter, and prompts them to once again review their selections. This final review differs from the initial review in two ways. First, the printed ballot is being physically presented to the user which creates a voter-verified paper trail. Second, the selections being reviewed are a result of the actual interpretation of the ballot rather than simply the selections made by the voter. As a result, even when a voter is unable to verify their printed paper ballot visually they are still able to verify the ballot through another interaction mode. Once the voter is satisfied with their second round of review, they may cast their ballot which is ejected into the attached ballot box.
If the voter finds a problem in their ballot during the final review stage, they must spoil the ballot. They are prompted to get help from a poll worker who can help them spoil their ballot and load a new, blank sheet. Once the blank sheet is loaded, the voter returns to the initial review stage from which they can edit selections before reprinting, reviewing, and casting their ballot.
While the paper ballot is being presented to the voter, they are supposed to leave it in the scanner so it can be ejected into the ballot box when they cast their ballot. Many voters will naturally remove the ballot from the scanner, however, and cannot cast their ballot until they re-insert the ballot. When they do insert their ballot, it is scanned again and they are returned to the final review stage.
It's possible that a voter removes their ballot and does not re-insert it before the voting session times out. In this case, it's possible for a poll worker to initialize a session by re-inserting an already printed ballot rather than by selecting a ballot style. The already printed ballot is scanned and the voter is dropped directly on the final review screen.
If a re-inserted ballot is somehow not compatible with the machine - wrong election, wrong precinct or wrong ballot mode - the user is alerted and the ballot is rejected out the front.
If a poll worker card is inserted during a voting session the poll worker can deactivate the current session and spoil any current ballot.
From the poll worker screen a poll worker may choose "Insert Printed Ballot" in order to scan a previously printed ballot and start a new voter session at the "Review Ballot" stage of the flow diagram above.
VxMark supports voting sessions in various display formats and interaction modes.
The voting session begins in visual mode with the following default settings:
Text Size - Medium, which corresponds to between 14pt - 16pt, meeting the default text size requirement specified in VVSG 2.0 7.1-G.
Contrast - Medium, which is at least a 10:1 contrast for all informational elements, meeting the default contrast requirement specified in VVSG 2.0 7.1-C
The voter can update the Text Size to Small, Medium, Large, or Extra-Large, which map to the four discrete text sizes defined in VVSG 2.0 7.1-G. Changing the text size changes the size of all informational elements including buttons, icons, and layout (VVSG 2.0 7.1-H) because all such elements are sized relative to the base font size. The font is always sans-serif (VVSG 2.0 7.1-J).
If there's too much content on a page to fit all on screen at once, which happens most commonly in large or extra-large text size, the interface introduces a large "More" button to indicate there are more contest option to scroll through. The interface never lays out content in a way which requires horizontal scrolling.
The voter can update the Contrast from medium contrast to low contrast, high contrast with black background, or high contrast with white background corresponding to the contrast options specified in VVSG 2.0 7.1-D. The contrast changes apply to all elements on screen.
In addition to text, color and icons are used on screen to guide voters. In conformance with color conventions (VVSG 2.0 7.1-E), red indicates danger, yellow indicates warning, and green indicates success. For example, choosing to spoil one's ballot is a red button. Purple is generally used as the primary color to indicate the recommended next step. In high contrast modes, the interface is entirely black and white to support the 20:1 contrast ratios. Icons are used on buttons to provide an additional visual cue, but are always paired with text (VVSG 2.0 7.3-L).
Ending a voting session will automatically reset all display settings to defaults (VVSG 2.0 7.1-A). The voter can change or reset the display settings to defaults at any time (VVSG 2.0 7.1-B).
In visual mode, when a voter makes a selection it is indicated in three ways:
Highlighting the selection in a contrasting color
Updating the icon from an unchecked to a checked box
Decrementing the number of remaining votes allowed shown on screen
Once a voter has used all their votes in a race, the progress button at the bottom of the screen to advance to the next race is also highlighted to encourage the voter to proceed.
Voters usually choose to use the touchscreen to vote. The voter taps buttons to move between contests and through the stages of the voting flow. The voter taps list items on each contest page in order to make selections. Touch areas never overlap and are sized to meet minimums described in VVSG 2.0 7.2-I. Touch areas require that the user's touch begins and ends within the touch area to activate, meaning that dragging a finger across a touch area will not activate the touch area, in order to avoid accidental activation (VVSG 2.0 7.2-H).
When there's more content on a page than can fit on one screen, the voter can scroll through the screen in one of two ways. First, they can tap the "More" button which acts as both the visual indicator that there are more contest options or contests. Second, they can use a swiping motion on the screen to move up or down. Swiping to see more contest options or contests is VxMark's only touch screen gesture. It cannot be used horizontally to navigate between contests or pages and (VVSG 2.0 7.2-E).
VxMark has a permanently attached accessible controller that can be used to navigate the ballot instead of using the touchscreen directly. The left and right buttons are used to navigate between contests and other screens while the up and down buttons are used to navigate between contest options or contests within each screen. The controller has a help button which will navigate to a help interface that explains the function of each button on the controller when pressed.
The currently focused element on screen is highlighted in visual mode or read aloud in audio mode. When navigating through selections on a screen large enough to be scrollable, the screen will automatically scroll to keep the focused element in view.
The accessible controller is integrated with the application via a hardware daemon that is always running. The daemon is continuously listening for input events from the controller. Each event is converted into virtual keyboard presses which are then handled by the frontend rendering agent just as a web browser might handle arrow key inputs.
VxMark has a PAT (personal assistive technology) input port into which a voter can plug in their own two-switch adaptive input such as a sip-and-puff device. When a PAT input is attached during a voting session, VxMark will enter a calibration flow where the voter will map their two inputs to "move" and "select." Different voters can calibrate their sip & puff devices differently such that sip is "move" for one and "select" for another.
Once calibrated, the voter can use the two inputs to navigate through the ballot. The "move" input advance the focus on screen to the next element and the "select" input is the equivalent of a tap in touch interaction mode. Just as with the accessible controller, the currently focused element on screen is highlighted in visual mode or read aloud in audio mode.
The PAT input is integrated with the application via a hardware daemon that is always running. The daemon is continuously listening for input events from an attached device. Each event is converted into virtual keyboard presses which are then handled by the frontend rendering agent just as a web browser might handle Tab
and Enter
.
As an alternative to the visual formats, the voter can listen to their ballot in an audio format. VxMark includes a headphone port and headphones which, when attached, will automatically play audio to guide the voter's ballot navigation. The audio includes information about the election, contests, and contest options equivalent to the information displayed on screen in visual mode. The audio also includes prompts and explanations for how to navigate the ballot that are equivalent to the cues in layout and highlighting on screen in visual mode. These instructions include but are not limited to:
how to start voting
how to make selections in a contest
how to navigate the review screens
how to use the accessible controller
The voter can adjust volume up and down or speech rate up and down with buttons on the accessible controller. Volume and rate defaults and options are calibrated according to VVSG 2.0 7.1-K. The voter can also pause and resume audio with a button on the accessible controller.
Blind or visually impaired voters can use the audio track to review their printed ballot. The printed ballot is scanned and interpreted on its way out of the printer, and the resulting interpretation is the basis for the audio played in the second review state. As a result, blind or visually impaired voters are able to verify their paper ballots just as seeing voters are able to verify their paper ballots.
VxMark supports switching the language for the current voting session to any language supported in the current election package. When the language is changed, all text on the ballot, all text shown on screen, and text read in audio mode to guide the voter will switch to the new language. The language can be changed at any time during a voting session. The language selection resets automatically after each voting session or can be reset by the voter at any time..
If a language other than English is set when printing the ballot, the ballot will show all information in both the current language - for the purpose of the voter's review - and in English - for ease of adjudication and audits.
VxMark's printer and scanner are covered by the printer cover which can be opened at any time in order to clear a paper jam or clean the scanner. In order to prevent unauthorized access, pursuant to VVSG 2.0 12.1-B, VxMark produces a jarring, audible alarm if the printer cover is opened while polls are opened. The alarm should alert a poll worker that something is wrong. A poll worker then inserts their card, which silences the alarm, and follows on screen instructions to close the printer cover.
Because authentication is required for the poll worker to open the printer cover without triggering an alarm, poll workers are instructed on screen to authenticate when clearing a paper jam. When polls are closed, the alarm is not active, so cleaning and setup can take place without triggering the alarm.
VxAdmin supports a variety of results exports.
contain contest results for the full election or a specific subset of ballots. They can be printed directly from VxAdmin, exported as PDFs, or exported in . In addition, full election results can be exported as an JSON file.
include only ballot counts, without contest results. They can also be printed directly from VxAdmin, exported as PDFs, or exported in .
The acts as a summary of all write-in adjudication activity or as a "scatter report." The tally reports consolidates write-in candidates whose vote totals are too small to affect the contest outcomes. The counts for those write-in candidates are available in the write-in adjudication report. The write-in adjudication report may be printed directly from VxAdmin or exported as a PDF.
For all VxAdmin reports, the report is either "Official" or "Unofficial." If the report is exported before the results are marked as official in the application, the results are "Unofficial." If the report is exported after the results are marked as official in the application, the results are "Official." All visual reports have "Official" or "Unofficial" included in the title and all exported files will have "official" or "unofficial" included in the filename.
The Election Results Reporting CDF requires that identifiers be in , so all identifiers from the election definition are re-formatted to be compliant. For example, "Sample County" becomes "vx_sample-county".
kiosk-browser is a web browser restricted to rendering a single full-screen application. The code can be found in the . It is a thin application which uses as its rendering engine. The browser communicates with the frontend server which serves HTML, JavaScript, and assets. The browser also communicates with the backend server which serves application data. Electron enables the browser to access certain operating system APIs - such as open file dialogs - that a lone renderer would not have access to. The browser is launched at startup, with limited privileges, and cannot be exited. Everything a standard (non-vendor) user sees or does is mediated through kiosk-browser.
The frontend is a application served from a server. All code for the application frontends are in the under apps/[app-name]/frontend
.
The application backend is a separate server which acts as the core of the entire application in that it manages all persistent data and communication with peripherals. All code for the application backends are in the under apps/[app-name]/backend
. Most code is written in TypeScript but some performance sensitive code, such as interpretation and background daemons, are written in and executed as binaries at runtime.
All application data that persists across restarts is stored or tracked in a database. Each machine has a single database that the application backend accesses to update or retrieve data such as election configuration, cast vote record data, diagnostic data, etc. Logging data is a notable exception that is stored outside of the application databases.
The voting system achieves software independence through the use of independent voter-verifiable paper records. All ballots are voter-verified paper ballots, either or .
— Core application code
— Generic Electron-based kiosk-mode browser
— Links compatible versions of vxsuite and kiosk-browser, and includes the scripts necessary to create a production machine
— Our framework for building VxSuite and managing its dependencies, across versions and environments
We take care to ensure that we're pulling authentic/correct versions of dependencies, by verifying against known hashes, checksums, or digital signatures. The details of this are covered in .
We also require peer code review of every change (), and for larger changes and features, we hold architecture discussions as a team to land on the best possible solutions given the constraints.
Our practices around testing are covered under .
The VotingWorks codebase uses database transactions to ensure that only complete and consistent (and not partial) updates are persisted. For data synced across a machine's internal drive and a connected USB drive, namely CVRs, we detect when data has fallen out of sync after a failure using the Merkle tree hash of the data () and re-sync data as needed.
Much of 2.5 is additionally covered under .
User Manual Reference:
The QR code includes ballot metadata - precinct, ballot style, election hash, ballot mode - but no vote information (see ). Up until now, the two sides of a ballot have been interpreted in parallel. At this point, the QR code metadata on the front and back are compared to ensure that they match to form a valid ballot. The ballot information from the QR code indicates which ballot layout from the election definition that the ballot conforms to, including the position of all the bubbles, contests, and write-in areas.
If interpretation didn't work, one possibility is that the ballot is actually a , so the interpreter will then attempt to interpret the ballot as a machine marked ballot. Since votes are encoded into the QR code, the interpreter only has to find the QR code. It searches the entire document for a QR code. By searching the top and bottom half separately, it can infer the orientation of the ballot because machine marked ballots have QR codes in the top right.
Assembly instructions are covered in the user manual under . In short, the legs are unfolded and the power block holder is set on the legs with the power block inside. The BMD then fits onto the legs with grooves on its underside.
The vast majority of the VxMark hardware is the Ballot Marking Device (Model 150) developed by Los Angeles County, manufactured by Smartmatic, and purchased through Los Angeles County. In addition, VotingWorks includes a few peripherals or COTS components added through modification. Documentation for these components can be found in or in the separately provided Los Angeles County documentation.
User Manual Reference:
VxScan is configured with a signed exported from VxAdmin. The election definition includes the ballot layouts necessary for interpreting ballots and the system settings which indicate what type of ballot issues (e.g. overvotes) require adjudication.
User Manual Reference:
After initial configuration, VxScan is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, only official ballots can be scanned and exported CVRs will be official ballot CVRs. In test ballot mode, only test ballots can be scanned and exported CVRs will be test ballot CVRs. If allowOfficialBallotsInTestMode
is set in the , official ballots will be allowed in test mode but exported CVRs will still be test CVRs.
User Manual Reference: , ,
While scanning is enabled, the scanner will grab and scan paper as soon as it is detected. The scanned image will be while the ballot is still being held by the scanner. If the ballot is interpreted successfully and contains no errors, it will be ejected into the ballot box with a chime and the screen will inform the voter that their ballot has been cast.
If the ballot cannot be interpreted, it will be rejected toward the voter. Interpretation can fail if the ballot is not a valid or if the ballot enters the scanner at too much of an angle, although the paper path normally prevents significant skew. If the ballot is interpretable but is invalid due to a mismatching election, precinct, or ballot mode, it will also be rejected toward the voter.
If the ballot is interpreted and valid, but contains some voter error, the scanner will hold the ballot out of view while the errors are presented to the voter on screen. The types of errors that are flagged are determined by the precinctScanAdjudicationReasons
set in the . Possible options are overvotes, undervotes, and blank ballots. In the case of overvotes or undervotes, the specific list of affected contests will be listed. The voter has the option to return the ballot to themselves or to cast it despite warnings. If there's an overvote and disallowCastingOvervotes
is set in the system settings, however, the ballot can only be returned.
User Manual Reference:
The election package's file specifies the translations that will be used to replace all on screen voter messages when the language is switched.
User Manual Reference:
For details about the format of the polls reports, see .
User Manual Reference:
User Manual Reference:
User Manual Reference:
Precinct
The name of the precinct
Ballot Style
The internal identifier of the ballot style
Party
The short name of the party, e.g. "Democrat". Included by default if the ballot style is included, in a primary
Voting Method
"Precinct", "Absentee", or "Provisional"
Scanner ID
The serial number of the scanner. Included by default if the batch is included
Batch
The label for the batch, or "Manual Tallies" for manually entered data
ElectionReport.Format
Fixed to "summary-contest"
ElectionReport.IsTest
true
or false
depending on whether VxAdmin was in test ballot mode
ElectionReport.SequenceStart
Fixed to 1
ElectionReport.SequenceEnd
Fixed to 1
ElectionReport.GeneratedDate
The generated timestamp of the report
ElectionReport.Issuer
The county name
ElectionReport.IssuerAbbreviation
The county identifier formatted as an NCName ID
ElectionReport.VendorApplicationId
"VxAdmin, version <code version>" where code version is the software version of the system e.g. "v4"
ElectionReport.Status
If the election has been marked as official in VxAdmin, "certified", otherwise "unofficial-complete"
Party.@id
The party identifier
Party.Name
The short name of the party e.g. "Libertarian"
Party.Abbreviation
The party abbreviation e.g. "L"
Election.StartDate
The date of the election
Election.EndDate
The date of the election
Election.Name
The title of the election
Election.ElectionScopeId
The state name formatted as an NCName ID
Election.Type
Either "general" or "primary"
BallotCounts.Type
Fixed to "total"
BallotCounts.GpUnitId
The county identifier formatted as an NCName ID
BallotCounts.BallotsCast
The total ballot count for the election
Candidate.@id
The candidate identifier formatted as an NCName ID
Candidate.PartyId
The candidate's party identifier formatted as an NCName ID
Candidate.BallotName
The candidate's name as it appears on the ballot in English
Contest.@id
The contest identifier formatted as an NCName ID
Contest.Name
The contest title
Contest.ElectionDistrictId
The district identifier of the contest's associated district formatted as an NCName ID
ContestSelection.@id
The option identifier formatted as an NCName ID
BallotMeasureSelection.Selection
The option label as it appears on the ballot in English
CandidateSelection.IsWriteIn
true
or false
depending on whether the candidate is a write-in candidate
VoteCounts.Count
The vote count for the specific contest selection
VoteCounts.Type
Fixed to "total"
VoteCounts.GpUnitId
The district identifier of the contest's associated district formatted as an NCName ID
OtherCounts.Overvotes
The overvote count
OtherCounts.Undervotes
The undervote count
OtherCounts.GpUnitId
The district identifier of the contest's associated district formatted as an NCName ID
GpUnit.@id
The county, state, or district identifier formatted as an NCName ID
GpUnit.Name
The county, state, or district name
GpUnit.Type
"state", "county", or for districts, "other"
GpUnit.ComposingGpUnitIds
State: only the county identifier
County: all district identifiers
All
Card reader
VxScan
Scanner
VotingWorks
VxScan
Printer
VotingWorks
VxMark
Printer-scanner
VotingWorks
VxMark
Accessible controller
VotingWorks
VxMark
PAT (sip and puff)
VotingWorks
VxAdmin
Printer
VxCentralScan
Scanner
Debian
12.2.0
Additional Debian Packages
Node.js
20.16.0
pnpm
8.15.5
Application Node Packages
See the relevant lock file
Rust
1.81
Rust Packages
See the relevant lock file
yarn
1.22.22
Electron
17.4.1
Chromium
98.0.4758.141
Kiosk Browser Node Packages
See the relevant lock file
Smartmatic
Ballot Marking Device
VSAP-150
High
APC
Uninterruptible Power Supply
BN1500M2
Low
HID
Smart Card Reader
R31210375-1
Medium
LORELEI
Headphones
X6
Low
Williams Audio Visual
T-Coil Neckloop
NKL-001
Low
VxCentralScan is the system's batch scanner which enable election managers to efficiently scan large batches of ballots.
VxCentralScan is configured with a signed election package exported from VxAdmin. The election definition includes the ballot layouts necessary for interpreting ballots and the system settings which indicate what type of ballot issues (e.g. overvotes) require adjudication. After the election package is loaded by an authenticated election manager, no further configuration is required.
User Manual Reference: Configure VxCentralScan
After initial configuration, VxCentralScan is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, only official ballots can be scanned and exported CVRs will be official ballot CVRs. In test ballot mode, only test ballots can be scanned and exported CVRs will be test ballot CVRs. If allowOfficialBallotsInTestMode
is set in the system settings, official ballots will be allowed in test mode but exported CVRs will still be test CVRs.
Switching between ballot modes clears all scanned ballot data. The election manager can switch from test ballot mode to official ballot mode at any time. When in official ballot mode after ballots have been scanned, the election manager can only switch back to test ballot mode if the scanned ballot data has been backed up.
VxCentralScan can be unconfigured by an election manager or system administrator. If ballots have been scanned in official ballot mode, an election manager can only unconfigure the machine after scanned ballot data has been backed up. System administrators can unconfigure the machine at any time.
VxCentralScan is compatible with the Ricoh fi-8170 and Ricoh fi-7600 production scanners. Once either scanner is detected, the user may begin scanning batches. The scanners are controlled via commands provided by the Debian sane
package ("Scanner Access Now Easy") which creates a uniform API for most commercial scanners. As a result, no scanner-specific drivers are required.
When the user triggers a batch scan, the scanner will start a batch and begin scanning sheets one a time. The scanner will pull the paper through and transfer a scanned image to the application which will then interpret the ballot according to the current election definition. If any issues are found with the ballot - either the ballot is incompatible or the marks trigger some adjudication reason - scanning will pause and the election manager will be prompted to remove or tabulate the ballot. When pausing for adjudication, the batch is not yet ended. Once the election manager addresses the ballot, scanning will continue until there are no more ballots in the hopper to be scanned. At that point, the batch will end.
The start time, end time, size, and index of all batches is tracked and displayed to the election manager. If a mistake was made in organizing batches or adjudicating a ballot, election managers can delete any individual batch or delete all batches.
User Manual Reference: #scan-ballot-batches
Both Ricoh scanners can be used with an optional imprinter - the fi-819PRB for the fi-8170 and the fi-760PRB for the fi-7600. As the ballot exits the scanner, the imprinter prints an identifier on the side margin of the ballot. The identifier is the batch's UUID suffixed with the index of the sheet in the batch e.g. 378f6a69-62d3-4184-a1a7-3a5d90083e21_0000
for the first sheet in a batch. The identifier will appear in the CVR as the BallotAuditId
. Imprinting allows later reconciling CVRs to ballots such as in ballot comparison audits.
The v4 UUID (universally unique identifier) for each batch is generated when the batch is first created. It is generated with the node package uuid
which uses the system's underlying FIPS-complaint OpenSSL implementation to generated random bytes.
Batch scanning pauses whenever a ballot is not counted for any reason. Sometimes the ballot was not interpreted or cannot be accepted, in which case the ballot must be removed:
Vertical Streaks Detected - the scanner may require cleaning
Wrong Ballot Mode - test ballots in official ballot mode or official ballots in test ballot mode
Wrong Election - the hash on the ballot does not match the currently configured election
Unreadable - the ballot image could not be successfully interpreted, possibly because it is not a valid ballot or because the image skew was too great
In other cases, the ballot requires adjudication. The adjudication reasons for VxCentralScan are set in the system settings as centralScanAdjudicationReasons
and map to the following:
Overvote - at least one contest is overvoted
Undervote - at least one contest is undervoted
Blank - all contests are blank
In these cases, the affected contests will be highlighted on screen to the election manager and they will have the option to remove or tabulate the ballot.
User Manual Reference: #adjudicate-ballots
CVRs must be exported onto a USB drive and taken to VxAdmin for aggregation and reporting. The election managers has options to either save CVRs or save a backup. When saving CVRs, ballot images are only included for ballots with write-ins and rejected ballots are not included. A backup is simply a CVR export with images for all ballots and images for rejected ballots.
After ballots are interpreted, their images are saved to disk and their interpretation is stored in VxCentralScan's data store. On export, all CVRs are pulled from the data store, converted to the CVR CDF, and written to the USB drive.
User Manual Reference: #saving-cast-vote-records-cvrs
Ready
Platen is attached and paper is detected
Application may print normally
No Paper
Platen is attached but no paper is detected
Printing disabled. A warning will be shown on poll worker screens.
Cover Open
Platen is not attached
Printing disabled. If the polls are open, a warning will be shown.
Error
Most likely the printhead has overheated, but other hardware errors are possible. Details available in diagnostics interface.
Printing disabled. Poll workers will not be able to operate the polls, but election managers and system administrators can still authenticate for diagnostics.
All VxSuite components have a diagnostics interface accessible to system administrators and election managers that allows a user to monitor or test key components. Diagnostic information is shown to the user and can be exported as a PDF readiness report.
When a test is performed, the system logs the result and creates a diagnostic record which includes the outcome of the diagnostic, pass or fail. The outcome and date of the most recent diagnostic is displayed on the readiness report. One possible use case of the readiness report is to run all diagnostics before an election and then produce a readiness report that confirms all tests passed.
Retrieves the current amount of disk space used and disk space available for the application. The displayed total disk space will not be as large as the actual disk because some space is reserved for the system. The disk space usage will not always return to 0% after clearing election data because the database may not have liberated that disk space back to the operating system, but the space will be reused once more election data is loaded.
For components with internal batteries - VxAdmin and VxCentralScan - the operating system is polled for battery status. The application will report the current charge level and whether or not the battery is currently charging.
If there is an election configured on the machine, it will display the election title and hash.
For precinct equipment, the list of ballot styles will include only those appropriate for the current precinct configuration. For central equipment, the list of ballot styles will be all ballot styles in the election. The languages for each ballot style are also enumerated.
For precinct equipment - VxScan and VxMark - the currently configured precinct will be shown, if any.
For scanners - VxScan and VxCentralScan - the currently configured mark and write-in area thresholds will be shown. The thresholds reflect what was set in the system settings.
The toner level and any alerts from the printer are displayed, such as sleep mode, paper jams, or hardware malfunctions. The user may perform a test print, which will send a mock report to the printer. The user inspects the printed document and confirms whether the test print was successful or failed.
User Manual Reference: VxAdmin Diagnostics
The user may perform a test scan, which requires that a blank white sheet of paper be scanned. The scanned image is broken up into small cells and each cell is checked for the percent of black pixels after binarization. If that percent is more than slightly over 0%, that cell is flagged and the entire diagnostic fails. The goal of the diagnostic is catch any defects in the scanned images, such as streaking produced by a dirty scanner.
User Manual Reference: VxCentralScan Diagnostics
The user may perform a test scan, which requires that a blank white sheet of paper be scanned. The scanned image is broken up into small cells and each cell is checked for the percent of black pixels after binarization. If that percent is more than slightly over 0%, that cell is flagged and the entire diagnostic fails. The goal of the diagnostic is catch any defects in the scanned images, such as streaking produced by a dirty scanner.
The test scan process is identical to that for VxCentralScan, and the images above apply.
The user may test the printer by printing a test page. After the print, the user must indicate whether the page printed successfully or not. The diagnostic available in the diagnostics interface is identical to that which election managers are encouraged to run after loading paper, and the outcome is recorded in either case.
The diagnostics page will also display details about any printer errors if the printer is in an error state.
The user may test the speaker by triggering the chime sound and confirming whether they heard the chime or not.
User Manual Reference: VxScan Diagnostics
The user may perform a test of the printer-scanner which mocks the ballot flow during a voting session:
User loads thermal paper
Mock ballot is printed onto paper
Mock ballot is scanned and presented in the front input tray
Mock ballot is ejected into the ballot box
A successful test indicates that the printer and scanner can properly produce and handle ballots during a voting session.
The user may perform a test of the accessible controller which validates that each button on the controller is producing the expected signal. The flow guides the user through pressing each button.
The user may perform a test of the PAT input, which is simply confirms that a PAT device can be successfully calibrated as it would be during a voting session.
The user may perform a test of the front headphone input by connecting headphones and triggering a chime. The user must indicate whether they heard the chime or not, corresponding to a pass or fail respectively.
User Manual Reference: VxMark Diagnostics
VxAdmin acts as the election setup hub at the beginning of the election and the results aggregation and reporting hub at the end of an election (and also at the end of testing).
Only a system administrator can authenticate onto an unconfigured VxAdmin and configure it with an election package from an external system. The election package must be loaded via a USB drive. The election package must be a valid .zip
election package. If the election package zip file, election definition file, system settings file, or metadata file are not valid, VxAdmin will surface an error to the user.
It's also possible to configure VxAdmin directly from a .json
election definition file rather than a full election package. The system will use default system settings and include no additional translations for application strings. Uploading a .json
file directly is not recommended for general use because it means you are unable to customize system settings like ballot adjudication reasons. The option exists for development purposes. VxMark, VxScan, and VxCentralScan cannot be configured from an election definition alone and require a signed election package.
Once VxAdmin is configured, system administrators and election managers can export signed election packages. The exported election package is the same as the imported election package but is accompanied by a digital signature, which ensures that the election package was validated by a certified VxAdmin. The election packages loaded into VxMark, VxScan, and VxCentralScan must be signed and unsigned election packages will be rejected.
User Manual References: &
Smart cards are used for two-factor authentication on all machines in the system. They can only be programmed at VxAdmin with system administrator privileges.
Programming, like authentication, takes place via the laptop's built-in USB card reader. Once a card is inserted, the application is able to detect the card and read and write data by issuing APDUs (application protocol data units) which are the standard form of communication between smart card readers and smart cards.
For extensive details on the authentication scheme, see the access control documentation.
User Manual Reference: Smart Cards and User Roles
VxSuite components require USB drives to be formatted with a FAT32 partition. The majority of USB drives are sold pre-formatted as FAT32, but some come in other formats. If an improperly formatted USB drive is inserted into a VxSuite component, it will be treated as if there is no USB drive.
VxAdmin includes a utility to format USB drives to be compatible with the system. The utility is available only to system administrators. It will rewrite the partition table on the drive to include a single partition with a FAT32 formatted filesystem that takes up all available space on the drive. The reformatting clears the USB drive and is thus a destructive action. If a USB drive is already correctly formatted, the feature can be used to clear its data. VxAdmin applies a new label to the reformatted USB drive in the form of VxUSB-00000, where the 0's can be any random alphanumeric characters.
Improperly formatted USB drives can only be detected and reformatted if there is some partition already existing, so a USB drive without any partitions cannot be reformatted using VxAdmin.
User Manual Reference: USB Formatting
The core post-election (and pre-election testing) function of VxAdmin is loading, managing, and tallying cast vote records (CVRs).
CVRs must be loaded from a USB drive. CVRs are exported from VxScan or VxCentralScan and are accompanied by a digital signature. CVRs without a digital signature cannot be loaded. CVR exports with digital signatures that do not match the content of the CVR exports cannot be loaded in order to prevent tampering.
The CVRs from the scanners are saved to specific directory structure on the USB drive, but exports can be loaded from anywhere on a USB drive's filesystem. When selecting an export manually, the export's metadata.json
file must be selected by the user.
When loading a full CVR export, each CVR is loaded into VxAdmin's backend store as one cvrs
record. The CVR record includes a data blob representing the interpreted votes and a series of metadata fields: ballot style, voting method (absentee vs. precinct), batch, scanner, precinct, sheet number within a multi-sheet ballot, and flags for adjudication reasons such as overvotes, undervotes, write-ins, or fully blank ballots. The metadata fields are used later on for filtering or aggregating tallies or ballot counts into groups.
Each write-in on a CVR will map to a write-ins
record, whether it is an unmarked write-in or a proper write-in. The ballot images are also each saved as database records. The write-in record links the write-in to its respective CVR, to the ballot images, and eventually to its adjudication result. The write-in adjudication interface essentially iterates through all write-ins
records on a per contest basis.
If an error is found when loading any single CVR in a CVR export, the entire export is rejected and a message is surfaced to the user. CVRs can be rejected for a variety of reasons: authentication failed; a file is incorrectly formatted; a CVR is not for a currently valid election, precinct, ballot style, or contest; a CVR with an identical ID has been loaded with different data. In everyday use of the system, all of these errors are either rare or impossible because VxAdmin will not allow loading CVR files from elections with mismatched metadata.
VxAdmin allows loading CVR exports that have already been partially loaded. For example, imagine that VxCentralScan exports CVRs after scanning 5 ballots and then again after scanning 10 ballots. If we first load the 5 CVR export and then the 10 CVR export, the 10 CVR export will successfully load but will ignore the CVRs that have already been imported.
User Manual Reference: Tally Results
VxAdmin is always in one of three ballot modes:
Unlocked Ballot Mode - no CVRs have been loaded
Test Ballot Mode - test CVRs have been loaded
Official Ballot Mode - official CVRs have been loaded
On VxAdmin, the ballot mode is determined by the ballot mode of the imported CVRs. VxAdmin differs in that respect from VxMark, VxScan, and VxCentralScan, where the ballot mode is set directly by the election manager.
Once VxAdmin is in test ballot mode, only test CVRs can be subsequently loaded. Similarly once VxAdmin is in official ballot mode, only official CVRs can be subsequently loaded.
CVRs can be removed by the user before results are marked as official or can be removed by fully unconfiguring VxAdmin. All CVRs are removed at once. The CVR data in the database along with all its dependent data - write-ins, ballot images, and adjudications - are permanently and irrecoverably deleted from the data store.
When ballots with write-ins are scanned at VxScan or VxCentralScan, they have not yet been adjudicated. The polls closed report at VxScan treats all write-ins simply as a generic "Write-In" and all unmarked write-ins as undervotes.
VxAdmin allows election managers to perform on-screen write-in adjudication. Each contest is adjudicated individually. The election manager can work through the queue of write-ins for that contest. The queue is ordered by least to most recently loaded into VxAdmin. Because multiple write-ins for a single CVR are loaded together, write-ins that appear on the same ballot sheet will appear next to each other in the queue.
The side of the ballot that the write-in appears on is rendered to the user, with options to zoom out and back in again. In the zoomed in view, the write-in area in question is highlighted. The location of the highlight is taken from the interpreted ballot layout, which is included in the cast vote record and loaded into VxAdmin alongside the ballot image.
The user can adjudicate the write-in in one of three ways:
Official Candidate: the list of official candidates for the given contest will be displayed and the write-in can be assigned to any official candidate
Unofficial Candidates: the list of unofficial candidates defined for the given contest by the election manager will be displayed and the write-in can be assigned to any unofficial candidate
Undervote: the write-in can be deemed invalid and will be considered in tallies as an undervote
Adjudications are immediately persisted to the data store. Adjudications can be changed or deselected.
The list of unofficial write-in candidates is created by the election manager as they adjudicate. The interface has an option to add a new write-in candidate and specify their name. That candidate will then be an option for other write-ins for the same contest. If there are no longer any adjudications that reference the unofficial candidates, their name will be removed from the list.
In most cases, the adjudication reclassifies a vote for an unadjudicated write-in to a write-in candidate. But in some cases, the adjudication effectively reclassifies a mark as a non-mark or vice versa.
If a marked write-in is adjudicated as an undervote, in addition to updating the associated write-ins
record, VxAdmin will create a vote_adjudications
record representing the switch from an indication to a non-indication. If an unmarked write-in is adjudicated for a candidate, VxAdmin will create a vote_adjudications
record representing the switch from a non-indication to an indication.
User Manual Reference: Write-In Adjudication
VxAdmin offers a way to enter manual tallies that are then added to reports. When manual tallies are present in a results export, they are always displayed separately from scanned tallies so that users can easily recognize the impact of manual results and recognize any human errors. The only exception to this rule is the CDF election results export in which, due to the limitations of the CDF, the manual and scanned tallies are simply combined.
The ballot style, precinct, and voting method (absentee vs. precinct) must be specified before entering manual tallies. By associating manual tallies with these pieces of metadata, they can be filtered and grouped according to those dimensions when creating reports. Notably, manual tallies are not associated with a batch or a scanner like CVRs. When filtering on batch or scanner, manual tallies are excluded. When grouping by batch or scanner, manual tallies are treated as a single batch or scanner.
The manual tallies for each contest are validated according to a standard formula:
The same formula also applies to all results generated from scanned ballots. If a vote for three contest is overvoted, it is considered three overvotes. If the contest tallies entered by the user are incomplete or invalid, the user is presented with warning messages.
In most cases, the ballot count will be the same across all contests. In some jurisdictions it is possible for different contests to have different ballot counts if, for example, someone votes on a ballot without local contests. In these cases, the user can override the ballot count on an individual contest basis.
Unofficial write-in candidates can also be allocated votes in manual tallies and new unofficial write-in candidates can be added directly from the manual tallies interface.
User Manual Reference: Manual Tallies
Vote tallying is a multi-step process which takes place on the VxAdmin backend:
Every tally is specified by a set of filters and groupings. The filter defines which CVRs are excluded and included. For example, a filter might limit the CVRs to the CVRs for a specific precinct. The group determines how tallies are subdivided by CVR metadata. For example, there may be a grouping on precinct which generates tallies for each precinct separately. Groups enable multiple related tallies to be efficiently generated at once.
Filters and groupings are specified by the user directly with the tally report builder or implicitly with built-in reports.
If there are no groupings specified, there is only one set of tallies. If the precinct grouping is specified, there will be tallies for each precinct. If multiple groupings are specified, the possible resulting groupings need to be calculated. For example, if the precinct and ballot style groupings are both specified, only some combinations are possible because not all ballot styles exist in all precincts. If filters are specified, they may rule out certain groupings. For example, if the precinct grouping is specified but only Precinct A and Precinct B are included by the filter, then the Precinct C grouping will be excluded.
If batch or scanner parameters are included, then VxAdmin will not attempt to compute the possible groupings because they may be too numerous. The potential groups will be created opportunistically during tallying.
The purpose of computing the groups when possible, rather than always creating groups opportunistically, is to know which zero tallies to expect. When we group by precinct, we'd like to generate empty results for Precinct A even if no ballots for Precinct A were cast.
CVR Aggregation
The CVRs are pulled from the data store one by one and their vote data is added into an ongoing tally of ballots, contest option votes, overvotes, and undervotes. If the tallies are being grouped, the CVR will be added into the group that matches its metadata e.g. a CVR from a Precinct A ballot will be added to the Precinct A group.
At this step in the process, the data does not contain any of the adjudication details from write-in adjudication.
CVR aggregation is the most computationally expensive step in the vote tallying so the results are cached. The cache is reset anytime a CVR file is added or removed or anytime a vote is adjudicated through write-in adjudication.
Write-In Adjudication Aggregation
The write-in adjudication records are summarized from the data store and their adjudication statuses are added into an ongoing tally of write-ins for official candidates, write-ins for unofficial candidates, invalid write-ins, and unadjudicated write-ins. They are filtered and grouped according to the same parameters as the CVRs.
The write-in adjudication report is simply the results of the write-in adjudication aggregation step, without filter or group, formatted into a PDF.
The vote tallies from the CVRs are then hydrated with the aggregated write-in adjudication tallies to create vote tallies that include the results of write-in adjudication. Before hydration, the tallies represent all write-ins as generic write-ins. The counts for generic write-ins are reconciled to counts for specific official and unofficial candidates.
Manual tallies are already aggregated in the sense that each can represent more than one ballot. Since they are divided by ballot style, precinct, and voting method, however, they may need to be merged to match the groupings (or lack thereof) of the scanned vote tallies.
Manual tallies are then combined with the scanned tallies in one of two ways. For most reports, the manual tallies are paired with the scanned tallies but are not immediately added together. Reports can then display the manual and scanned tallies separately in addition to showing the total tallies. For the CDF election results report, however, the manual tallies and scanned tallies are added together because there is not a clear way to represent the difference between them in the CDF.
Reporting
The final step is for the VxAdmin backend to format the vote tallies into one of VxAdmin's Results Export Formats and export the result onto a USB drive or, if it is a PDF document, print it.
User Manual Reference: Reports
Ballot counts are tallied as part of the vote tallying flow described above, but there is a separate tallying path that only calculates the ballot counts. It is used when generating ballot count reports and exports from VxAdmin. It follows the same steps as vote tallying, but is more efficient because it can use the underlying SQLite database to generate tallies rather than iterating through each CVR one-by-one.
When tallying ballot counts, VxAdmin is actually tallying sheet counts. In an election where all ballots are a single sheet, there is no distinction between ballot counts and sheet counts. In an election with multi-sheet ballots, there may be different numbers of different ballot sheets. VxAdmin tallies each sheet separately, which is displayed on tally reports and ballot count reports.
The Ballot Count is defined in VxSuite as simply the count of first sheets. For example, if there are 1,000 first sheets and 999 second sheets, the ballot count will appear in reports as 1,000.
Results on VxAdmin are considered unofficial until the election manager marks them as official. As long as results are unofficial, CVRs can be loaded, write-ins can be adjudicated, and manual tallies can be added and edited. All reports and result exports are labelled as "Unofficial."
Once the results are final and often only after a jurisdiction's specific certification process, the election manager can mark results as official. All reports and result exports will then be labelled as "Official." CVRs can no longer be loaded, write-ins can no longer be adjudicated, and manual tallies can no longer be altered.
There are two ways to exit official results modes:
The system administrator may unconfigure VxAdmin entirely, removing the election configuration in addition to all tallies and adjudications.
The election manager may remove all tallies and adjudications at once, leaving the election configuration in place.
VxAdmin can print reports via an attached printer. The supported printer is the HP LaserJet Pro 4001dn. VxAdmin can also export reports as PDFs so, in the event of a printer failure, reports will always be available.
VxAdmin interfaces with the printer through the CUPS, the open-source printing system developed by Apple and installed on our Debian system. When a printer is attached, it is registered with the CUPS server and made available to the application. VxAdmin is able to send print jobs to the printer via CUPS commands. The HP LaserJetPro does not require any additional third-party or in-house driver because it supports the IPP (Internet Printing Protocol) which CUPS then utilizes.
Using IPP, the VxAdmin is also able to poll the detailed status (toner level, jam status, etc.) of the printer for use in the diagnostics interface.
VxAdmin can only connect with one printer at a time and will always connect with with the first attached printer.
Signed Hash Validation provides end users with a way to verify that a VotingWorks machine is running authentic unmodified VotingWorks software.
The machine preps a payload consisting of the following, with 1//shv//
as a prefix and #
as a separator:
System hash
Software version
Election ID
Current timestamp
The machine signs that payload with its TPM private key and then bundles the following together, with ;
as a separator:
Payload
Payload signature
Machine cert
This combination is displayed as a QR code. Putting this all together, the QR code contains:
This QR code can be scanned at https://check.voting.works. The site parses the QR code and performs the following verification:
Verifies the machine cert using the root VotingWorks cert.
Extracts the machine's public key from the machine cert.
Uses that public key to verify the payload signature against the original payload. If this verification succeeds, we can be confident that the machine possesses the TPM private key that pairs with the public key in the machine cert.
Because the TPM private key will only sign data if the system hash is correct, per System Integrity, we can further be confident that the software on the machine is authentic and unmodified.
After completing the above verification, https://check.voting.works displays a success indicator alongside the payload components and the machine ID as extracted from the machine cert. These attributes can be matched against what's displayed on the machine.
Refer to the following code links for more details:
VxScan consists of two main components - the collapsible ballot box and the scanner itself - which are secured together during setup.
The ballot box features a telescoping handle and wheels for ease of transport. When collapsed, closing straps run around the side of the box to hold it closed. Before the ballot box is set up, the closing straps are loosened and secured to the underside of the ballot box lid.
The front of the ballot box is the ballot door, which is used to access the bin interior and any ballots within. It's opened by pulling the ballot door latch pictured above, which automatically latches whenever the door is closed. A seal can be installed to prevent the door from being opened without tamper-evidence.
The ballot door has a built-in auxiliary bin for depositing ballots in situations where the ballots cannot be scanned. It can be in one of three states: closed, partially open for depositing ballots, or fully open for removing ballots. It's opened by pressing down on the indicated handle which can be sealed with the adjacent seal point.
After closing straps are loosened, the ballot box can be expanded. An accented foot hook can be used as an aid in expanding the box. Once the box is fully expanded, the lid can be rotated up and over 270 degrees to eventually close and latch into place.
After being latched, the ballot box lid can be released by pushing the ballot box lid handle, indicated below. The handle is covered by the scanner when installed, so it cannot be opened while the scanner is in operation and sealed in place. The box lid has a ballot slot which mates with the scanner's ballot outfeed.
The scanner attaches to the ballot box by sliding into the area in the front of the lid. Flanges on the bottom of the scanner prevent it from moving up and down or side to side. To secure the scanner front to back and lock it into place, the scanner has a security bolt which mates with the security bolt hole on the top of the ballot box. After the security bolt is engaged, the scanner cannot be removed until the security bolt is unsealed and released. This is covered more fully in the next section.
The scanner is built into a customized Pelican 1485 Air case. The COTS case features:
Seal Points
Carrying Handle
Spring-Loaded Latches
Additional cuts are made into the case for the back power port, the back cable wrap, the security bolt exit, nameplate attachment, and mounting features within the case.
The case is opened by pressing the buttons on each case latch and then lifting the lid. The elements that a voter or poll worker interact with are generally accented in purple, just as with the ballot box. In the picture below you can see the smart card insert, security bolt, ballot infeed, and printer outfeed all accented in purple.
When the scanner is first installed on the ballot box, the security bolt must be disengaged. While the security bolt is disengaged, the smart card slot will be blocked. Once the scanner is installed on the ballot box, the user must push the bolt down to lock the scanner into place on the ballot box. This will also unblock the smart card slot. In this way, the scanner can not be activated until it is properly installed.
When the scanner must be removed from the ballot box, the user pushes the security bolt release to the left to disengage the security bolt. The security bolt release is accented with graphical instructions for the user. In order to access the security bolt release, the poll worker door must be opened, which also exposes the scanner's USB ports. The poll worker door can be sealed shut by passing a seal through a cutout in the door and the hole in the top of the security bolt.
Poll workers will normally not have to interface with any parts of the scanner that have not already been described, but election managers may have to open the access door to perform maintenance on the printer and scanner. The access door is held in place by the poll worker door and can only be opened when the poll worker door is unsealed and opened. The printer and printer roll holder are beneath the access door toward the screen. The user presses the green release lever to remove the printer roll holder and install a paper roll. The scanner can be opened simply by lifting the scanner cover handle, revealing the scanner glass for easy cleaning.
The various components of the scanner are arranged and wired together within the Pelican case. Custom cut holes in the Pelican case allow mounting brackets in the top and bottom tubs which are then used to attach components.
Power enters through a power module embedded in the case. The power module connects to a 24-volt power supply which supplies the scanner and printer with power. A 12-volt power supply is daisy-chained from the 24-volt power supply in order to power the single board computer.
The metal chassis of the bottom tub is grounded to exterior ground via the power module. Everything else requiring grounding is then grounded to the bottom chassis - power supply, lid chassis, access panel, and the scanner.
All USB cables ultimately connect to the single board computer. The card reader and printer connect via a custom USB cable directly to headers on the computer. The USB hub, which then connects to the USB ports and scanner, is connected directly to the computer. Finally, a USB-C cable connects the computer to the screen. The USB-C cable carries video, audio, touch input, and power. Audio is carried through the screen to the speakers via a separate cable.
The wiring digram below outlines the power and data connections within the scanner. Black lines indicate power connections, gray lines indicate ground connections, and purple lines indicate data connections, which may also carry low voltage power.
To prevent access to internals, VotingWorks installs three seals over screws holding the metal panels in place - one on the bottom left panel covering the computer, one on the bottom right panel covering the power supplies, and one on the top panel holding the display in place. These seals are installed at the factory and are intended to be permanent aside from when panels need to be opened for repairs.
The paper path is carefully designed and tested to ensure a smooth and uninterrupted ballot scan and deposit. The voter inserts paper over the infeed which mates directly with the scanner. The scanner lid handle doubles as an upper deflector, deflecting ballots which are inserted too high by the voter. As the ballot passes through the scanner, it hits the ballot redirector behind the scanner. The ballot redirector is a logarithmic curve which ensures that wherever the ballot strikes, it will be directed downward. The ballot then passes through the outfeed slot (which is only open when the scanner case is open) into the ballot box.
VxScan includes many COTS components, which mostly fall into two categories. First, many small pieces of hardware such as fasteners are purchased commercially. These are called out in the bill of materials and are not generally critical components. Second, most of the electronic components are purchased commercially. Documentation for these components can be found in the documentation repository.
Peripheral Dynamics, Inc.
PageScan 6 Scanner
PS6
High
USBFirewire
10" USB A-B Cable
RR-ADBU-10GR
Medium
L-com
0.5m USB A-B Cable
CAABLK-90RB-05M
Medium
GlobTek, Inc.
USB-C Cable
USBCW1M0USBC2SLEMBK
Medium
HID Omnikey
Embedded Smart Card Reader
R31210375-1
Medium
Aaeon
Single-Board Computer
UPN-ADLN97-A10-0864
High
ADATA
Solid-State Drive
IM2P32A8-128GCTB5
High
Tripp Lite
USB Panel Mount
U324-001-APM
Medium
CUI Devices
Power Cable
AC-C13 NA
Low
MEAN WELL
12V Power Supply
LRS-75-12
Medium
MEAN WELL
24V Power Supply
LRS-150-24
Medium
Fujitsu
A4 Thermal Printer Mechanism
FTP-68EMCL112-R
High
Fujitsu
A4 Thermal Printer Control Board
FTP-62EDSL201-R
High
Fujitsu
A4 Thermal Printer Head Cable
FTP-62EY001-R
Medium
Coolgear
USB Hub
CG-3510S4-BOARD
Medium
Pelican
Outer Case
Pelican Air 1485
Medium
Elo
Touchscreen
E976783
Medium
As listed in the COTS table above, the high criticality components are as follows:
Aaeon UP Squared Pro 7000 Computer - As the computer which orchestrates ballot interpretation and vote tallying, the single board computer is a highly critical component. VotingWorks partners with Aaeon, Inc. and their production in Taiwan to ensure the trustworthy production and quality of each single board computer.
PageScan 6 Scanner - As the source of ballot images for interpretation, the embedded scanner is a highly critical component. Any interference in image creation could affect interpretation and subsequently vote tallies. Any interference in paper handling could affect ballot accounting. VotingWorks works closely with Peripheral Dynamics, Inc. to ensure the quality of the hardware and firmware of the scanner manufactured domestically. The specific VotingWorks firmware version is tracked by Peripheral Dynamics, Inc. and installed on all scanners.
Fujitsu Thermal Printer Mechanism and Control Board - The thermal printer is a less sensitive component than the previous two because it does not send sensitive data to the application - it only receives sensitive data. It is still a single-sourced component with complex subassemblies, however, and any issues printing would prevent jurisdictions from having accurate day-end results.
Solid State Drive - The solid state drive is the storage medium for all sensitive election data.
The medium criticality components and the reasons for their classification are as follows:
USB Cables, Hub, and Mounts - USB cables connect to the computer and carry sensitive election data, so they are medium criticality. The attack vectors are difficult, however, and all cables can be produced by alternate manufacturers.
Power Cables & Power Supplies - Power supplies and cables can affect the reliability of the equipment in initially difficult to detect ways, and are thus medium criticality, but they generally cannot corrupt election data in a targeted or undetectable way.
Pelican Case - The Pelican case cannot meaningfully affect the operation of the software, but its sole supplier is Pelican. Since the equipment is designed around the particular case, the case and its supplier are considered critical.
Touchscreen - The Elo touchscreen is responsible for rendering election data and correctly handling user touches, but it generally cannot impact election data and impacts would be perceptible. It is custom component from a single manufacturer, however, and is certainly medium criticality.
Smart Card Reader - The smart card reader is responsible for communicating with smart cards to manage authentication, and is thus a critical component.