summaryrefslogtreecommitdiffstats
path: root/devel-phases-next.md
blob: f4793dfbc526c9018fb35b40ffc27048932efbc7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# MeshBay — Next Implementation Phases

> Base: Phases 1-6 complete. demo-v2 NAT QUIC validated.
> Architecture reference: docs/meshbay-draft-v3.md
> First security review: first-review.md (2026-08-10)

---

## Phase 7 — Node v2 : production, streaming, chat

**Objective:** a node usable for daily operations — multi-group, smooth streaming,
integrated chat, fast reconnection.

### Prerequisites (from first security review, 2026-08-10)

Before writing Phase 7 production code, two critical design gaps must be
addressed — see `first-review.md` for full analysis:

1. **[C2] JWT must carry group membership claims.** Add `"groups": [group_ids]`
   to `issue_access_token()`. Node MNP handshake must verify the requested
   group_id is in the JWT's groups claim before serving any content. Without
   this, any authenticated user can access any group on the node.
   → Implement in 7.3 (multi-group daemon) before any other milestone.

2. **[C1] Chat encryption: Sender Keys, not shared Double Ratchet.** The Double
   Ratchet is a pairwise (1:1) protocol — sharing a single ratchet state across
   N group members causes key/nonce reuse (AEAD catastrophic failure). The
   architecture now uses **Sender Keys** (Signal Groups approach): each member
   has their own sending chain key, O(N) state.
   → Implement in 7.5. The existing `ratchet.py` is kept for future 1:1 DM.

### Architectural decisions (settled)

**Multi-group → multiplexing on a single QUIC port**
A node exposes a single QUIC port (e.g. 19010). All hosted groups share this
port. The group is identified in the MNP handshake by the `group_id` in the
JWT. Advantages: one NAT hole to maintain, one manual port forward if needed.
The QUIC server routes each connection to the appropriate IndexGroup/GEK
after JWT verification **and group membership authorization check**.

**Signaling punch/connect (via hub WebSocket)**
Currently the node punches blindly at startup → 12.7s handshake (NAT hole ages
before the client arrives). Solution:
```
Client → Hub (HTTPS) : "I'm about to connect to node X, I'm at IP:PORT"
Hub → Node  (WS)     : message "client_incoming: {peer_ip, peer_port}"
Node → NAT  (UDP)    : punch_nat(peer_ip, peer_port) immediately
Node → Hub  (WS)     : "punch_ready"
Hub → Client (HTTPS) : "connect now"
Client → Node (QUIC) : < 2s after probe → fresh NAT entry → < 200ms
```
The hub→node WebSocket channel already exists (`hub/api/revocation.py`).
Just add `client_incoming` / `punch_ready` message types.
This mechanism is a simplified ICE (Interactive Connectivity Establishment).

The same WebSocket channel also carries **jti denylist push** (security review
S3): when the hub revokes a token, it pushes the jti to all connected nodes.
Nodes maintain an in-memory set and check it during MNP handshake.

**Chat — between a forum and Signal**
Not a real-time ephemeral chat (Signal) nor a heavy forum.
Model: **E2E encrypted discussion thread, persisted on the node**.
- Short messages + attachments (like Signal group)
- Optional threads/topics for structure (like a light forum)
- History stored on the node (not ephemeral)
- Push for connected members, pull for offline
- **Sender Keys** protocol for encryption (security review C1 — Double Ratchet
  is pairwise only, cannot be shared across group members)
- Scope: per group (not per user pair)
- No automatic deletion (group admin manages retention)

### Milestones

| # | Component | File(s) | Priority |
|---|---|---|---|
| 7.0 | JWT group claims + node authz check | `hub/auth.py` + `node/transport/quic_server.py` | **Blocker** |
| 7.1 | QUIC 0-RTT session resumption | `transport/quic_server.py` + `quic_client.py` | High |
| 7.2 | Signaling `client_incoming`/`punch_ready` + jti denylist push | `hub/api/revocation.py` + `node/hub_client.py` | High |
| 7.3 | Multi-group daemon (1-port multiplexing) | `node/daemon.py` — N IndexGroups, 1 QuicChunkServer | High |
| 7.4 | HLS streaming via QUIC | `node/transport/hls.py` — segments as QUIC streams | Medium |
| 7.5 | Chat: Sender Keys protocol + storage + MNP wire | `common/senderkeys.py` + `node/chat/store.py` | Medium |
| 7.6 | Chat: local web UI + WS push to members | `node/ui/app.py` WebSocket for notifications | Medium |
| 7.7 | Argon2id calibration CLI | `node/daemon.py` — `meshbay-node calibrate-argon2` | Low |

**Remaining open questions:**
- Do groups on the same node share the node's Ed25519 key? (likely yes)
- Multi-group UI at localhost:18000: tabs per group or unified list?

---

## Phase 8 — Hub v2: admin, federation, production security

**Objective:** hub ready for public operation — admin roles, MHP network,
CSAM integrated, monitoring.

| # | Component | File(s) | Priority |
|---|---|---|---|
| 8.1 | Admin roles (hub_admin flag on User) + authz on revocation | `hub/db/models.py` + `hub/api/admin.py` + `hub/api/revocation.py` | **High — S1** |
| 8.2 | Email encryption at rest | `hub/db/models.py` — AES-256-GCM with config-derived key | **High — S2** |
| 8.3 | Refresh token rotation (one-time use) | `hub/api/users.py` — rotate on each use, detect reuse | **High — S5** |
| 8.4 | MHP inter-hub network (not just in-memory) | `hub/api/federation.py` + Alembic migration | High |
| 8.5 | federated_groups DB persistence | `hub/db/models.py` FederatedGroup already defined | High |
| 8.6 | CSAM real DB (import NCMEC/IWF) | `hub/csam.py` — import CLI + API update | High |
| 8.7 | Rate limiting on all authenticated endpoints | `hub/api/middleware.py` — extend slowapi | Medium — M3 |
| 8.8 | Metrics / healthcheck | `hub/api/health.py` | Medium |
| 8.9 | Cleanup IP logs (purge > 1 year) | `hub/tasks/cleanup.py` — APScheduler | Medium |
| 8.10 | Alembic migration Argon2id params | Bump migration + `hub/auth.py` | Low |

Items 8.1-8.3 are from the first security review (S1, S2, S5).

**Questions to clarify:**
- Who can be hub_admin? First registered user? Config toml?
- MHP: inter-hub authentication via JWT or mutual TLS?

---

## Phase 9 — Android client MVP

**Objectif :** app Android permettant de créer un compte, rejoindre un groupe,
télécharger des fichiers depuis un node.

**Stack technique à décider :**
- **Kotlin natif** : plus de contrôle, accès direct aux APIs Android (WebRTC, QUIC via fork)
- **Flutter** : cross-platform (iOS futur), Dart, mais bindings aioquic inexistants
- **React Native** : JS, même problème de bindings natifs QUIC

**Recommandation :** Kotlin natif. La partie critique (QUIC/UDP + crypto) est en C/Rust via
des bindings JNI. La couche UI peut être Jetpack Compose.

| # | Composant | Tech | Priorité |
|---|---|---|---|
| 9.1 | Hub client (auth, groups, GEK) | Kotlin + Retrofit | Haute |
| 9.2 | Crypto (Ed25519, X25519, ChaCha20) | Bouncy Castle JVM | Haute |
| 9.3 | QUIC client | quiche (Cloudflare, Rust JNI) ou QUIC4J | Haute |
| 9.4 | NAT traversal (STUN + punch) | Kotlin native UDP | Haute |
| 9.5 | File browser + download | Kotlin + streaming IO | Haute |
| 9.6 | Chat UI | Jetpack Compose | Moyenne |
| 9.7 | Node UI pairing (QR code) | Android camera + hub API | Moyenne |

**Préalable à clarifier :** quels bindings QUIC existent sur Android ?
`quiche` de Cloudflare (en Rust, JNI) est le plus mature.

---

## Phase 10 — Web client v2 : groupes privés + streaming

**Objectif :** navigateur peut décoder le contenu privé (AES-GCM) et streamer des vidéos.

| # | Composant | Fichier(s) | Priorité |
|---|---|---|---|
| 10.1 | Web client : décryptage privé (AES-GCM + SubtleCrypto) | `static/crypto.js` MeshBayCrypto | Haute |
| 10.2 | Web client : groupe-type "browser" (AES-GCM GEK) | Hub : `cipher` field sur Group | Haute |
| 10.3 | Player HLS dans browser (hls.js + déchiffrement) | `static/app.js` + hls.js | Haute |
| 10.4 | Chat browser (Sender Keys JS — AES-GCM via SubtleCrypto) | `static/senderkeys.js` | Moyenne |
| 10.5 | PWA / Service Worker | offline + cache | Basse |

**Question clé :** pour le streaming privé en browser, deux approches :
- **AES-GCM GEK** (actuel) : browser-native mais nécessite un groupe dédié
- **ChaCha20 via WASM** : même GEK que les clients natifs, plus complexe

---

## Phase 11 — Résilience réseau : TURN relay, 0-RTT, CGNAT

**Objectif :** fonctionner même derrière les NAT les plus restrictifs (mobile 4G/5G CGNAT).

| # | Composant | Notes | Priorité |
|---|---|---|---|
| 11.1 | Mesh Relay TURN server | Node Python serveur UDP relay chiffré | Haute |
| 11.2 | Relay registration MHP | Hub : `/v1/relays/` + annonce aux nodes | Haute |
| 11.3 | Node : fallback automatique → relay | Après échec STUN dans discover_nat() | Haute |
| 11.4 | Punch coordination signaling | Hub WS → node punch → client connect < 2s | Haute |
| 11.5 | QUIC 0-RTT (aioquic session tickets) | Node stocke ticket → reconnexion < 50ms | Moyenne |
| 11.6 | Test CGNAT mobile 4G | Spike dédié : node mobile → node fixe | Moyenne |
| 11.7 | Connection pool (1 QUIC conn = N requêtes) | Node : réutilisation de stream par user | Moyenne |

---

## Phase 12 — RPM/DEB packaging production + CI

**Objectif :** packages installables, CI qui tourne les tests, releases signées.

| # | Composant | Notes |
|---|---|---|
| 12.1 | RPM build pipeline (Fedora, RHEL) | rpmbuild + spec files déjà écrits |
| 12.2 | DEB build pipeline (Ubuntu, Debian) | dpkg-deb + control déjà écrits |
| 12.3 | GitHub Actions CI | pytest + ruff sur PR |
| 12.4 | Release signing | GPG key pour les packages |
| 12.5 | Repo apt/dnf auto-hébergé | meshbay.org/packages/ |

---

## Ordre recommandé

```
Phase 7 (Node v2)     ← débloque l'usage réel au quotidien
Phase 8 (Hub v2)      ← stabilisation, admin, CSAM
Phase 11 (Relay+0-RTT)← résout le handshake 12.7s et CGNAT mobile
Phase 9 (Android)     ← client mobile, long chantier
Phase 10 (Web v2)     ← streaming privé browser
Phase 12 (Packaging)  ← distribution
```

**Next structural decisions (all resolved — see first-review.md):**
1. Multi-group on a single QUIC port ✅ (decided Phase 7)
2. Signaling punch/connect via existing hub WS ✅ (decided Phase 7)
3. Chat is a core feature, not a module ✅ (decided draft v3)
4. Chat encryption: Sender Keys ✅ (decided in security review)
5. JWT group claims required ✅ (decided in security review)