# Multi-Agent Work Plan: Sections 1 (Security) + 5 (Features) This document splits work for **Future Improvements §1 (Security and hardening)** and **§5 (Features and product)** between two agents so they can work in parallel with minimal merge conflicts. --- ## Agent A: Security and hardening **Owns:** Server auth/OPAQUE, TLS config, core crypto (identity, keypackage, hybrid_kem), docs under `docs/src/cryptography/` and TLS/cert docs. ### A1. 1.2 CA-signed TLS / certificate lifecycle - **Files:** `docs/src/getting-started/` (new or existing), `crates/quicproquo-server/src/tls.rs` (optional env), `README.md`. - **Tasks:** 1. Add **Certificate lifecycle** doc: using CA-issued certs (e.g. Let's Encrypt), cert rotation, OCSP/CRL optional. Recommend pinning for single-server. 2. Optional: server config or env to prefer CA-signed cert path (e.g. `QPQ_USE_CA_CERT=1` and read from a different path). Low priority if docs suffice. - **Deliverable:** `docs/src/getting-started/certificate-lifecycle.md` (or section in running-the-server) + README link. ### A2. 1.4 Username enumeration (OPAQUE) - **Files:** `crates/quicproquo-server/src/node_service/auth_ops.rs`, `docs/SECURITY-AUDIT.md`. - **Tasks:** 1. Document the risk in SECURITY-AUDIT (already mentioned). 2. Optional mitigation: ensure `get_user_record` is always called before `ServerLogin::start` (already true). If desired, add a constant-time delay or dummy work when user not found so response timing does not leak existence. Keep OPAQUE security unchanged. - **Deliverable:** Doc update; optional small code change in `handle_opaque_login_start`. ### A3. 1.1 M7 — Post-quantum MLS - **Files:** `crates/quicproquo-core/src/` (new or modified crypto provider), `crates/quicproquo-core/src/group.rs`, `crates/quicproquo-core/src/hybrid_kem.rs`, `crates/quicproquo-core/src/hybrid_crypto.rs`. - **Tasks:** 1. Implement a custom `OpenMlsCryptoProvider` (or adapter) that uses hybrid X25519 + ML-KEM-768 for MLS KEM (HPKE layer). 2. Wire hybrid shared secret derivation (see milestones M7) into the provider. 3. Run full test suite; ensure M3/M4/M5 tests pass. - **Deliverable:** Hybrid KEM in MLS path; tests green. Large change; coordinate with core crate. ### A4. 1.3 Stronger credential binding - **Files:** Docs only for now. - **Tasks:** Add a short **Future research** subsection or ADR: X.509-based MLS credentials, or Key Transparency for public key binding. No code change in this round. - **Deliverable:** `docs/src/roadmap/future-research.md` or ADR update. --- ## Agent B: Features and product **Owns:** Cap'n Proto schema (node.capnp delivery/channel methods), server storage (Store trait, FileBackedStore, SqlStore), `node_service/delivery.rs`, `node_service/key_ops.rs` (if createChannel lives there), client commands for channels. ### B1. 5.1 Private 1:1 channels (DM) - **Files:** `schemas/node.capnp`, `crates/quicproquo-server/src/storage.rs`, `crates/quicproquo-server/src/sql_store.rs`, `crates/quicproquo-server/src/node_service/delivery.rs`, new `crates/quicproquo-server/src/node_service/channel_ops.rs` (or add to delivery), migrations for channels table. - **Tasks:** 1. **Schema:** Add `createChannel @N (auth :Auth, peerKey :Data) -> (channelId :Data);` to `node.capnp`. Rebuild proto. 2. **Store trait:** Add `create_channel(&self, member_a: &[u8], member_b: &[u8]) -> Result, StorageError>`, `get_channel_members(&self, channel_id: &[u8]) -> Result, Vec)>, StorageError>`. Implement in FileBackedStore (in-memory map channel_id -> (a, b)) and SqlStore (channels table, unique on sorted (a,b)). 3. **Server:** Implement `handle_create_channel`: auth required, identity required; create channel with (caller_identity, peer_key); return 16-byte channel_id (e.g. UUID). 4. **Delivery authz:** When `channel_id.len() == 16`: call `get_channel_members`. If Some((a, b)), verify caller identity is one of a/b and recipient_key is the other. If channel not found or authz fails, return E022 (or new code). Legacy: `channel_id` empty = current behaviour (no channel check). 5. **Config:** Optional server flag to require channel authz for non-empty channel_id (default on). - **Deliverable:** createChannel RPC, channel storage, per-channel authz on enqueue/fetch/fetchWait; legacy mode when channel_id empty. - **Ref:** [DM channels design](src/roadmap/dm-channels.md). ### B2. 5.2 MLS lifecycle (remove, update, proposals) - **Files:** `crates/quicproquo-core/src/group.rs`, client commands that use GroupMember. - **Tasks:** 1. Add `remove_member` (by index or identity) and `update_credential` / rekey using openmls APIs. 2. Handle incoming MLS proposals (Remove, Update) in `receive_message` path and apply to group state. 3. CLI: `remove` and `update` subcommands or options. - **Deliverable:** Members can be removed and credentials updated; proposals handled; CLI exposed. - **Ref:** OpenMLS API for `MlsGroup::remove_member`, `MlsGroup::process_pending_proposals`, etc. ### B3. 5.3 Sealed Sender and 5.4 Traffic analysis - **Files:** Docs; optionally `crates/quicproquo-server`, `crates/quicproquo-client` for padding. - **Tasks:** 1. Document current `sealed_sender` behaviour (enqueue without identity binding) and that full “sender in ciphertext” is a future protocol change. 2. Optional: add optional payload padding (e.g. pad to next 256 bytes) or random delay in client send path for 5.4. - **Deliverable:** Doc update; optional padding/behaviour. --- ## File ownership (avoid conflicts) | Area | Agent A | Agent B | |------|---------|---------| | `schemas/node.capnp` | — | Add createChannel | | `crates/quicproquo-server/src/node_service/auth_ops.rs` | 1.4 username enum | — | | `crates/quicproquo-server/src/node_service/delivery.rs` | — | 5.1 channel authz | | `crates/quicproquo-server/src/storage.rs` | — | 5.1 Store channel methods | | `crates/quicproquo-server/src/sql_store.rs` | — | 5.1 channels table + impl | | `crates/quicproquo-server/src/tls.rs` | 1.2 optional | — | | `crates/quicproquo-core/` | 1.1 M7, 1.3 doc | 5.2 group.rs | | `docs/` | 1.2, 1.3, 1.4, 5.3/5.4 | — (or shared) | **Shared:** `docs/`, `README.md`. Prefer non-overlapping files (e.g. A adds `certificate-lifecycle.md`, B does not edit it). --- ## Order of operations (recommended) 1. **Both:** Sync on schema and Store trait changes so B adds `createChannel` and channel methods without A touching the same trait. 2. **Agent A:** Ship A1 (CA/TLS docs) and A2 (1.4 doc + optional code) first; then A3 (M7) in a follow-up PR/batch. 3. **Agent B:** Ship B1 (createChannel + channel authz) first; then B2 (MLS remove/update); then B3/B4 (docs/padding). --- ## Completion checklist - [ ] A1: CA-signed TLS / certificate lifecycle doc - [ ] A2: Username enumeration doc and/or mitigation - [ ] A3: M7 hybrid KEM in MLS provider - [ ] A4: 1.3 credential binding (docs) - [ ] B1: createChannel RPC + channel storage + delivery authz - [ ] B2: MLS remove/update and proposal handling - [ ] B3/B4: Sealed Sender and traffic analysis (docs + optional padding)