System

The server & its API

A deliberately blind router written in Rust. It verifies signatures, moves ciphertext, and keeps no request logs — there is no logging layer mounted at all.

The server is a blind mailroom. It can check that a request is properly signed and hand off sealed envelopes, but it can’t read them, and it doesn’t keep a diary of who came and went. There are two ways in: a normal session key once you’re logged in, and — for the few public lookups — a puzzle instead of an ID check.

Rust + Axum + Tokio. The router mounts CORS (fail-closed allowlist) and label-free metrics but no tracing/logging layer, by design. Auth is either a 24h HMAC session token (header X-Privex-Auth) proven by a hybrid signature, or a PoW-gated public endpoint where a single-use proof replaces IP identity. A prekey bundle is never returned without a KT proof.

Routes & backing stores
session auth vs PoW-gated public endpoints
PoW-gated public session auth WebSocket store
Figure. The relay crate (onion/Sphinx) is a Phase-2 skeleton and the Nym worker is a stub today; Phase 1 runs over direct WSS.

The guarantees baked into the routes

  • /auth/verify returns a single generic 401 and runs dummy-key work for absent users — no timing oracle.
  • A prekey bundle is never returned without a Key Transparency inclusion proof; one OPK is consumed atomically.
  • WebSocket auth uses a single-use Redis ticket in Sec-WebSocket-Protocol, never a query string.
  • /health/ready sheds the pod (503) when Postgres, Redis, or the object store is unreachable.
  • Online presence lives only in a RAM map, cleared on disconnect — never written to disk.