feat: add confidential ballot reference provider

This commit is contained in:
2026-08-02 03:41:01 +02:00
parent c176c5cfcb
commit 0a4e06077d
10 changed files with 1505 additions and 44 deletions
+32
View File
@@ -32,6 +32,30 @@ credentials inside its own assurance boundary and returns aggregate counts,
weighted counts, a result hash, and evidence. GovOPlaN does not claim that a
provider or deployment satisfies legal or certification requirements merely
because the adapter contract is implemented.
Core bounds provider evidence to JSON, 64 items and 64 KiB and rejects fields
that can carry credentials, private key material, plaintext, or raw
selections before Voting or Committee can persist the projection.
### Bundled local confidential provider
`local_confidential` is an interactive reference provider for the
`confidential` profile. Opening a ballot creates a ballot-scoped Encryption
vault using the configured `local_aesgcm` provider. Casting stores the elector,
weight, receipt, and replacement generation as provider metadata while the
selection payload is stored only as authenticated ciphertext. Finalization
opens active cast envelopes inside the provider boundary and exports only the
aggregate and sanitized evidence.
Encryption records a context-bound keyed commitment rather than an enumerable
plaintext digest, so low-entropy choices are not exposed to an offline database
reader through idempotency metadata.
This profile is server-readable. It does not provide voter anonymity,
unlinkability, coercion resistance, client-held keys, an HSM/KMS claim, or
external certification. It therefore cannot be selected for `secret` or
`external_certified` ballots. A provider ballot reference is generated when
the ballot opens; externally hosted providers may continue to require a
pre-existing reference.
## Lifecycle and concurrency
@@ -55,6 +79,8 @@ Back up these tables as one consistency unit:
- `voting_cast_records`
- `voting_lifecycle_events`
- `voting_command_replays`
- `voting_confidential_ballots`
- `voting_confidential_casts`
A restore is valid only when current revisions are unique per tenant and
ballot, cast generations are unique per elector, every active cast references
@@ -62,6 +88,10 @@ the current frozen definition hash, result hashes can be recomputed, and event
sequences are contiguous. Provider-backed restores also require the external
provider evidence and ballot reference to remain resolvable. Do not reopen a
restored external ballot merely to compensate for missing provider state.
For `local_confidential`, restore the Voting and Encryption tables from the
same consistency point and restore the exact deployment `MASTER_KEY_B64` from
the approved secret store. A database-only restore or a changed/lost master
key must fail closed; it cannot reconstruct confidential casts.
Before destructive retirement, stop new casts, retain a verified database
snapshot, export result/certification evidence under the applicable retention
@@ -74,6 +104,8 @@ node-local filesystem.
- tenant predicates apply to every ballot, cast, event, and replay lookup
- the authenticated account must match the frozen elector subject
- native casting fails closed for non-recorded assurance profiles
- interactive provider casting validates the frozen tenant, electorate,
definition, options, replacement policy, and time window again
- raw selections are never returned by list, detail, result, or history APIs
- provider result keys must exactly match frozen options
- external results require evidence and cannot exceed the frozen electorate