Cast Vote Records
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.
Directory Structure
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.
CVR UUIDs
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.
Including Ballot Images
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.
Including Rejected 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:
Cast Vote Record Report
CDF Implementation
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 NIST JSON schema with the VxSuite JSON schema. The additionally required fields are listed in a table below.
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.
VxSuite Required Fields
CVR
BallotStyleId, BallotStyleUnitId, BatchId, CreatingDeviceId, UniqueId
CVRContest
CVRContestSelection
CVRContestSelection
ContestSelectionId
SelectionPosition is limited to length 1
CVRSnapshot
CVRContest
Report Metadata
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 election package. 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
.
CastVoteRecordReport
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
CastVoteRecordReport.ReportingDevices
Only one ReportingDevice
is ever listed:
@id
The scanner serial number
SerialNumber
The scanner serial number
Manufacturer
Fixed to "VotingWorks"
CastVoteRecordReport.Party
The list of parties in the cast vote record report is mapped directly from the Party list in the election definition:
@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"
CastVoteRecordReport.GpUnit
GpUnit
s are created for each Precinct in the election, for the County, and for the state:
@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
CastVoteRecordReport.Election
The Election
class has values mapped to it directly from the election definition:
@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
Cast Vote Record Attributes
Each cast vote record includes a set of ballot metadata attributes:
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
Ballot Images
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:
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
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.
Snapshots
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
Ballot Type
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:
CVRSnapshot.Status
Fixed to ["other"]
CVRSnapshot.OtherStatus
JSON blob representing the ballot type. The possible values are "absentee", "precinct", or "provisional".
Representing Votes
The CVRContest
class within each snapshot contains a list of vote records by contest. The fields are used as follows:
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
Ballot Images
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
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.
Export Metadata
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:
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
Batch Manifest
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.
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
Last updated