aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-common/src/meshbay_common/__init__.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-03 16:16:55 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-03 16:16:55 +0200
commit675beed6ff688733a9598f9d82d41578f48316be (patch)
tree78dd4f8dff312f0ad99bd63bc679bf402591c5ed /packages/meshbay-common/src/meshbay_common/__init__.py
parent15087b0e8fdb872602310119f14680aaa443fd93 (diff)
downloadmeshbay-675beed6ff688733a9598f9d82d41578f48316be.tar.gz
feat!: MNP 1.0 — seal index and handshake_ack under the group key
`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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HkzbhmMmK8PqQBtGz5zCvY
Diffstat (limited to 'packages/meshbay-common/src/meshbay_common/__init__.py')
-rw-r--r--packages/meshbay-common/src/meshbay_common/__init__.py25
1 files changed, 24 insertions, 1 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/__init__.py b/packages/meshbay-common/src/meshbay_common/__init__.py
index 61502c9..e96c483 100644
--- a/packages/meshbay-common/src/meshbay_common/__init__.py
+++ b/packages/meshbay-common/src/meshbay_common/__init__.py
@@ -70,5 +70,28 @@ __version__ = "0.10.0"
# there: the WebRTC shape — the one every deployed client speaks — is byte for byte
# what it was, and no QUIC client ships. Recorded as a MINOR bump for that reason;
# a deployed QUIC peer would have made it a MAJOR one.
-MNP_VERSION = "0.15"
+# 1.0: `index_sync`, `index_delta` and the `handshake_ack` configuration
+# fields now travel **sealed under a GEK-derived subkey**
+# (`meshbay_common.groupbox`), and the handshake negotiates a supported
+# version range instead of writing a `v` nobody reads.
+#
+# **Breaking, on the wire every deployed client speaks**, and there is no way
+# to describe it as additive: an old client sends `index_sync` and gets a
+# message with no `entries`; it reads `ack.enabled_apps`, finds nothing, and
+# applies its documented fallback — "show every app" — rather than reporting
+# an error; a new client against an old node finds `entries` it does not
+# expect and no `ct`. 0.15 stayed MINOR because only the QUIC wire changed and
+# no QUIC client ships; that argument is not available here, and MAJOR is what
+# the project's own rule says. Hub and every node deploy together; the SPA is
+# served by the hub, so a browser picks up the new client on reload.
+#
+# Version negotiation ships in the same flag day rather than after it (phase
+# 15.6): the coordinated deployment is already being paid for, and it is what
+# makes the *next* breaking change cost a refusal message instead of a second
+# flag day. `MNP_MIN_SUPPORTED` in `handshake.py` is the other half.
+#
+# The index at rest, `index_progress` (counters only, never a path — see
+# `groupbox.py` and daemon.py `_push_index_progress`), chat, and file content
+# on the operator's disk are all deliberately unchanged.
+MNP_VERSION = "1.0"
MHP_VERSION = "0.1"