From 754387590fa1754436b4648f969915888c6f6c9e Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 2 Oct 2026 10:51:19 +0200 Subject: refactor(mnp): remove ten operator messages no client sent node_status, node_settings_set, roster_read, denylist_read, denylist_clear, node_reload and the signed gek_rotate, member_unpin, transfer_limits, group_detach leave MNP 6.0; the Node page and the CLI do this work over loopback. Their ops keep their tests, moved to the ops level. Co-Authored-By: Claude Opus 5.5 --- .../src/meshbay_node/transport/webrtc/admin.py | 49 +--------------------- 1 file changed, 2 insertions(+), 47 deletions(-) (limited to 'packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py') diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py index 738dbce..9a6cbd1 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py @@ -17,13 +17,10 @@ from meshbay_common.adminop import ( OP_CHAT_LINK_PREVIEW, OP_DIR_DELETE, OP_FILE_DELETE, - OP_GEK_ROTATE, - OP_GROUP_DETACH, OP_INVITE_CANCEL, OP_INVITE_CREATE, OP_INVITE_LINK_CREATE, OP_MEMBER_REVOKE, - OP_MEMBER_UNPIN, OP_MUSICBRAINZ_ENABLED, OP_ROOT_EJECT, OP_ROOT_PLUG, @@ -34,7 +31,6 @@ from meshbay_common.adminop import ( OP_TMDB_ENABLED, OP_TMDB_OVERRIDE, OP_TMDB_REMATCH, - OP_TRANSFER_LIMITS, admin_transcript, ) from meshbay_common.crypto import pk_to_b64 @@ -59,10 +55,7 @@ _ADMIN_EXECUTORS = { OP_INVITE_CREATE: "_admin_exec_invite_create", OP_INVITE_LINK_CREATE: "_admin_exec_invite_link_create", OP_INVITE_CANCEL: "_admin_exec_invite_cancel", - OP_GEK_ROTATE: "_admin_exec_gek_rotate", - OP_MEMBER_UNPIN: "_admin_exec_member_unpin", OP_APPS_ENABLED: "_admin_exec_apps_enabled", - OP_TRANSFER_LIMITS: "_admin_exec_transfer_limits", OP_SET_SCAN_SETTINGS: "_admin_exec_set_scan_settings", OP_TMDB_CONFIG: "_admin_exec_tmdb_config", OP_TMDB_ENABLED: "_admin_exec_tmdb_enabled", @@ -77,7 +70,6 @@ _ADMIN_EXECUTORS = { OP_CHAT_EPOCH: "_admin_exec_chat_epoch", OP_ROOT_EJECT: "_admin_exec_root_eject", OP_ROOT_PLUG: "_admin_exec_root_plug", - OP_GROUP_DETACH: "_admin_exec_group_detach", } @@ -174,49 +166,12 @@ class AdminMixin: says "the hub says you are the owner", which is the one thing NS4 and M3 rule out: a hub that can name the operator can install itself as node administrator. It rides the handshake ack so a client knows whether - to offer the Node page at all, and every operation is gated on - `_operator_device()` below. + to offer operator controls at all; every operation is gated on a + signature (`_verify_admin_sig`). """ node_user_id = self._ctx.get("node_user_id") return bool(node_user_id and self._user_id == node_user_id) - async def _operator_device(self) -> bool: - """ - Whether this connection may run the node's own controls. - - Two things, and the second is the one that cannot be forged: - - - the account is the one this node belongs to (`_is_node_admin`), which - is what keeps node-wide controls with the machine's owner rather than - with every paired operator of every group on it; and - - **the device on this connection proved a key the node pinned as an - operator**. `device_hello` is signed over a transcript naming this - node, this group and this connection's nonce, and `operator_pks()` is - rebuilt from the roster on each call, so an unpinned browser and a - revoked one are both refused at once. - - The second clause is the fix for the door this used to leave open. - `node_status`, `node_settings_set`, `roster_read`, `denylist_read`, - `denylist_clear` and `node_reload` were gated on the account id alone — - a value the hub chooses. An active hub that can also reach the group key - (which §3.5 concedes it can in an open-join group) could therefore mint - a token for the owner's account and read `node_status`, which lists - every group on the node with the operator's **absolute paths**, or clear - the denylist, which is the persisted revocation H4 exists to keep. - - It holds no user keys and cannot countersign anything, so it cannot - produce a `device_hello` — which is the same property device linking - rests on (§3.3), applied to the node's own surface. - """ - if not self._is_node_admin(): - return False - if not self._device_confirmed or not self._pinned_pk: - return False - roster = self._ctx.get("roster") - if roster is None: - return False - return self._pinned_pk in await roster.operator_pks() - def _has_admin_authority(self) -> bool: """ Cheap synchronous pre-check: is there anyone who could authorize this? -- cgit v1.2.3