From 76724252d08162d4df39090af19796054bf4add8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 15 Aug 2026 00:49:54 +0200 Subject: fix(members): restore the member list and invite form, and retire the pairing form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving the invite form above the member list cut both out of MembersPanel and pasted them into AdminPage, where `doInvite`, `members`, `adminId` and `inviteCode` do not exist. A standard member saw an empty Members tab, the group owner saw only a pairing form, and the hub's own Users tab referenced four undefined names. The pairing form outstaying its welcome is a second bug and an older one. `is_node_admin` compares the connecting account with the account that owns the node — it says nothing about whether *this browser's key* was ever paired, which is the thing pairing changes and the thing that lets you sign an invite. So the form showed for an operator who paired months ago, accepted a fresh code, reported success, and stayed exactly where it was. The node already reports the roster role in `join_result`; the transport keeps it, and the form appears only when this identity is not an operator key yet. Also dropped a clause from the pairing hint: the code never passing through the hub is worth saying, the theory behind it is not. test_spa_ordering.py gets three checks for this class of bug — a cut-and-paste between components is invisible to every other test we have. Co-Authored-By: Claude Opus 5 --- packages/meshbay-hub/src/meshbay_hub/static/transport.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index 0306a5c..d904286 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -383,6 +383,7 @@ class MeshBayTransport { err.reason = reason; throw err; } + this.memberRole = 'operator'; return resp; } @@ -588,6 +589,10 @@ class MeshBayTransport { const myPkX = Uint8Array.from(atob(pkXB64), c => c.charCodeAt(0)); const gekRaw = await C.unwrapGEK(resp, skXRaw, myPkX); this._gekRaw = gekRaw; + // What the node's roster says this identity is, which is not what the hub + // says: `operator` here means this browser's key was paired with the node, + // not merely that the account owns it. + this.memberRole = resp.role || ''; return gekRaw; } -- cgit v1.2.3