summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/ui/app.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-09 01:15:41 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-09 01:15:41 +0200
commitb3ea222ca8b6218e0187070fe94bc8fed7059a90 (patch)
tree236ed70a1efffe4137078fa29410feb5bd459319 /packages/meshbay-node/src/meshbay_node/ui/app.py
parent77615ddb5fead3e74751a94847d3bcc99fc0a96d (diff)
downloadmeshbay-b3ea222ca8b6218e0187070fe94bc8fed7059a90.tar.gz
fix(node): give the per-member transfer cap a door anyone can open
Reported as "the slots seem hardcoded to 2": `meshbay-node transfers set 8 8` and still only two downloads at a time. Not hardcoded — that is the *per-member* cap, which is a group's setting and is checked before the node's, so raising the machine's total cannot move it. But the diagnosis was right in the way that matters: nothing could change it. `OP_TRANSFER_LIMITS` shipped with exactly one front door, the signed MNP handler, and nothing anywhere opened it — no client call, no CLI verb, no loopback route. So the cap sat at its default of 2 for ever, which from outside is indistinguishable from a constant. CLAUDE.md states the rule this missed: operator operations are one implementation with several front doors. - `PUT /api/groups/{id}/transfer-limits`, calling the same `ops.set_transfer_limits` the signed handler calls; - `meshbay-node transfers per-member <downloads> <uploads> [--group X]`; - `transfers show` now separates the node-wide pools from the per-group per-member caps, and marks each `[set]` or `[default]`. It printed "2 per member" with no indication of where the 2 came from, which is half of why this looked like a constant. Zero is refused here as everywhere else: it is not "unlimited", and a member who may not transfer at all is a member the operator revokes. Verified on a live node: the cap changes, survives a daemon restart, and `transfer_probe.py --want 6` measures 4 granted against a cap of 4 where it measured 2 before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HCGdheDLxGReuKHga3BtST
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/ui/app.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/ui/app.py10
1 files changed, 10 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/ui/app.py b/packages/meshbay-node/src/meshbay_node/ui/app.py
index 9b9307d..4ad3787 100644
--- a/packages/meshbay-node/src/meshbay_node/ui/app.py
+++ b/packages/meshbay-node/src/meshbay_node/ui/app.py
@@ -515,4 +515,14 @@ def create_ui_app(state: dict) -> FastAPI:
async def get_transfers():
return await _op(lambda: ops.list_transfers(state))
+ @app.put("/api/groups/{group_id}/transfer-limits")
+ async def set_transfer_limits(group_id: str, payload: dict):
+ # The same `ops.set_transfer_limits` the signed MNP handler calls. The
+ # op existed with only that one door, and nothing anywhere opened it —
+ # so the per-member cap sat at its default of 2 with no way to change
+ # it, which from outside is indistinguishable from a hardcoded 2.
+ return await _op(lambda: ops.set_transfer_limits(
+ state, group_id,
+ int(payload.get("downloads", 0)), int(payload.get("uploads", 0))))
+
return app