From 675beed6ff688733a9598f9d82d41578f48316be Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 3 Sep 2026 16:16:55 +0200 Subject: feat!: MNP 1.0 — seal index and handshake_ack under the group key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `index_sync`, `index_delta` and the `handshake_ack` config payload now travel sealed under a GEK-derived subkey (`meshbay_common/groupbox.py`, mirrored by `sealGroup`/`openGroup` in `crypto.js`). Only `type`, `v`, `group_id` and the ack's `node_pk`/`proof`/`sig` stay in clear — a receiver must route and authenticate before it would trust a decryption. Verify, then decrypt. The ack line is integrity, not confidentiality: the signed handshake transcript names no ack field, so `is_node_admin`, `enabled_apps`, `video_root` and the rest were authenticated by the DTLS channel alone. The index line is defence in depth against a repeat of C1/C6 — a peer served before the handshake completes now gets ciphertext, not filenames. Nothing against an observer, the hub, or a member; that is the whole claim. `index_progress` stays clear (D3, counters only). Chat is out of scope. Failure is fatal: a payload that does not open ends the session naming the message type — never an empty index or an empty `enabled_apps`, both of which are legitimate states. Version negotiation ships here too (phase 15.6, brought forward): `v` + `v_min` on `handshake` and `handshake_challenge`, refused with `version_too_old` / `version_too_new` / `version_unreadable`. The flag day was already being paid for; the next breaking change now costs a refusal message. BREAKING CHANGE: breaks the WebRTC wire every deployed client speaks. Hub and every node must deploy together; the SPA is served by the hub, so a browser picks up the new client on reload. See MESHBAY_NODE_PROTOCOL.md §11.1a, §13.1. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HkzbhmMmK8PqQBtGz5zCvY --- packages/meshbay-hub/src/meshbay_hub/static/group-page.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/group-page.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js index 7d13260..466af53 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js @@ -392,6 +392,16 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, if (cancelled) return; applyIndexDelta(msg); }; + // A pushed message that will not open under the group key ends the + // session (transport.js _failSession). Nothing is waiting on a push, so + // without this the page would keep showing a stale index with nothing + // wrong on screen — the worst of the three failure shapes. + transport.onSessionFailed = (err) => { + if (cancelled) return; + setError(err.message); + setStatus('error'); + if (onPresence) onPresence(groupId, 'online'); + }; // We are in: an invitation to this group has served its purpose. if (onJoined) onJoined(groupId); -- cgit v1.2.3