# Phase 2 (Protocol Hardening) + M4–M6 Roadmap

This page tracks implementation of **Phase 2** (protocol hardening) from the
[Production Readiness WBS](production-readiness.md), followed by **M4** (Group CLI),
**M5** (Multi-party groups), and **M6** (Persistence).

---

## Legacy code removed

The following legacy behaviour has been removed; only current behaviour is supported:

- **Auth:** Server no longer accepts "any non-empty token" when no static token is configured. Either a static `auth_token` or a valid OPAQUE session token is required (auth version 1 only).
- **Wire version:** Only wire version `1` is accepted on `enqueue`, `fetch`, `fetchWait`. Version `0` is rejected.
- **Delivery storage:** Server only loads the channel-aware delivery map format (v2). Old v1 `deliveries.bin` files will not load; delete or migrate the file.
- **Client:** Hybrid decryption is required for Welcome and application payloads. No fallback to plaintext MLS; missing or failed hybrid decrypt returns an error.

---

## Phase 2 — Protocols and Core Hardening

| Task | Status | Notes |
|------|--------|-------|
| **Ciphersuite allowlist** | **Done** | Server rejects KeyPackages whose ciphersuite is not `MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519`. See `quicproquo_core::validate_keypackage_ciphersuite` and `upload_key_package` (E021). |
| **ALPN enforcement** | **Done** | Server TLS config sets `alpn_protocols = [b"capnp"]`; handshake completes only if client offers `capnp`. |
| **Connection draining** | **Done** | On `Ctrl+C`, server calls `endpoint.close(0, b"server shutdown")` and exits the accept loop. |
| **Wire versioning** | **Done** | `enqueue`, `fetch`, `fetchWait` require `version == CURRENT_WIRE_VERSION` (1). Other RPCs use auth version. |
| **Downgrade guards** | **Deferred** | MLS epoch/ciphersuite consistency is enforced by openmls when processing commits. Explicit epoch-rollback checks can be added in M5. |
| **KeyPackage rotation** | **Doc** | Clients should upload a fresh KeyPackage before the 24h TTL. Helper or background task can be added in M4. |

---

## M4 — Group CLI Subcommands

**Goal:** Persistent, composable CLI for group operations (replace monolithic `demo-group`).

| Deliverable | Status |
|-------------|--------|
| `create-group` | Planned |
| `invite <identity>` | Planned |
| `join` | Planned |
| `send <message>` | Planned |
| `recv` | Planned |
| Keep `demo-group` | Existing |

See [Milestones](milestones.md#m4--group-cli-subcommands-next).

---

## M5 — Multi-party Groups

**Goal:** N > 2 members, commit fan-out, proposal handling.

| Deliverable | Status |
|-------------|--------|
| Commit fan-out via DS | Planned |
| Proposal handling (Add, Remove, Update) | Planned |
| Epoch sync across N members | Planned |
| Benchmarks | Planned |

---

## M6 — Persistence

**Goal:** Server survives restart; client state persists across sessions.

| Deliverable | Status |
|-------------|--------|
| SQLite/SQLCipher (AS + DS) | Partial (SqlStore exists) |
| `migrations/` | Planned |
| Client reconnect + session resume | Planned |
| Docker + healthcheck | Partial (Dockerfile exists) |

---

## Cross-references

- [Production Readiness WBS](production-readiness.md) — Phase 2 definition
- [Milestones](milestones.md) — M4, M5, M6 details
- [Auth, Devices, and Tokens](authz-plan.md) — Phase 3
