Files
quicproquo/docs/src/design-rationale/adr-006-rest-gateway.md
Christian Nennemann 2e081ead8e chore: rename quicproquo → quicprochat in docs, Docker, CI, and packaging
Rename all project references from quicproquo/qpq to quicprochat/qpc
across documentation, Docker configuration, CI workflows, packaging
scripts, operational configs, and build tooling.

- Docker: crate paths, binary names, user/group, data dirs, env vars
- CI: workflow crate references, binary names, artifact names
- Docs: all markdown files under docs/, SDK READMEs, book.toml
- Packaging: OpenWrt Makefile, init script, UCI config (file renames)
- Scripts: justfile, dev-shell, screenshot, cross-compile, ai_team
- Operations: Prometheus config, alert rules, Grafana dashboard
- Config: .env.example (QPQ_* → QPC_*), CODEOWNERS paths
- Top-level: README, CONTRIBUTING, ROADMAP, CLAUDE.md
2026-03-21 19:14:06 +01:00

4.6 KiB

ADR-006: SDK-First Adoption — Native QUIC + Cap'n Proto, No REST Gateway

Status

Accepted (supersedes earlier REST gateway proposal)

Context

quicprochat uses QUIC + Cap'n Proto RPC as its native protocol. This combination delivers zero-copy serialization, multiplexed streams, and sub-RTT connection establishment — ideal for high-performance clients.

Cap'n Proto has limited language support compared to Protocol Buffers or JSON. Adding an HTTP/JSON REST gateway was considered to lower the barrier to entry. However, this would:

  1. Contradict the project identity. The name is literally quicnprotochat. An HTTP gateway undermines the protocol-native philosophy.
  2. Add base64 overhead (~33%) for binary payloads (MLS ciphertext, key packages) that are already optimal in Cap'n Proto's wire format.
  3. Create a second code path to maintain, test, and secure.
  4. Lose QUIC transport benefits (0-RTT, multiplexing, congestion control) for clients that use the HTTP path.

Decision

No REST/HTTP gateway. Instead, invest in native QUIC + Cap'n Proto SDKs for every viable language, plus WASM/FFI for the crypto layer.

The .capnp schema files ARE the interface definition — they serve the same role as an OpenAPI spec, but for the native protocol.

SDK strategy

Language QUIC Cap'n Proto Approach
Rust quinn capnp-rpc Existing reference client
Go quic-go go-capnp Native SDK, high confidence
Python aioquic pycapnp Native QUIC, manual RPC framing
C/C++ msquic/ngtcp2 capnproto Reference impl, full RPC
Browser WebTransport WASM bridge QUIC transport via HTTP/3

Browser access via WebTransport

Browsers cannot open raw QUIC connections, but they can use WebTransport — which runs over HTTP/3 (which runs over QUIC). The server adds a WebTransport listener alongside the Cap'n Proto QUIC listener. Cap'n Proto RPC is framed over WebTransport bidirectional streams, identical to the native path.

Browser → WebTransport (HTTP/3 over QUIC) → Cap'n Proto RPC → Server
Native  → QUIC                            → Cap'n Proto RPC → Server

Both paths use QUIC transport. The project name stays honest.

Crypto layer distribution

MLS encryption/decryption must happen client-side. The quicprochat-core crate is compiled to:

  • WASM — for browsers, Node.js, Deno
  • C FFI (libquicprochat) — for Swift, Kotlin, Python, Go (via cgo)
  • Native Rust — for Rust clients (existing)

Why not REST?

  1. Protocol purity. One protocol, one code path, one mental model.
  2. No serialization tax. No base64, no JSON parsing, no HTTP headers.
  3. QUIC everywhere. WebTransport gives browsers QUIC access without HTTP semantics leaking into the protocol.
  4. Schema-driven. .capnp files generate type-safe stubs in every supported language — the same developer experience as protobuf/gRPC.

Why not gRPC?

  1. We already have Cap'n Proto with zero-copy deserialization.
  2. Adding protobuf would mean three serialization formats in one project.
  3. Cap'n Proto's time-travel RPC (promise pipelining) is architecturally superior to gRPC's request-response model for chained operations.

gRPC may be reconsidered for server-to-server federation (Phase 7.3).

Consequences

Positive

  • Protocol coherence. Every client speaks the same wire format.
  • Performance. No translation layer, no base64 overhead, no HTTP framing.
  • Identity. The project name accurately describes the protocol stack.
  • Security. One code path to audit, not two.
  • WebTransport. Browsers get native QUIC with the same RPC interface.

Negative

  • Higher SDK effort. Each language needs a QUIC + Cap'n Proto integration, not just an HTTP client.
  • Cap'n Proto ecosystem gaps. JavaScript and Swift lack mature Cap'n Proto RPC libraries; these languages rely on WASM bridges.
  • WebTransport maturity. Browser support is good (Chrome, Edge, Firefox) but not universal; Safari support is emerging.

Neutral

  • SDKs live in separate repositories (e.g., quicprochat-go, quicprochat-py) to avoid bloating the core workspace.
  • The C FFI crate (quicprochat-ffi) bundles both crypto and transport, so language bindings only need to call C functions.