Product · Architecture
Architecture overview
Three user surfaces and one protocol. Votes never cross the officer console. Public legitimacy uses an append-only hash chain — not a general-purpose public blockchain.
System context
Who talks to what
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Officer portal │ │ Voter device │ │ Public HTML / │
│ (admin only) │ │ (ONLY cast) │ │ observers │
└────────┬────────┘ └────────┬─────────┘ └────────▲────────┘
│ │ │
└──────────► Go API + services ────────────────┘
│
┌──────────┴──────────┐
│ Append-only log │ public artefacts, votes
│ Private membership │ PII, bind secrets
│ Object/blob store │ evidence by hash
└─────────────────────┘
Repositories (multi-repo)
| Repository | Responsibility |
|---|---|
| publicvoting-protocol | OpenAPI, procedure packs, Mode B suite + vectors, SemVer VERSION |
| publicvoting-api | Go API, Postgres, public pages, smoke/verifier, deploy |
| publicvoting-portal | React officer console — no cast |
| publicvoting-mobile | Dart Mode B crypto, API client, cast tooling (Flutter UI planned) |
| publicvoting.org | Design, ADRs, governance, this marketing site |
Dependency direction: protocol → vendored into API & mobile; portal and mobile call API over HTTP; portal ↛ mobile.
Technology stack
| Layer | Choice |
|---|---|
| API | Go, Postgres (memory store for tests), Docker Compose |
| Portal | React, Vite, TypeScript |
| Device | Dart cryptography + CLI; Flutter target UI |
| Crypto suite | publicvoting-modeb-v1 — Ed25519, X25519 hybrid seal, AES-256-GCM, Shamir t-of-n, Argon2id recovery |
| Integrity substrate | Append-only hash chain + optional log signatures |
| Config | Procedure packs (JSON Schema), system settings, brand themes |
| License | Apache-2.0 for software; trademarks separate |
Data canonicity
| Data | Canonical store |
|---|---|
| Votes, decision public text hashes, arguments, freezes, void/extend | Append-only log |
| Membership PII, bind tokens, admin labels | Private DB |
| Evidence files | Blob store; hash + URI on log |
| DB projections of log | Rebuildable; log wins if diverge |
Mode B cast path (summary)
- Officers publish ballot public key (private key split t-of-n)
- Device builds plaintext choice + content hash
- Hybrid-encrypt under ballot key → ciphertext + tracker
- Sign envelope with device Ed25519 key
- API verifies sig, binding, roll, window, idempotency → append log
- After close, ≥t talliers open and publish tally transcript hash
Details: Security model and protocol suite docs on GitHub.
Trust boundaries
- Registration authority — officers control who is on the roll (dual control mitigates solo abuse)
- Device — holds K_device; malware residual risk for all remote voting
- API during vote — has ballot public key only in production default; cannot decrypt choices
- Talliers — threshold custodians of ballot private material after close
- Public mirrors — anyone can recompute log heads and inclusion