diff options
Diffstat (limited to 'packages/meshbay-node/tests/test_webrtc_transport.py')
| -rw-r--r-- | packages/meshbay-node/tests/test_webrtc_transport.py | 99 |
1 files changed, 50 insertions, 49 deletions
diff --git a/packages/meshbay-node/tests/test_webrtc_transport.py b/packages/meshbay-node/tests/test_webrtc_transport.py index cc0c6a2..5727ef9 100644 --- a/packages/meshbay-node/tests/test_webrtc_transport.py +++ b/packages/meshbay-node/tests/test_webrtc_transport.py @@ -48,6 +48,7 @@ from meshbay_common.adminop import ( ) from meshbay_common.join import ROLE_MEMBER, ROLE_OPERATOR, join_transcript from meshbay_node.bundle_store import BundleStore +from conftest import one_root from meshbay_node.roster import Roster from meshbay_node.indexer import DirectoryIndexer from meshbay_node.transport.webrtc_server import WebRTCTransport @@ -265,12 +266,12 @@ async def _setup_peer(transport, sk_hub, gek, peer_id, jwt_sub="user-001", sk_us async def test_webrtc_datachannel_handshake(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: browser sends MNP handshake, node responds with handshake_ack.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -309,12 +310,12 @@ async def test_webrtc_datachannel_handshake(sk_node, sk_hub, gek, shared_dir): async def test_webrtc_datachannel_file_transfer(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: full file transfer — handshake, index, fetch chunk, decrypt.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -396,12 +397,12 @@ async def test_webrtc_datachannel_file_transfer(sk_node, sk_hub, gek, shared_dir async def test_webrtc_invalid_jwt_rejected(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: invalid JWT is rejected with error.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -444,12 +445,12 @@ async def test_webrtc_invalid_jwt_rejected(sk_node, sk_hub, gek, shared_dir): async def test_webrtc_request_before_handshake_rejected(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: request without handshake is rejected.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -490,7 +491,7 @@ async def test_webrtc_chat_send_and_history(sk_node, sk_hub, gek, shared_dir, tm from meshbay_node.chat.store import ChatStore hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() chat_store = ChatStore(db_path=tmp_path / "chat_test.db") @@ -498,7 +499,7 @@ async def test_webrtc_chat_send_and_history(sk_node, sk_hub, gek, shared_dir, tm transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["chat_store"] = chat_store @@ -537,12 +538,12 @@ async def test_webrtc_chat_send_and_history(sk_node, sk_hub, gek, shared_dir, tm async def test_webrtc_chat_history_no_store(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: chat history without chat_store returns empty list.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -566,7 +567,7 @@ async def test_webrtc_chat_broadcast(sk_node, sk_hub, gek, shared_dir, tmp_path) from meshbay_node.chat.store import ChatStore hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() chat_store = ChatStore(db_path=tmp_path / "chat_bc.db") @@ -574,7 +575,7 @@ async def test_webrtc_chat_broadcast(sk_node, sk_hub, gek, shared_dir, tmp_path) transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["chat_store"] = chat_store @@ -604,12 +605,12 @@ async def test_webrtc_chat_broadcast(sk_node, sk_hub, gek, shared_dir, tmp_path) async def test_webrtc_group_membership_enforced(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: JWT without matching group claim is rejected.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -651,12 +652,12 @@ async def test_webrtc_group_membership_enforced(sk_node, sk_hub, gek, shared_dir async def test_webrtc_peer_cleanup_on_close(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: peer removed from _peers dict on session close.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -678,12 +679,12 @@ async def test_webrtc_peer_cleanup_on_close(sk_node, sk_hub, gek, shared_dir): async def test_webrtc_stream_segment_missing_file(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: stream_segment for non-existent file returns error.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -708,12 +709,12 @@ async def test_webrtc_stream_segment_missing_file(sk_node, sk_hub, gek, shared_d async def test_webrtc_wrong_gek_proof_rejected(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: wrong GEK proof is rejected — hub admin can't fake membership.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -768,12 +769,12 @@ async def test_webrtc_wrong_gek_proof_rejected(sk_node, sk_hub, gek, shared_dir) async def test_webrtc_dtls_channel_binding_detects_mitm(sk_node, sk_hub, gek, shared_dir): """WebRTC: DTLS channel binding detects fingerprint substitution (simulated MitM).""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -850,14 +851,14 @@ async def test_webrtc_admin_challenge_response(sk_node, sk_hub, gek, shared_dir, tmp_path): """WebRTC DataChannel: admin file delete requires Ed25519 challenge-response.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() sk_admin = Ed25519PrivateKey.generate() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["roster"] = await _paired_operator_roster(tmp_path, sk_admin) @@ -899,7 +900,7 @@ async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_ tmp_path): """WebRTC DataChannel: wrong Ed25519 signature is rejected — hub can't fake admin.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() sk_admin = Ed25519PrivateKey.generate() @@ -907,7 +908,7 @@ async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_ transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["roster"] = await _paired_operator_roster(tmp_path, sk_admin) @@ -946,12 +947,12 @@ async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_ async def test_webrtc_stream_request_missing_file(sk_node, sk_hub, gek, shared_dir): """WebRTC DataChannel: stream_request for non-existent file returns error.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -975,7 +976,7 @@ async def test_webrtc_stream_request_missing_file(sk_node, sk_hub, gek, shared_d async def test_webrtc_uploader_delete_requires_challenge(sk_node, sk_hub, gek, shared_dir): """Uploader must prove Ed25519 key ownership to delete — no uploader shortcut.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() sk_uploader = Ed25519PrivateKey.generate() @@ -986,7 +987,7 @@ async def test_webrtc_uploader_delete_requires_challenge(sk_node, sk_hub, gek, s transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) # No admin_pk configured — only uploader_pk should authorize deletion @@ -1032,7 +1033,7 @@ async def test_webrtc_uploader_delete_requires_challenge(sk_node, sk_hub, gek, s async def test_webrtc_uploader_impersonation_blocked(sk_node, sk_hub, gek, shared_dir): """Hub-forged JWT with same sub cannot delete — wrong Ed25519 key is rejected.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() # User A uploaded the file @@ -1047,7 +1048,7 @@ async def test_webrtc_uploader_impersonation_blocked(sk_node, sk_hub, gek, share transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) # No admin_pk — only uploader_pk matters @@ -1117,7 +1118,7 @@ async def test_invite_then_join_delivers_the_gek(sk_node, sk_hub, gek, shared_di that lookup was H3. """ hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() roster = Roster(db_path=tmp_path / "roster.db") @@ -1125,13 +1126,13 @@ async def test_invite_then_join_delivers_the_gek(sk_node, sk_hub, gek, shared_di transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["roster"] = roster transport._ctx["has_admin_authority"] = True transport._ctx["groups"] = { - TEST_GROUP: {"gek": gek, "shared_root": shared_dir, "index": indexer.index}, + TEST_GROUP: {"gek": gek, "roots": shared_dir, "index": indexer.index}, } # A paired operator, as `meshbay-node operator pair` would have left it. @@ -1229,7 +1230,7 @@ async def test_gek_bundle_fetch_during_handshake(sk_node, sk_hub, gek, shared_di tmp_path, x25519_keypair): """Browser fetches GEK bundle from node during the handshake challenge window.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() sk_x_raw, pk_x_raw = x25519_keypair @@ -1244,7 +1245,7 @@ async def test_gek_bundle_fetch_during_handshake(sk_node, sk_hub, gek, shared_di transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["bundle_store"] = bundle_store @@ -1328,7 +1329,7 @@ async def test_gek_bundle_fetch_during_handshake(sk_node, sk_hub, gek, shared_di async def test_keypair_bundle_store_and_fetch(sk_node, sk_hub, gek, shared_dir, tmp_path): """Keypair bundle stored on node, then fetched during handshake window.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() bundle_store = BundleStore(db_path=tmp_path / "bundles.db") @@ -1336,7 +1337,7 @@ async def test_keypair_bundle_store_and_fetch(sk_node, sk_hub, gek, shared_dir, transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["bundle_store"] = bundle_store @@ -1415,7 +1416,7 @@ async def test_keypair_bundle_store_and_fetch(sk_node, sk_hub, gek, shared_dir, async def test_keypair_bundle_fetch_not_found(sk_node, sk_hub, gek, shared_dir, tmp_path): """Keypair bundle fetch returns found=false when no bundle exists.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() bundle_store = BundleStore(db_path=tmp_path / "bundles.db") @@ -1423,7 +1424,7 @@ async def test_keypair_bundle_fetch_not_found(sk_node, sk_hub, gek, shared_dir, transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["bundle_store"] = bundle_store @@ -1492,7 +1493,7 @@ async def test_gek_not_auto_activated_on_bundle_store(sk_node, sk_hub, gek, shar through the node's local admin UI or CLI. """ hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() sk_x_raw, pk_x_raw = x25519_keypair @@ -1504,7 +1505,7 @@ async def test_gek_not_auto_activated_on_bundle_store(sk_node, sk_hub, gek, shar transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["bundle_store"] = bundle_store @@ -1547,12 +1548,12 @@ async def test_gek_not_auto_activated_on_bundle_store(sk_node, sk_hub, gek, shar async def test_webrtc_no_gek_connection_refused(sk_node, sk_hub, shared_dir): """WebRTC DataChannel: connection refused when GEK is not initialized.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=None) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=None) await indexer.initial_scan() transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=None, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) @@ -1594,7 +1595,7 @@ async def test_webrtc_no_gek_connection_refused(sk_node, sk_hub, shared_dir): async def test_gek_bundle_fetch_not_found(sk_node, sk_hub, gek, shared_dir, tmp_path): """GEK bundle fetch returns found=false when no bundle exists.""" hub_pk_pem = _hub_pk_pem(sk_hub) - indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek) + indexer = DirectoryIndexer(roots=one_root(shared_dir), group_id="g", sk_node=sk_node, gek=gek) await indexer.initial_scan() bundle_store = BundleStore(db_path=tmp_path / "bundles.db") @@ -1602,7 +1603,7 @@ async def test_gek_bundle_fetch_not_found(sk_node, sk_hub, gek, shared_dir, tmp_ transport = WebRTCTransport( sk_node=sk_node, hub_pk_pem=hub_pk_pem, gek=gek, - shared_root=shared_dir, index=indexer.index, + roots=one_root(shared_dir), index=indexer.index, stun_servers=[], ) transport._ctx["bundle_store"] = bundle_store |