aboutsummaryrefslogtreecommitdiffstats
path: root/devel-phases-next.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-11 04:13:53 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-11 04:13:53 +0200
commite23e33adeaf8ee7439187d4451c856b37816a51f (patch)
treea41eef1fba34cdd642d25576395b4ad484a748ad /devel-phases-next.md
parent60c4570e72e36c2a9720593c8baec74ee2ab52d6 (diff)
downloadmeshbay-e23e33adeaf8ee7439187d4451c856b37816a51f.tar.gz
feat: Phase 9 — Web client SPA with WebRTC P2P transport
Complete browser-based client: Preact SPA with login, group file browser, encrypted download, video playback, group chat, i18n, and dark/light theme. Browser connects P2P to nodes behind residential NAT via WebRTC DataChannel (aiortc). Hub handles signaling only — all data flows E2E. Performance: pipelined downloads (8-chunk sliding window), binary msgpack wire format (no base64), redundant I/O elimination. Large file downloads stream to disk via File System Access API (showSaveFilePicker). Validated on SFR + Orange residential NATs, Chrome + Firefox, IPv4/IPv6. 132 tests passing. Deployed to meshbay.org + Orange node. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'devel-phases-next.md')
-rw-r--r--devel-phases-next.md64
1 files changed, 51 insertions, 13 deletions
diff --git a/devel-phases-next.md b/devel-phases-next.md
index 09d07fa..b2806bd 100644
--- a/devel-phases-next.md
+++ b/devel-phases-next.md
@@ -1,6 +1,6 @@
# MeshBay — Next Implementation Phases
-> Base: Phases 1–8 complete. 117 tests. demo-v3 validated against meshbay.org.
+> Base: Phases 1–9 complete. 132 tests. Web SPA live on meshbay.org.
> Architecture reference: docs/meshbay-draft-v4.md
> First security review: first-review.md (2026-08-10)
@@ -42,7 +42,10 @@ Deployed to meshbay.org. Existing emails encrypted. DB schema migrated.
---
-## Phase 9 — Web client: WebRTC transport + core SPA
+## Phase 9 — Web client: WebRTC transport + core SPA ✅ DONE
+
+Commit: TBD — 23 files, ~2000 lines, 132 tests.
+Deployed to meshbay.org + Orange node. Tested browser → node P2P through two ISP NATs.
**Objective:** a web browser can connect P2P to a node behind residential NAT,
browse files, download, stream video, and chat — with zero data through the hub.
@@ -134,17 +137,23 @@ Content is not indexed on the hub. Search works client-side:
| 9.3 | WebRTC→MNP transport adapter on node | `node/transport/webrtc_server.py` + hub_client WebRTC handler | ✅ |
| 9.4 | `transport.js` — browser WebRTC client | `static/transport.js` — connect, handshake, fetch, msgpack | ✅ |
| 9.5 | **Spike: E2E browser→NAT→node file transfer** | Mobile 4G → SFR NAT → node, IPv4 STUN + IPv6 validated | ✅ |
-| 9.6 | Preact SPA shell (login, routing, theme) | `static/app.js`, `static/css/style.css` | High |
-| 9.7 | Group list + file explorer UI | `static/components/GroupList.js`, `FileExplorer.js` | High |
-| 9.8 | File download via DataChannel | `static/components/Download.js` — chunk reassembly | High |
-| 9.9 | Video streaming via DataChannel | HLS segments → MediaSource API | Medium |
-| 9.10 | Chat/forum UI via DataChannel | `static/components/ChatView.js` — Sender Keys | Medium |
-| 9.11 | i18n framework + English strings | `static/i18n/en.json` | Medium |
-| 9.12 | Settings UI (profile, theme, notifications) | `static/components/Settings.js` | Medium |
-| 9.13 | Tests: unit + integration | WebRTC transport, MNP over DataChannel | High |
+| 9.6 | Preact SPA shell (login, routing, theme) | `static/app.js`, `static/style.css`, `static/vendor/htm-preact.js` | ✅ |
+| 9.7 | Group list + file explorer UI | `app.js` GroupPage, `groups.py` nodes endpoint, `revocation.py` group tracking | ✅ |
+| 9.8 | File download via DataChannel | AES-GCM chunks, GEK delivery, progress bar, browser download | ✅ |
+| 9.9 | Video streaming via DataChannel | Chunk download → Blob URL, video overlay with native controls | ✅ |
+| 9.10 | Chat/forum UI via DataChannel | ChatPanel component, chat history MNP, peer broadcast, tabs UI | ✅ |
+| 9.11 | i18n framework + English strings | `static/i18n.js` — t() lookup, ESM, localStorage lang, all strings extracted | ✅ |
+| 9.12 | Settings UI (profile, theme, language) | SettingsPage component, system theme support, sidebar link | ✅ |
+| 9.13 | Tests: unit + integration | WebRTC transport, MNP over DataChannel | ✅ |
+| 9.14 | Performance: pipelined download | sliding window (8 concurrent chunks) | ✅ |
+| 9.15 | Performance: binary wire format | raw bytes via msgpack, no base64 (+33%) | ✅ |
+| 9.16 | Performance: avoid redundant I/O | file_hash from index, not re-read per chunk | ✅ |
+| 9.17 | Large file download to disk | File System Access API (`showSaveFilePicker`) | ✅ |
**Critical path validated (2026-08-10):** 9.1 → 9.5 all pass. WebRTC DataChannel
-works browser → node through SFR residential NAT, confirmed with three scenarios:
+works browser → node through two different ISP residential NATs:
+
+**SFR residential NAT** (mobile 4G → node behind SFR Port-Restricted Cone + CGNAT):
| Test | ICE path | Result |
|---|---|---|
@@ -152,8 +161,37 @@ works browser → node through SFR residential NAT, confirmed with three scenari
| Mobile 4G SFR + IPv6 | IPv6 inter-network | OK, ~600ms |
| Mobile 4G SFR + IPv4 only | STUN hole-punch IPv4 | OK, ~650ms |
-Node behind SFR Port-Restricted Cone NAT + mobile behind SFR CGNAT 4G.
-No TURN relay needed. ICE/STUN handles both NAT types automatically.
+**Orange Livebox NAT** (laptop browser → node behind Orange residential NAT, cross-site):
+
+| Test | ICE path | Result |
+|---|---|---|
+| Chrome laptop → Orange node | IPv6 inter-network | OK, ~7000ms |
+| Firefox laptop → Orange node | IPv6 inter-network | OK, ~6700ms |
+| Firefox laptop → Orange node (IPv6 disabled) | STUN hole-punch IPv4 | OK, ~6900ms |
+
+Two ISPs validated, both Chrome and Firefox. No TURN relay needed.
+ICE/STUN handles all tested NAT types automatically.
+
+**Performance optimizations (2026-08-11):**
+- Initial transfer speed: ~2 MB/s (sequential, base64, redundant I/O)
+- After file_hash fix (9.16): ~3 MB/s (eliminated 78 GB redundant reads on 279 MB file)
+- After pipelining (9.14): ~5 MB/s (8-chunk sliding window, concurrent requests)
+- After binary wire format (9.15): eliminated 33% base64 inflation + removed
+ redundant per-chunk fields (sig, hashes, pk_node) — AES-GCM tag already
+ authenticates ciphertext, DTLS authenticates transport
+- Large file support (9.17): `showSaveFilePicker` (Chrome/Edge) streams decrypted
+ chunks directly to disk — flat ~8 MB RAM regardless of file size. Firefox/Safari
+ fall back to Blob-in-RAM approach.
+
+**Indexer debounce (2026-08-11):**
+- File copy triggers multiple watchdog events at different file sizes → duplicate
+ index entries with different blake3 hashes. Fixed with 2-second debounce +
+ path-based dedup (remove old entry before adding new).
+
+**Known remaining items for future phases:**
+- True video streaming (MSE or Service Worker) — currently downloads full file first
+- Multiple shared directories per node (UI + config)
+- Multi-node per user support
**Dependencies added:**
- `aiortc>=1.9` in `meshbay-node/pyproject.toml` ✅