Files

3.8 KiB

Voting domain, assurance, and operations

Ownership boundary

Voting owns the protocol and authoritative state of a governed ballot:

  • immutable ballot definitions after opening
  • frozen electorate entries, weights, and provenance
  • eligibility enforcement, vote replacement, and receipts
  • deterministic tally, quorum, threshold, closure, and certification
  • challenge, annulment, command replay, and lifecycle evidence
  • provider-neutral handoff for confidential, secret, or externally certified voting

Committee owns the body, meeting, agenda, deliberation, and minute context. It stores a Voting ballot reference and a verified aggregate result for meeting records. Poll owns informal preference, response, and availability collection. Decisions owns the resulting formal institutional outcome. Encryption and Identity Trust own cryptographic key and device primitives rather than the voting ceremony.

Assurance profiles

The native recorded profile stores each current vote with its elector, selection, weight, generation, and receipt hash. Superseded votes remain available for authorized reconstruction. It is auditable but not secret.

The confidential, secret, and external_certified profiles require a provider exposed as voting.provider.<provider-id>. Voting refuses to open the ballot when that provider is unavailable. The provider keeps raw ballots and 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.

Lifecycle and concurrency

Ballots move through draft -> open -> closed -> certified. A closed or certified result can be challenged. An administrator can annul an invalid ballot from any non-annulled lifecycle state. Opening freezes SHA-256 hashes of the definition and electorate. Each state change creates a new immutable revision and lifecycle event. Mutating commands require an expected revision and an idempotency key; a key replay returns the first outcome and a key reused with another payload is rejected.

Recorded voters can replace a vote only when the frozen definition allows it. The previous generation is retained and excluded from the active tally. Lifecycle events contain the receipt hash and generation, not the selection.

Operations and recovery

Back up these tables as one consistency unit:

  • voting_ballot_revisions
  • voting_cast_records
  • voting_lifecycle_events
  • voting_command_replays

A restore is valid only when current revisions are unique per tenant and ballot, cast generations are unique per elector, every active cast references 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.

Before destructive retirement, stop new casts, retain a verified database snapshot, export result/certification evidence under the applicable retention policy, and reconcile any Committee or Decision references. Horizontal nodes must use the shared database; no authoritative Voting state is stored on a node-local filesystem.

Security checks

  • 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
  • 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
  • certification and annulment use separate permissions