aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-common/src/meshbay_common/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-common/src/meshbay_common/__init__.py')
-rw-r--r--packages/meshbay-common/src/meshbay_common/__init__.py43
1 files changed, 25 insertions, 18 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/__init__.py b/packages/meshbay-common/src/meshbay_common/__init__.py
index ac69e18..cb6ad15 100644
--- a/packages/meshbay-common/src/meshbay_common/__init__.py
+++ b/packages/meshbay-common/src/meshbay_common/__init__.py
@@ -90,14 +90,9 @@ __version__ = "0.11.0"
# 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.
-# 1.1: `index_delta` carries `roots` (additive — a 1.0 client ignores it), and
-# the per-root/per-app operations: `root_update`/`root_eject`/`root_plug`,
-# `app_directories`, `chat_directory`, `chat_link_preview`.
-# 2.0: the **write** path is sealed, and the last unencrypted content message
-# is gone.
+# **2.0 (2026-09-07): the write path is sealed, chat is encrypted, and the last
+# unencrypted content message is gone.** Three changes that landed together and
+# share one version, because they share one flag day.
#
# - `file_upload` and `file_upload_ack` travel sealed under a GEK-derived
# subkey (`groupbox.PURPOSE_UPLOAD`). The filename, the destination folder
@@ -105,6 +100,12 @@ __version__ = "0.11.0"
# client-chosen correlation id — and `chunk_index` stay in clear because
# the node routes and orders on them. `filename` used to be the
# correlation key and cannot be any more, which is what forced `upload_id`.
+# - `chat_msg` is sealed under a per-device subkey of the group's chat epoch
+# key (`meshbay_common.chatbox`) and signed over the ciphertext with the
+# device key the node pinned. There is deliberately **no per-group switch**:
+# every node in existence is a test node, so an opt-in flag would buy
+# nothing and leave a plaintext branch reachable. Existing node data is
+# migrated by `QE/migration/migrate_chat_encryption.py`.
# - `stream_seg` is **removed**. It answered with an MPEG-TS segment as
# base64 with no encryption at all, on both transports, to any
# authenticated member — the one content-plane message that never went
@@ -113,18 +114,24 @@ __version__ = "0.11.0"
# and never once invoked.
#
# **Breaking, on the wire every deployed client speaks**, and MAJOR by the same
-# rule 1.0 was: a 1.x client's upload reaches a 2.0 node with no `filename` and
-# no `data` outside the seal. That is why the break is confined rather than
-# total — `MNP_MIN_SUPPORTED` stays at "1.0", so a 1.x peer still connects,
-# browses, downloads, streams and chats; only its uploads are refused, with
-# `upload_not_sealed` and a message saying which side is old. A client refuses
-# symmetrically before sending (`supportsSealedUpload` in transport.js), so
-# neither side discovers this as a timeout.
+# rule 1.0 was.
+#
+# **`MNP_MIN_SUPPORTED` moves to "2.0" with it, and that is a change of plan
+# worth reading.** The sealed upload alone was a *confined* break: a 1.x peer
+# could still connect, browse, download, stream and chat, and only its uploads
+# were refused — so the floor stayed at "1.0" and the refusal was per message
+# (`upload_not_sealed`). Mandatory chat encryption ends that confinement. A 1.x
+# peer can neither produce a sealed chat message nor read one, so it would
+# connect, appear to work, and then be unable to say anything or read anything
+# anyone else said. Refusing it at the handshake with `version_too_old` and a
+# sentence saying so is the honest form: a stated refusal is a bug report, a
+# chat that quietly does not work is a support case. The per-message
+# `upload_not_sealed` path stays, unchanged — it is still the right answer if
+# the floor is ever lowered again.
#
# Still deliberately in clear, and none of it is content: the handshake itself,
# `index_progress` (counters only — see daemon.py `_push_index_progress`), the
-# admin and configuration acks, and the media-metadata replies. Chat is next,
-# under sender keys. The index at rest and file content on the operator's disk
-# are unchanged.
+# admin and configuration acks, and the media-metadata replies. The index at
+# rest and file content on the operator's disk are unchanged.
MNP_VERSION = "2.0"
MHP_VERSION = "0.1"