Implement governed voting module
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user