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)

RepositoryResponsibility
publicvoting-protocolOpenAPI, procedure packs, Mode B suite + vectors, SemVer VERSION
publicvoting-apiGo API, Postgres, public pages, smoke/verifier, deploy
publicvoting-portalReact officer console — no cast
publicvoting-mobileDart Mode B crypto, API client, cast tooling (Flutter UI planned)
publicvoting.orgDesign, ADRs, governance, this marketing site

Dependency direction: protocol → vendored into API & mobile; portal and mobile call API over HTTP; portal ↛ mobile.

Technology stack

LayerChoice
APIGo, Postgres (memory store for tests), Docker Compose
PortalReact, Vite, TypeScript
DeviceDart cryptography + CLI; Flutter target UI
Crypto suitepublicvoting-modeb-v1 — Ed25519, X25519 hybrid seal, AES-256-GCM, Shamir t-of-n, Argon2id recovery
Integrity substrateAppend-only hash chain + optional log signatures
ConfigProcedure packs (JSON Schema), system settings, brand themes
LicenseApache-2.0 for software; trademarks separate

Data canonicity

DataCanonical store
Votes, decision public text hashes, arguments, freezes, void/extendAppend-only log
Membership PII, bind tokens, admin labelsPrivate DB
Evidence filesBlob store; hash + URI on log
DB projections of logRebuildable; log wins if diverge

Mode B cast path (summary)

  1. Officers publish ballot public key (private key split t-of-n)
  2. Device builds plaintext choice + content hash
  3. Hybrid-encrypt under ballot key → ciphertext + tracker
  4. Sign envelope with device Ed25519 key
  5. API verifies sig, binding, roll, window, idempotency → append log
  6. 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