Architecture
This page explains how the running system is built and why. For the exact endpoints see the API Reference; for the cryptography see The matching protocol.
The shape of the system
Section titled “The shape of the system”Vouch is a small monorepo with a deliberately thin, crypto-blind server. The device does the cryptography; the server only ever pairs users and compares opaque points.
- Server — FastAPI on Python, backed by CloudNativePG Postgres 18. Alembic
migrations run once per release as a Helm hook Job. A background matcher loop pairs
preference-compatible users. Admin/debug endpoints sit behind a bootstrap
token. Surrogate primary keys are UUIDv7, generated server-side by
Postgres 18’s built-in
uuidv7()— PG18 is a hard requirement. - Client — a React SPA served by nginx. All crypto runs in-browser via libsodium; cross-language test vectors keep the browser bit-compatible with the server.
- Infra — k3s on two Graviton EC2 nodes (a public edge node and a private apps node), fck-nat for egress, Traefik with Let’s Encrypt for TLS, images in ECR. Everything is provisioned by OpenTofu, and helmfile converges the cluster.
Why the server is crypto-blind
Section titled “Why the server is crypto-blind”The whole point of Vouch is that plaintext contacts and secret keys never leave the device. So the server is designed to hold as little as possible: it stores opaque 32-byte points, pairs users by preference, and hands each side the other’s published set. It learns only the cardinality of an intersection and index linkage — never a phone number. This is what the protocol buys, and it shapes every API: there is no endpoint that could return a contact, because the server never has one.
Request path
Section titled “Request path”A request from the SPA hits Traefik on the edge node (TLS terminated with a
Let’s Encrypt cert), is routed by host (app. → client, api. → FastAPI), and
lands on the apps node. The API talks to the in-cluster Postgres. The
background matcher runs inside the API process on a timer.
Deployment topology
Section titled “Deployment topology” Internet │ (TLS, Let's Encrypt) ┌────▼─────┐ │ Traefik │ edge node (public) └────┬─────┘ app. │ api. │ hyperdx. ┌────────┴─────────┐ │ FastAPI · nginx SPA │ apps node (private) │ CloudNativePG Postgres │ └───────────────────────────┘ │ egress ┌────▼────┐ │ fck-nat │ └─────────┘Known gaps
Section titled “Known gaps”The architecture is deliberately minimal and has documented gaps on the way to production — single nodes per role, no Postgres backups yet, and an unfinished observability hop. These are catalogued and prioritised in The road to production and Observability.