Delivery sequence numbers (MLS epoch ordering fix):
- schemas/node.capnp: add Envelope{seq,data} struct; enqueue returns seq:UInt64;
fetch/fetchWait return List(Envelope) instead of List(Data)
- storage.rs: Store trait enqueue returns u64; fetch/fetch_limited return
Vec<(u64, Vec<u8>)>; FileBackedStore gains QueueMapV3 with per-inbox seq
counters and V2→V3 on-disk migration
- migrations/002_add_seq.sql: seq column, delivery_seq_counters table, index
- sql_store.rs: atomic UPSERT counter via RETURNING, ORDER BY seq, SCHEMA_VERSION→3
- node_service/delivery.rs: builds Envelope list; returns seq from enqueue
- client/rpc.rs: enqueue→u64, fetch_all/fetch_wait→Vec<(u64,Vec<u8>)>
- client/commands.rs: sort-by-seq before MLS processing; retry loop in cmd_recv
and receive_pending_plaintexts for correct epoch ordering
Server refactor:
- Split monolithic main.rs into node_service/{mod,delivery,auth_ops,key_ops,p2p_ops}
- Add auth.rs (token validation, rate limiting), config.rs, metrics.rs, tls.rs
- Add SQL migrations runner (001_initial.sql, 002_add_seq.sql)
- OPAQUE PAKE login/registration, sealed-sender mode, queue depth limit (1000)
Client refactor:
- Split lib.rs into client/{commands,rpc,state,retry,hex,mod}
- Add cmd_whoami, cmd_health, cmd_check_key, cmd_ping subcommands
- Add cmd_register_user, cmd_login (OPAQUE), cmd_refresh_keypackage
- Hybrid PQ envelope (X25519 + ML-KEM-768) on all send/recv paths
- E2E test suite expanded
Other:
- quicnprotochat-gui: Tauri 2 desktop GUI skeleton (backend + HTML UI)
- quicnprotochat-p2p: iroh-based P2P transport stub
- quicnprotochat-core: app_message, hybrid_crypto modules; GroupMember API updates
- .github/workflows/size-lint.yml: binary size regression check
- docs: protocol comparison, roadmap updates, fully-operational checklist
6.7 KiB
Milestone Tracker
This page tracks the project milestones for quicnprotochat, from initial transport layer through post-quantum cryptography. Each milestone produces production-ready, tested, deployable code -- see Coding Standards for what that means in practice.
Milestone Summary
| # | Name | Status | What it adds |
|---|---|---|---|
| M1 | QUIC/TLS Transport | Complete | QUIC + TLS 1.3 endpoint, length-prefixed framing, Ping/Pong |
| M2 | Authentication Service | Complete | Ed25519 identity, KeyPackage generation, AS upload/fetch |
| M3 | Delivery Service + MLS Groups | Complete | DS relay, GroupMember create/join/add/send/recv |
| M4 | Group CLI Subcommands | Complete | Persistent CLI (create-group, invite, join, send, recv), OPAQUE login |
| M5 | Multi-party Groups | Complete | N > 2 members, Commit fan-out, send --all, epoch sync |
| M6 | Persistence | Complete | SQLite/SQLCipher, migrations, durable server + client state |
| M7 | Post-quantum | Next | PQ hybrid for MLS/HPKE (X25519 + ML-KEM-768) |
M1 -- QUIC/TLS Transport (Complete)
Goal: Two processes establish a QUIC connection over TLS 1.3 and exchange typed Cap'n Proto frames.
Deliverables:
schemas/envelope.capnp:Envelopestruct withMsgTypeenum (Ping/Pong at this stage)quicnprotochat-proto:build.rsinvokingcapnpc, generated type re-exports, canonical serialisation helpersquicnprotochat-core: Ed25519 identity keypair generation, Cap'n Proto frame codec (TokioEncoder/Decoder)quicnprotochat-server: QUIC listener with TLS 1.3 (quinn/rustls), Ping to Pong handler, one tokio task per connectionquicnprotochat-client: connects over QUIC, sends Ping, receives Pong, exits 0- Integration test: server and client in same test binary using
tokio::spawn docker-compose.ymlrunning the server
Tests: codec (7 unit tests), keypair (3 unit tests), QUIC transport integration.
Branch: feat/m1-noise-transport
M2 -- Authentication Service (Complete)
Goal: Clients register an Ed25519 identity and publish/fetch MLS KeyPackages via Cap'n Proto RPC.
Deliverables:
schemas/auth.capnp:AuthenticationServiceinterface (uploadKeyPackage,fetchKeyPackage)quicnprotochat-core: Ed25519 identity keypair generation, MLS KeyPackage generation viaopenmlsquicnprotochat-server: AS RPC server withDashMapstore, atomic consume-on-fetchquicnprotochat-client:register-stateandfetch-keyCLI subcommands- Integration test: Alice uploads KeyPackage, Bob fetches it, fingerprints match
Tests: auth_service.rs integration tests (upload, fetch, consume semantics).
M3 -- Delivery Service + MLS Groups (Complete)
Goal: Alice creates a group and adds Bob via MLS Welcome. Both exchange encrypted application messages through the Delivery Service.
Deliverables:
- Unified
NodeServiceon port 7000 combining Authentication Service and Delivery Service into a single Cap'n Proto RPC interface GroupMemberstruct with full MLS lifecycle:create_group,add_member,join_from_welcome,send_message,receive_message- DS relay with
enqueue,fetch, andfetchWait(long-polling) operations demo-groupsubcommand exercising the complete Alice/Bob flow in one process- Channel-aware delivery: messages routed by
(channelId, recipientKey)
Tests: All passing -- codec (5+ tests), keypair (3 tests), group round-trip, group_id lifecycle, MLS integration.
Key design decisions from M3:
-
OpenMlsRustCrypto backend holds the HPKE init key in memory. The same
GroupMemberinstance that generated the KeyPackage must process the corresponding Welcome. If the process exits in between, the init private key is lost. This is by design for M3; persistence comes at M6. -
KeyPackage wire format: raw TLS-encoded bytes. KeyPackages are serialised using
tls_serialize_detached()rather than wrapped inMlsMessageOut. This avoids an extra layer of indirection and matches whatopenmlsexpects on the receive side viaKeyPackageIn::tls_deserialize_exact(). -
openmls 0.5 API gotchas. Several
openmlsmethods changed signatures between 0.4 and 0.5 (e.g.,MlsGroup::newvsMlsGroup::new_with_group_id,BasicCredential::newtakingVec<u8>directly). These differences are documented inline inquicnprotochat-core/src/group.rs.
Branch: feat/m1-noise-transport
M4 -- Group CLI Subcommands (Complete)
Goal: Persistent, composable CLI subcommands for group operations, replacing
the monolithic demo-group proof-of-concept.
Deliverables: create-group, invite, join, send, recv, chat;
OPAQUE register-user and login; demo-group remains for single-command demo.
M5 -- Multi-party Groups (Complete)
Goal: Support groups with N > 2 members, including Commit fan-out and epoch synchronisation.
Deliverables: Commit fan-out to existing members on invite; send --all;
cmd_join processes all queued payloads (Welcome + Commits); three-party E2E
passing. Proposal handling (Remove, Update) and Criterion benchmarks are
optional follow-ups.
M6 -- Persistence (Complete)
Goal: Server survives restart. Client state persists across sessions.
Deliverables: SQLite/SQLCipher via rusqlite, migrations/ directory and
migration runner; client state file and DiskKeyStore (encrypted QPCE optional).
See Future Research: SQLCipher for
encrypted-at-rest options.
M7 -- Post-quantum (Next)
Goal: Replace the MLS crypto backend with a hybrid X25519 + ML-KEM-768 KEM, providing post-quantum confidentiality for all group key material.
Deliverables:
-
Custom
OpenMlsCryptoProviderwith hybrid KEM inquicnprotochat-core -
Hybrid shared secret derivation:
SharedSecret = HKDF-SHA256( ikm = X25519_ss || ML-KEM-768_ss, info = "quicnprotochat-hybrid-v1", len = 32 ) -
All M3/M4/M5 tests pass unchanged with the new ciphersuite
-
Follows the combiner approach from
draft-ietf-tls-hybrid-design
The ml-kem crate is already vendored in the workspace. See
Hybrid KEM for the detailed design.
Cross-references
- Production Readiness WBS -- phased work breakdown for hardening beyond the milestone track
- Auth, Devices, and Tokens -- authentication and authorisation design that cuts across M4--M6
- 1:1 Channel Design -- DM channel schema and authz model
- Future Research -- technology options for M6+ and beyond
- Testing Strategy -- how tests are structured across milestones