From 1dcedc77083b908b7b3b431bad679a4813884355 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 10 Sep 2026 17:23:40 +0200 Subject: refactor(mnp)!: one answer to "may this member write", and it is the root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The group-wide `member_upload` switch is gone: the message, the signed operation, the field on the handshake ack, the `upload` alias on every root in the index payload, and the client's fallback path to it. Whether a member may write has been a property of each root for a while, and that is the model that survives: a single flag over the group cannot express "this library is published read-only and that folder is a drop box", which is the ordinary arrangement. What was left of the switch was a handler that logged a deprecation and acted on nothing, and a client that read `ack.member_upload` whenever the roots carried no `writable` — a second source for one question, with whichever the code consulted first deciding it. `roots.describe()` drops `upload` for the same reason: it was `writable` under an older name, and two names for one boolean is one too many. The paperclip now says "nowhere to write" rather than picking a root, in a group that has none writable. That is the honest answer; the fallback picked whatever came first and failed at send time. Node suite 1215 passed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AsoWC3GmhNdwVFomW3QjH3 --- packages/meshbay-node/src/meshbay_node/roots.py | 4 +--- .../src/meshbay_node/transport/webrtc_server.py | 22 ---------------------- 2 files changed, 1 insertion(+), 25 deletions(-) (limited to 'packages/meshbay-node/src') diff --git a/packages/meshbay-node/src/meshbay_node/roots.py b/packages/meshbay-node/src/meshbay_node/roots.py index d288231..410fe68 100644 --- a/packages/meshbay-node/src/meshbay_node/roots.py +++ b/packages/meshbay-node/src/meshbay_node/roots.py @@ -371,9 +371,7 @@ class RootSet: "available": r.available, "writable": r.writable, "removable": r.removable, - "ejected": r.ejected, - # Backward compat for MNP 1.0 clients - "upload": r.writable} + "ejected": r.ejected} # `with_paths` is for the operator's *own* channels only — the # loopback API and the CLI reading it, both of which already # require being on this machine with the run token. A member is diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py index 11412bf..ec7ef5d 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py @@ -67,7 +67,6 @@ from meshbay_common.adminop import ( OP_MEMBER_REVOKE, OP_GEK_ROTATE, OP_MEMBER_UNPIN, - OP_MEMBER_UPLOAD, OP_APPS_ENABLED, OP_SET_SCAN_SETTINGS, OP_TRANSFER_LIMITS, @@ -570,8 +569,6 @@ class WebRTCPeerSession: self._spawn(self._do_device_revoke(msg)) elif mtype == MNP.DEVICE_HELLO and self._nonce_node: self._spawn(self._do_device_hello(msg)) - elif mtype == MNP.MEMBER_UPLOAD: - self._do_member_upload(msg) elif mtype == MNP.APPS_ENABLED: self._do_apps_enabled(msg) elif mtype == MNP.TRANSFER_LIMITS: @@ -879,12 +876,6 @@ class WebRTCPeerSession: # channel and nothing else. config = { "is_node_admin": self._is_node_admin(), - # Backward compat for MNP 1.0 clients: computed from writable roots. - # New clients read per-root writable from the index payload instead. - "member_upload": any( - r.get("writable") for r in - (self._group_ctx().get("roots").describe() - if self._group_ctx().get("roots") else [])), # Which group "applications" to show. Absent/empty falls back to # every registered one client-side, so a node that predates this # setting (or one whose context has not loaded it yet) hides @@ -2075,14 +2066,6 @@ class WebRTCPeerSession: self._send({"type": MNP.MEMBER_UNPIN_ACK, "v": MNP_VERSION, "user_id": user_id}) - def _do_member_upload(self, msg: dict) -> None: - # Deprecated: upload control is now per-root via writable flag. - # Old clients may still send this — acknowledge without acting. - log.warning("Deprecated member_upload message received — use root " - "writable/read-only instead") - self._send({"type": MNP.MEMBER_UPLOAD_ACK, "v": MNP_VERSION, - "allowed": True, "deprecated": True}) - # Every "application" a group can show. Photos joins this set (and # apps.js's registry, client-side) when it lands; nothing else about # this handler changes. DEFAULT_APPS (roster.py) deliberately does not @@ -5321,11 +5304,6 @@ class WebRTCPeerSession: elif pending["op"] == OP_MEMBER_UNPIN: self._spawn( self._admin_exec_member_unpin(pending, transcript, sig_bytes)) - elif pending["op"] == OP_MEMBER_UPLOAD: - log.warning("Deprecated OP_MEMBER_UPLOAD signed op — use root " - "writable/read-only instead") - self._send({"type": MNP.MEMBER_UPLOAD_ACK, "v": MNP_VERSION, - "allowed": True, "deprecated": True}) elif pending["op"] == OP_APPS_ENABLED: self._spawn( self._admin_exec_apps_enabled(pending, transcript, sig_bytes)) -- cgit v1.2.3