Christian Nennemann 5a6d9ae7f4 docs: next sprint planning — 12 feature candidates for selection
Sprint plan for cycles 12-19. Pick 8 of 12 features:
A) Federation wiring, B) Contacts/blocking, C) Voice/video signaling,
D) Encrypted backup, E) Group roles, F) KT audit client, G) Message
search, H) Server clustering, I) Protocol compliance, J) User profiles,
K) Notification framework, L) Mobile app shell.
2026-03-04 02:02:01 +01:00
2026-03-01 21:40:13 +01:00

QPQ logo

QPQ — quicproquo

CI

End-to-end encrypted messaging over QUIC + TLS 1.3 + MLS (RFC 9420), written in Rust.

The server never sees plaintext. Every byte on the wire is protected by a QUIC transport secured with TLS 1.3 (quinn + rustls). The inner MLS layer provides forward secrecy, post-compromise security, and ratcheted group key agreement across any number of participants. Messages are framed with Cap'n Proto for zero-copy, schema-versioned serialisation.

┌─────────────────────────────────────────────┐
│          Application / MLS ciphertext        │  <- group key ratchet (RFC 9420)
├─────────────────────────────────────────────┤
│              Cap'n Proto RPC                │  <- typed, schema-versioned framing
├─────────────────────────────────────────────┤
│        QUIC + TLS 1.3 (quinn/rustls)        │  <- mutual auth + transport secrecy
└─────────────────────────────────────────────┘
Property Mechanism
Transport confidentiality TLS 1.3 over QUIC (rustls)
Transport authentication TLS 1.3 server cert (self-signed or CA)
Group key agreement MLS MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
Post-compromise security MLS epoch ratchet
Forward secrecy Per-epoch key schedule
Identity Ed25519 (MLS credential + leaf node signature)
Password auth OPAQUE (password never sent to server)
Post-quantum readiness X25519 + ML-KEM-768 hybrid KEM envelope
Local storage encryption SQLCipher + Argon2id + ChaCha20-Poly1305
Message framing Cap'n Proto (unpacked wire format)

Features

Core

  • Interactive REPL — multi-conversation chat with auto-register, auto-login, slash commands, background polling, and message history
  • 1:1 DMs — dedicated channels with server-enforced membership authorization
  • Multi-party groups — N-member MLS groups with Commit fan-out and epoch sync
  • OPAQUE authentication — password-authenticated key exchange (password never leaves the client)
  • Encrypted local storage — SQLCipher database + encrypted session tokens (Argon2id + ChaCha20-Poly1305)
  • Persistent state — server and client survive restarts; SQLite/SQLCipher or file-backed storage
  • Self-DM notepad — send messages to yourself (local-only, no server round-trip)
  • Certificate pinning — pass the server cert as --ca-cert to trust only that server
  • Federation — server-to-server message relay via Cap'n Proto RPC over QUIC with mTLS
  • mDNS discovery — servers announce _quicproquo._udp.local.; clients auto-discover nearby nodes
  • Sealed sender mode — optional anonymous enqueue (sender identity inside MLS ciphertext only)
  • Prometheus metrics--metrics-listen exposes /metrics endpoint for monitoring
  • Dynamic plugin system — load .so/.dylib plugins at runtime via --plugin-dir
  • Safety numbers/verify <username> for out-of-band key verification (60-digit numeric code)
  • Transcript export — encrypted, tamper-evident message archives with hash-chain integrity verification
  • 20 CLI subcommandsregister-user, login, create-group, invite, join, send, recv, chat, repl, export, export-verify, and more

REPL slash commands

Command Description
/dm <username> Start a 1:1 DM with a peer
/create-group <name> (or /cg) Create a new group
/invite <username> Add a member to the current group
/remove <username> Remove a member from the current group
/join Join a pending group invitation
/leave Leave the current group
/switch @user or /switch #group Switch active conversation
/list or /ls List all conversations
/members Show group members
/history [count] (or /hist) Show message history (default 20)
/verify <username> Compare safety numbers with a peer
/update-key (or /rotate-key) Rotate your MLS key material
/mesh peers Scan for nearby qpq nodes via mDNS
/mesh server <host:port> Note a discovered server address
/whoami Show identity and group status
/help Command reference
/quit Exit

Experimental / proof-of-concept

  • Tauri 2 GUI (quicproquo-gui) — foundational desktop app shell; not feature-complete
  • Mobile FFI (quicproquo-mobile) — C API for QUIC connection migration (wifi to cellular)
  • P2P transport (quicproquo-p2p) — iroh-based direct peer-to-peer messaging with NAT traversal (feature-gated behind --features mesh)
  • Bot framework (quicproquo-bot) — programmable bot client

Quick start

# Prerequisites: Rust 1.77+, capnp CLI
brew install capnp          # macOS
# apt-get install capnproto # Debian/Ubuntu

# Build (excludes GUI — requires GTK system libs)
cargo build --bin qpq-server --bin qpq

# Run tests
cargo test --workspace --exclude quicproquo-gui

# Start the server (port 7000 by default, auto-generates self-signed cert)
cargo run --bin qpq-server -- --allow-insecure-auth

# Interactive REPL (auto-registers and logs in)
cargo run --bin qpq -- repl --username alice --password mypass

REPL quickstart (two terminals)

# Terminal 1
qpq repl --username alice --password secretA

# Terminal 2
qpq repl --username bob --password secretB

# In Alice's REPL:
/dm bob
Hello from Alice!

# Bob sees: [alice] Hello from Alice!

Server configuration (TOML)

cat > qpq-server.toml <<'EOF'
listen = "0.0.0.0:7000"
data_dir = "data"
tls_cert = "data/server-cert.der"
tls_key = "data/server-key.der"
auth_token = "your-strong-token-here"
store_backend = "sql"       # or "file"
db_path = "data/qpq.db"
db_key = "your-db-encryption-key"
metrics_listen = "0.0.0.0:9090"
metrics_enabled = true
# Federation (optional)
# federation_enabled = true
# federation_domain = "chat.example.com"
# federation_listen = "0.0.0.0:7001"
# Plugin loading (optional)
# plugin_dir = "/etc/qpq/plugins"
EOF
cargo run --bin qpq-server -- --config qpq-server.toml

Production: use a strong QPQ_AUTH_TOKEN, set QPQ_DB_KEY when using store_backend = "sql", and provide real TLS certificates (the server refuses to auto-generate certs in production mode).

See the full demo walkthrough for a step-by-step guide.


Crate layout

Crate Purpose
quicproquo-core MLS group operations, hybrid KEM, OPAQUE auth, crypto primitives
quicproquo-proto Cap'n Proto schemas and generated RPC code
quicproquo-server QUIC server, NodeService RPC, storage backends, federation, plugins
quicproquo-client CLI + REPL, session management, conversation store
quicproquo-plugin-api C-compatible plugin hook API (HookVTable)
quicproquo-kt Key transparency / Merkle-log identity bindings
quicproquo-bot Programmable bot client framework
quicproquo-gen Code generation utilities
quicproquo-gui Tauri 2 desktop app (experimental, requires GTK)
quicproquo-mobile C FFI for mobile connection migration (experimental)
quicproquo-p2p iroh-based P2P transport (feature-gated, --features mesh)

CI pipeline

GitHub Actions runs on every push and PR:

  • cargo fmt --check — formatting
  • cargo build --workspace — full build
  • cargo test --workspace — 103+ tests (core, server, client, E2E, doctests)
  • cargo clippy --workspace — lint
  • cargo deny check — license and advisory audit
  • cargo audit — vulnerability scan
  • cargo tarpaulin — code coverage (uploaded as artifact)
  • docker build — container image validation

Milestones

# Name Status What it adds
M1 QUIC/TLS transport Done QUIC + TLS 1.3 endpoint, length-prefixed framing, Ping/Pong
M2 Authentication Service Done Ed25519 identity, KeyPackage generation, AS upload/fetch
M3 Delivery Service + MLS groups Done DS relay, GroupMember create/join/add/send/recv
M4 Group CLI subcommands Done Persistent CLI, OPAQUE login, 20 subcommands
M5 Multi-party groups Done N > 2 members, Commit fan-out, send --all, epoch sync
M6 Persistence + REPL Done SQLite/SQLCipher, interactive REPL, DM channels, encrypted local storage
M7 Post-quantum MLS Planned Hybrid X25519 + ML-KEM-768 integrated into MLS ciphersuite

M7 note: the hybrid KEM envelope is already implemented and tested (10 tests passing). What remains is integrating it into the OpenMLS CryptoProvider so all MLS key material gets post-quantum confidentiality.


Roadmap

See ROADMAP.md for the full phased plan. Summary:

Phase Focus Status
1 Production hardening (unwrap removal, secure defaults, Docker) In progress
2 Test and CI maturity Partially done
3 Client SDKs (Go, Python, WASM, FFI, WebTransport) Planned
4 Trust and security (audit, key transparency, PQ MLS) Planned
5 Features and UX (multi-device, offline queue, file transfer) Planned
6 Scale and operations (horizontal scaling, observability) Planned
7 Platform expansion (mobile, web, federation, sealed sender) Planned
8 Freifunk / community mesh networking F0-F2 done
9 Developer experience and community growth Planned

Recently completed

  • Federation routing — server-to-server message relay with mTLS
  • mDNS discovery — servers advertise on local network, clients discover peers
  • P2P transport — iroh-based direct messaging re-included in workspace (--features mesh)
  • CI pipeline — fmt, build, test, clippy, deny, audit, coverage, Docker build
  • Plugin system — dynamic .so/.dylib loading with C-compatible hook API
  • Safety numbers — Signal-style 60-digit verification codes
  • Transcript export — encrypted, hash-chained message archives

Building without the GUI

The GUI crate requires GTK system libraries. To build just the server and client:

cargo build --bin qpq-server --bin qpq

To build the client with mesh/P2P support:

cargo build -p quicproquo-client --features mesh

Documentation

Full documentation is available as an mdBook in docs/:

cargo install mdbook     # once
mdbook serve docs        # http://localhost:3000

Security

This is a research project and has not undergone a formal third-party audit. See the threat model and security audit for details.

  • The server only routes opaque ciphertexts by recipient key — it never sees plaintext.
  • OPAQUE ensures passwords never leave the client.
  • Local databases are encrypted with SQLCipher when a password is provided.
  • Session tokens are encrypted at rest (Argon2id key derivation + ChaCha20-Poly1305).
  • Certificate pinning: pass the server cert as --ca-cert so the client trusts only that server.
  • Sealed sender: optional mode where the server cannot see who sent a message.
  • Dependency checks: CI runs cargo deny check and cargo audit on every PR.

License

MIT

Description
End-to-end encrypted messaging over QUIC + TLS 1.3 + MLS (RFC 9420), written in Rust.
Readme 6.9 MiB
Languages
Rust 86.4%
HTML 3.6%
Python 2.1%
TeX 1.9%
Shell 1.6%
Other 4.2%