aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-28 22:47:23 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-28 22:47:23 +0200
commit6bb2fa48ef13e0630e155565c4c0e046de03a1a1 (patch)
treee641c5f548f05d393aa198643e5f88cb104c9bf4
parent215864bf655f7dcb793e80c836598655d6d945a9 (diff)
downloadmeshbay-6bb2fa48ef13e0630e155565c4c0e046de03a1a1.tar.gz
refactor(node): remove five loopback routes nothing called
The group-setting routes for app directories, chat directory, link previews, Search listing and scan settings had no caller and no test; those settings are signed MNP operations only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--docs/MESHBAY_DESIGN.md2
-rw-r--r--docs/MESHBAY_NODE_PROTOCOL.md5
-rw-r--r--packages/meshbay-node/src/meshbay_node/ui/app.py45
3 files changed, 6 insertions, 46 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index c37e43b..06ba2b5 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -2537,7 +2537,7 @@ everything registered — a node that predates an application hides nothing.
**An application's directories are the same shape one level down**: one generic
signed op (`app_directories`) keyed by the application's own registry name, stored
-under `<key>_directories`, one MNP message, one loopback route. Adding an
+under `<key>_directories`, one MNP message. Adding an
application adds **no function, no message type and no route** — which is what
"plug-in architecture" has to mean to be worth the phrase.
diff --git a/docs/MESHBAY_NODE_PROTOCOL.md b/docs/MESHBAY_NODE_PROTOCOL.md
index c3254da..ce99a40 100644
--- a/docs/MESHBAY_NODE_PROTOCOL.md
+++ b/docs/MESHBAY_NODE_PROTOCOL.md
@@ -1207,6 +1207,11 @@ one is the one that decides. A front door is allowed to differ in how it *authen
— a signature here, a run token on loopback, an operator's shell for the CLI — and never
in what it *does*.
+An operation has the doors something uses, and no more: a door nobody calls is an
+untested way in. The per-group settings the group's Settings tab changes —
+application folders, the chat folder, link previews, the Search listing, the scan
+settings — are signed MNP operations only.
+
---
## 11. Content plane
diff --git a/packages/meshbay-node/src/meshbay_node/ui/app.py b/packages/meshbay-node/src/meshbay_node/ui/app.py
index 50beb26..bbc4649 100644
--- a/packages/meshbay-node/src/meshbay_node/ui/app.py
+++ b/packages/meshbay-node/src/meshbay_node/ui/app.py
@@ -20,7 +20,6 @@ from fastapi.responses import JSONResponse
from meshbay_common.background import spawn
from meshbay_node import __version__, ops
-from meshbay_node.indexer.indexer import DirectoryIndexer
log = logging.getLogger(__name__)
@@ -493,50 +492,6 @@ def create_ui_app(state: dict) -> FastAPI:
raise HTTPException(400, "apps must be a non-empty list")
return await _op(lambda: ops.set_enabled_apps(state, group_id, apps))
- # ── App directories (operator only, localhost) ────────────────────────
- #
- # The loopback twin of the `app_directories` MNP op. One endpoint for every
- # application, keyed by the app's own name, so adding one needs no route
- # here — the same reason the op is generic. `ALLOWED_APPS` is checked on
- # the MNP path; here the caller is already on localhost holding the run
- # token, and `ops` refuses a directory outside the group's roots either
- # way, so an unknown key writes one unread settings row and nothing else.
-
- @app.put("/api/groups/{group_id}/app-directories/{app_key}")
- async def set_app_directories(group_id: str, app_key: str, payload: dict):
- dirs = payload.get("directories")
- if not isinstance(dirs, list):
- raise HTTPException(400, "directories must be a list")
- return await _op(lambda: ops.set_app_directories(
- state, group_id, app_key, [str(d) for d in dirs]))
-
- @app.put("/api/groups/{group_id}/chat-directory")
- async def set_chat_directory(group_id: str, payload: dict):
- return await _op(lambda: ops.set_chat_directory(
- state, group_id, str(payload.get("path") or "")))
-
- @app.put("/api/groups/{group_id}/chat-link-preview")
- async def set_chat_link_preview(group_id: str, payload: dict):
- return await _op(lambda: ops.set_chat_link_preview(
- state, group_id, bool(payload.get("enabled", True))))
-
- @app.put("/api/groups/{group_id}/search-listed")
- async def set_search_listed(group_id: str, payload: dict):
- return await _op(lambda: ops.set_search_listed(
- state, group_id, bool(payload.get("listed", True))))
-
- # ── Scan settings (operator only, localhost) ──────────────────────────
-
- @app.put("/api/groups/{group_id}/scan-settings")
- async def set_scan_settings(group_id: str, payload: dict):
- return await _op(lambda: ops.set_scan_settings(
- state, group_id,
- float(payload.get("reconcile_interval_secs",
- DirectoryIndexer.DEFAULT_RECONCILE_SECS)),
- float(payload.get("debounce_secs",
- DirectoryIndexer.DEFAULT_DEBOUNCE_SECS)),
- ))
-
# ── Reload config ────────────────────────────────────────────────────
@app.post("/api/reload")