From 36ef1b76dce56a40650f890156eb137536ef015d Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sun, 6 Sep 2026 19:11:05 +0200 Subject: fix(client): a successful root op must never blank the operator's table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ops.update_root` and `remove_root` returned `[]` when the group context had no live RootSet, and `group-page.js` accepted it: `if (msg.roots)` is true for an empty array. An op that succeeded would have emptied the shared-directories table, and "the node says this group has no directories" is not something the client can tell from "the node could not say". Both ends now refuse it — the node builds from config rather than answering empty, and the client requires a non-empty array. Found while adding `test_spa_imports.py`, which is the other half of this: it resolves every named import across the SPA against what the target actually exports. That failure has a shape nothing else here catches — no build step to fail, so the browser resolves the graph at load, finds a missing binding, and the page renders blank or the component just does not appear. `node --check` parses one file at a time and the source-reading guards look inside a file rather than between two. The settings split moved two shared components into a new module and rewired eight files to import them, which is exactly the change where a rename lands in one file and not the other. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011pvMdvLBG92jyhvD5pD6us --- packages/meshbay-hub/src/meshbay_hub/static/group-page.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'packages/meshbay-hub/src') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js index 747cb74..e762fc8 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js @@ -374,7 +374,11 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs, transport.onMusicbrainzEnabled = (enabled) => setMusicbrainzConfig((prev) => ({ ...(prev || {}), enabled })); transport.onRootsChanged = (msg) => { - if (msg.roots) { + // `msg.roots &&` would accept `[]`, and an empty array is truthy — + // so a node that could not describe its roots would blank the + // operator's table on an op that actually succeeded. A group always + // has at least one root, so nothing legitimate is dropped here. + if (Array.isArray(msg.roots) && msg.roots.length) { setNodeRoots(msg.roots); } }; -- cgit v1.2.3