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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
# MeshBay — Development Phases
> Reference: architecture spec in `docs/meshbay-draft-v3.md`
> POC results: `poc/spike-results.md`
---
## Phase 1 — Foundations ✅ DONE
**Goal:** validate all blocking concepts before writing production code.
### Deliverables
| Item | Status | Notes |
|---|---|---|
| POC Spike 1 — Crypto primitives | ✅ | All 22 tests pass. ChaCha20 1MB in 1.1ms. |
| POC Spike 2 — Hub skeleton | ✅ | 12/12 endpoints. JWT EdDSA offline verify in 884µs. |
| POC Spike 3 — Node registration | ✅ | Full handshake. jti bug found and fixed. |
| POC Spike 4 — NAT traversal | ✅ | Cone NAT on SFR. UDP P2P works. UPnP disabled (SFR). |
| POC Spike 5 — Encrypted transfer | ✅ | 1MB P2P. 3.2ms encrypt, 3.9ms decrypt. 4.3MB/s. |
| POC Spike 6 — GEK distribution | ✅ | X25519+HKDF wrap/unwrap. 0.48ms/0.59ms. Hub opaque. |
| Security cleanup meshbay.org | ✅ | UFW: 22/80/443 only. No services exposed. |
| Git monorepo | ✅ | 3 packages: meshbay-common, meshbay-hub, meshbay-node. |
| Draft v3 | ✅ | POC findings integrated. All corrections applied. |
| CLAUDE.md conventions | ✅ | Python 3.12+, uv, ruff, SemVer, commit format. |
### Key findings from POC
- jti mandatory in all JWTs (Ed25519 is deterministic — same payload = same token)
- Argon2id at 64MB/3iter = 78ms — increase to 256MB for production (~500ms target)
- NAT order: STUN/hole-punching is priority 2, not UPnP (UPnP disabled on tested SFR box)
- TCP+TLS for v1 transport; QUIC in v2
- GEK wrapping: ephemeral X25519 + HKDF(salt=pk_eph) + ChaCha20-Poly1305(aad=pk_recipient)
---
## Phase 2 — Node v1 ✅ DONE
**Goal:** working Mesh Node: indexes a directory, registers with hub,
serves encrypted chunks over TCP+TLS, local web UI on localhost:18000.
**Transport:** TCP+TLS 1.3 (QUIC in v2). Self-signed cert per node.
Node identity verified via Ed25519 PK from hub, not TLS cert chain (client uses CERT_NONE).
### Milestones
| # | Component | File(s) | Tests |
|---|---|---|---|
| 2.1 | Keystore | `meshbay_node/keystore.py` | 10/10 |
| 2.2 | Hub client | `meshbay_node/hub_client.py` | 6/6 |
| 2.3 | Directory indexer | `meshbay_node/indexer/indexer.py` | 5/5 |
| 2.4 | Mesh Group Index | `meshbay_node/indexer/group_index.py` | 5/5 |
| 2.5 | TCP+TLS chunk server | `meshbay_node/transport/server.py` | 3/3 |
| 2.6 | TCP+TLS chunk client | `meshbay_node/transport/client.py` | included above |
| 2.7 | TLS cert helper | `meshbay_node/transport/tls_cert.py` | — |
| 2.8 | Config (TOML + env) | `meshbay_node/config.py` | — |
| 2.9 | Local web UI | `meshbay_node/ui/app.py` | — |
| 2.10 | Daemon + CLI | `meshbay_node/daemon.py` | — |
**Total: 29/29 tests passing**
### Python dependencies (dev venv — `/home/cbesson/meshbay/.venv`)
Installed packages (freeze) as of Phase 2 completion:
```
aioice==0.10.2 # ICE/STUN for NAT traversal
blake3==1.0.9 # fast content hashing
cryptography==50.0.0 # Ed25519, X25519, ChaCha20, Argon2id, AES-GCM
fastapi==0.141.1 # local web UI + hub POC
httpx==0.28.1 # hub client HTTP
meshbay-common==0.1.0 # editable install
meshbay-node==0.1.0 # editable install
msgpack==1.2.1 # wire serialisation
PyJWT==2.13.0 # JWT EdDSA
pytest==9.1.1 # test runner
pytest-asyncio==1.4.0 # async test support
uvicorn==0.52.1 # ASGI server (local UI)
watchdog==6.0.0 # filesystem watcher
zstandard==0.25.0 # zstd compression
```
Also installed transitively: pydantic 2.13.4, starlette 1.6.0, anyio 4.14.2, uvloop 0.22.1.
### meshbay_common/crypto.py — Argon2id NOTE
Current params: `iterations=3, memory_cost=65536` (64MB) → ~78ms on dev laptop.
**Must increase to `memory_cost=262144` (256MB) before production keystore use.**
Run `meshbay-node calibrate-argon2` on target hardware to tune.
### Out of scope for Phase 2
Multiple groups, chat, QUIC, module sandbox, mobile pairing, HLS streaming.
---
## Phase 3 — Hub v1 production ✅ DONE
**Goal:** replace POC in-memory hub with a production-ready service on meshbay.org.
PostgreSQL persistence, HTTPS via Caddy, all endpoints hardened, legal IP logging, deploy.
### Environment
- **Server:** meshbay.org — Ubuntu 26.04 LTS, Python 3.14.4, OVH VPS
- **Database:** PostgreSQL 16 (to install)
- **Proxy:** Caddy (to install — handles Let's Encrypt automatically)
- **Service:** systemd `meshbay-hub.service`
### Python dependencies to add (Phase 3)
```
sqlalchemy>=2.0 # async ORM (SQLAlchemy 2.x)
alembic>=1.13 # DB migrations
asyncpg>=0.30 # PostgreSQL async driver
aiosqlite>=0.20 # SQLite async driver (tests only)
slowapi>=0.1 # rate limiting (FastAPI middleware)
```
### Milestones
| # | Component | File(s) | Status |
|---|---|---|---|
| 3.1 | DB models | `meshbay_hub/db/models.py` | ✅ |
| 3.2 | DB engine + session | `meshbay_hub/db/engine.py` | ✅ |
| 3.3 | Alembic migrations | `meshbay_hub/db/migrations/` | ✅ initial_schema |
| 3.4 | Hub config | `meshbay_hub/config.py` | ✅ |
| 3.5 | Auth (JWT + Argon2id) | `meshbay_hub/auth.py` | ✅ |
| 3.6 | API deps | `meshbay_hub/api/deps.py` | ✅ |
| 3.7 | Hub info router | `meshbay_hub/api/hub.py` | ✅ |
| 3.8 | Users router | `meshbay_hub/api/users.py` | ✅ |
| 3.9 | Nodes router | `meshbay_hub/api/nodes.py` | ✅ |
| 3.10 | Groups router | `meshbay_hub/api/groups.py` | ✅ |
| 3.11 | Rate limiting | `meshbay_hub/api/middleware.py` | ✅ slowapi |
| 3.12 | App factory + lifespan | `meshbay_hub/app.py` | ✅ |
| 3.13 | Hub daemon CLI | `meshbay_hub/daemon.py` | ✅ |
| 3.14 | PostgreSQL 16 | meshbay.org | ✅ DB: meshbay_hub |
| 3.15 | Caddy + Let's Encrypt | meshbay.org Caddyfile | ✅ HTTPS auto-cert |
| 3.16 | Systemd service | `/etc/systemd/system/meshbay-hub.service` | ✅ |
| 3.17 | Deploy + smoke test | https://meshbay.org | ✅ 11/11 endpoints |
**Total: 40 local tests (SQLite) + 11/11 smoke tests HTTPS production**
### Phase 3 deployment details (meshbay.org)
- PostgreSQL 16, user `meshbay`, DB `meshbay_hub`
- Caddy auto-handles Let's Encrypt for `meshbay.org` and `www.meshbay.org`
- `www.meshbay.org` → 301 redirect → `meshbay.org`
- TLS setup documented in `docs/HTTPS.md`
- Hub listens on `127.0.0.1:8000`, Caddy proxies 80/443
- Systemd service: `meshbay-hub.service` (restart-on-failure)
- Hub config: `~/.config/meshbay/hub.toml`
- Hub keypair: `~/.config/meshbay/hub_private.pem` (chmod 600)
- Source deployed at: `~/meshbay-hub/` (common_pkg + hub_pkg)
### Additional Python dependencies added in Phase 3
```
sqlalchemy==2.0.51 # async ORM
alembic==1.19.1 # DB migrations
asyncpg==0.31.0 # PostgreSQL async driver
aiosqlite # SQLite async (tests only)
slowapi==0.1.10 # rate limiting
hatchling==1.31.0 # build backend (needed for pip install)
```
### Notes
- Initial DB schema created via `init_db()` (`create_all`) — Alembic tracks future changes
- IP logging records: account_create, login, login_fail, group_create, node_announce
- Rate limiting active on /v1/users/register and /v1/users/login (slowapi)
- Revocation, CSAM hash matching, moderation deferred to Phase 5
### Phase 3 scope
**In scope:**
- All POC endpoints from Spike 2+6, production-ready
- PostgreSQL via SQLAlchemy async + Alembic migrations
- IP logging (creation, login, group events) — 1-year retention, legal compliance
- Access token (JWT, 1h) + refresh token (30d, stored hashed)
- Rate limiting on auth endpoints
- Hub config file `/etc/meshbay/hub.toml` or env vars
- HTTPS via Caddy + auto Let's Encrypt on meshbay.org
- Systemd service with restart-on-failure
**Deferred to later:**
- Revocation push (WebSocket signaling to nodes)
- CSAM hash matching (NCMEC/IWF integration)
- Moderation flow (blocklist + takedown)
- MHP federation
- RPM/DEB packaging
### Testing strategy
- Unit tests with SQLite in-memory (`aiosqlite`) — no PostgreSQL needed locally
- API tests via `httpx.AsyncClient` + `ASGITransport` — no network
- All tests run in the existing `.venv` after adding Phase 3 deps
---
## Phase 4 — Integration & Client
**Goal:** end-to-end working product: node + hub + web client.
| # | Component | Notes |
|---|---|---|
| 4.1 | Web client (browser) | Browse Mesh Group Index, download, stream VOD |
| 4.2 | End-to-end integration test | Node ↔ Hub ↔ Client full flow |
| 4.3 | HLS/DASH streaming | Node segments on-the-fly, per-segment GEK-derived key |
| 4.4 | Chat (Double Ratchet) | Group messaging with attachments, Signal-like |
| 4.5 | Multi-group + multi-dir | Node hosts N groups across M directories |
---
## Phase 5 — QUIC, Federation, Mobile
**Goal:** full decentralization, mobile support, community infrastructure.
| # | Component | Notes |
|---|---|---|
| 5.1 | QUIC transport (MNP v2) | Replace TCP+TLS with aioquic; same application protocol |
| 5.2 | MHP federation | Hub-to-hub Mesh Directory exchange, explicit peer allowlist |
| 5.3 | Mesh Relay | Community TURN relay registration protocol |
| 5.4 | Android client | Kotlin/Flutter, hub account, group access, node pairing |
| 5.5 | Content replication | Node-to-node, admin-authorized, no hub involvement |
| 5.6 | iOS client | After Android stabilizes |
| 5.7 | Revocation push | WebSocket hub→node signed token broadcast |
| 5.8 | CSAM hash matching | NCMEC/IWF integration on public content registration |
| 5.9 | Moderation flow | blake3 blocklist, DMCA takedown, escalation |
| 5.10 | RPM/DEB packaging | meshbay-hub, meshbay-node, python3-meshbay-common |
---
## Conventions
- Commits: `feat(node):`, `fix(hub):`, `chore(common):`, `docs:`, `test(node):`
- Branch per feature/fix, merge to `main` (when remote configured)
- **Always close test UFW ports after any spike on meshbay.org**
- **Never commit key material** (keystore.enc, hub_private.pem, *.key, node_state.json, unlock.key)
- meshbay.org is internet-facing: only run known-safe services, close ports after tests
|