aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src')
-rw-r--r--packages/meshbay-node/src/meshbay_node/daemon.py18
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/webrtc_server.py24
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