aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_spa_ordering.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-14 11:15:27 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-14 11:15:27 +0200
commit6309894d019421f54cff311e630f3897f7eba93e (patch)
tree274e9cd1721a7c7b1a89344d1d06f0e127b6df15 /packages/meshbay-hub/tests/test_spa_ordering.py
parent8f9ac4d931e43358cb0e4e82085f49e916419a8b (diff)
downloadmeshbay-6309894d019421f54cff311e630f3897f7eba93e.tar.gz
test: prove a second browser works after pairing
The mechanism was already there — the encrypted keypair bundle goes to the node after a first successful connection, and any client holding the password can recover it — but nothing exercised it. e2e.py never pushed a bundle, so the case that matters to an ordinary user was the one case never tested. It now does what app.js does: backs the member's keys up to the node, then opens a second client carrying nothing but a username and a password. Against the live deployment that client recovers its identity keys, is recognised as the same person with no second code, gets the same group key, and browses the group. Also guards the ordering this depends on: the keypair bundle must be fetched before joinGroup() runs, or a browser that did not register has no key to sign the join with — invisible on the browser that did register, broken on every other one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests/test_spa_ordering.py')
-rw-r--r--packages/meshbay-hub/tests/test_spa_ordering.py16
1 files changed, 16 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_spa_ordering.py b/packages/meshbay-hub/tests/test_spa_ordering.py
index 839698a..0ef34fc 100644
--- a/packages/meshbay-hub/tests/test_spa_ordering.py
+++ b/packages/meshbay-hub/tests/test_spa_ordering.py
@@ -74,6 +74,22 @@ def test_join_happens_before_the_gek_proof():
"key to prove with")
+def test_keys_are_recovered_before_the_join_is_attempted():
+ """
+ A second browser holds nothing but a password. It recovers its identity keys
+ from the node's encrypted keypair bundle, and only then can it sign a join —
+ so the recovery has to come first. Getting this order wrong is invisible on
+ the browser that registered, and breaks every other one.
+ """
+ recover, join_call = _positions(
+ "type: 'keypair_bundle_fetch'",
+ "await this.joinGroup(",
+ )
+ assert recover < join_call, (
+ "the keypair bundle must be fetched before joinGroup() — otherwise a "
+ "browser that did not register has no key to sign the join with")
+
+
def test_the_ack_still_verifies_the_announced_node_key():
"""
Taking node_pk from the challenge is only safe because the ack proves it and