diff options
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/daemon.py | 18 | ||||
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py | 24 |
2 files changed, 35 insertions, 7 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/daemon.py b/packages/meshbay-node/src/meshbay_node/daemon.py index 966dc69..dcfa8f8 100644 --- a/packages/meshbay-node/src/meshbay_node/daemon.py +++ b/packages/meshbay-node/src/meshbay_node/daemon.py @@ -1190,10 +1190,20 @@ class NodeDaemon: spec["ejected"] = True return RootSet.build(specs) - # Every app that keeps directories. Not derived from `enabled_apps`: the - # context is read once at load and an app enabled later must not find its - # own setting missing. Adding an app adds a name here and nowhere else on - # this side. + # Every application that keeps directories. This is the one list, and it + # lives here because the daemon is what wires a group's context: `roster.py`, + # `ops.py` and the rest must name no application at all — that is the + # property the reference app exists to demonstrate + # (`test_helloworld_proves_the_plugin_claim.py`). + # + # Not derived from `enabled_apps`: the context is read once at load, and an + # application enabled later must not find its own setting missing. + # + # The handshake ack does **not** get a copy of this. It emits whatever + # `<app>_directories` the context holds, so the two cannot drift — a copy + # lived in `webrtc_server.py` until 2026-09-10 and had already lost + # `helloworld`, which made the app that proves a new one needs no + # special-casing the single app whose directories never reached a client. APP_DIR_KEYS = ("video", "music", "photo", "chat", "helloworld") async def _app_directories_ctx(self, group_id: str) -> dict: 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 54f1541..a0776d2 100644 --- a/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py +++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py @@ -897,9 +897,7 @@ class WebRTCPeerSession: # safe for the reason those were not: it is *derived* from this list # on every build rather than stored beside it, so the two cannot # drift apart. - **{f"{app}_directories": - list(self._group_ctx().get(f"{app}_directories") or []) - for app in ("video", "music", "photo", "chat")}, + **self._app_directories_ack(), # Where chat attachments are written — the singular form, because # Chat genuinely has one destination. "" means the operator has not # chosen, and the paperclip says so. @@ -3182,6 +3180,26 @@ class WebRTCPeerSession: task.add_done_callback(_on_done) return task + def _app_directories_ack(self) -> dict: + """ + Every application's configured folders, for the handshake ack. + + Read off the group context rather than from a list of applications kept + here, so this cannot name an application the node knows nothing else + about — and cannot fail to name one the daemon does. A copy of the + daemon's `APP_DIR_KEYS` lived here until 2026-09-10 and had already lost + an entry, which made the app that entry belonged to the single one whose + directories never reached a client. This module names an application in + exactly one place, and it is `ALLOWED_APPS`. + + `_app_directories_ctx` is the only thing that puts a `*_directories` key + in that context, and an absent one reads as none configured — never as + "the whole group index". + """ + return {key: list(value or []) + for key, value in self._group_ctx().items() + if key.endswith("_directories")} + def _group_ctx(self) -> dict: if "groups" in self._ctx and self._group_id: # `.get`, not a bare subscript. A config reload removes a group |