<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-hub/src/meshbay_hub/api/signaling.py, branch 0.2</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.2</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.2'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-08-13T09:18:24Z</updated>
<entry>
<title>fix: resource limits, signaling authz, node admin UI token</title>
<updated>2026-08-13T09:18:24Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-13T09:18:24Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=b86be704df752f2fd3086fcca43b7f4de78389d1'/>
<id>urn:sha1:b86be704df752f2fd3086fcca43b7f4de78389d1</id>
<content type='text'>
Phase 11.5 — findings H6, C4 (partial), and milestone 11.5.3.

H6 — resource exhaustion. Several paths let one peer degrade or stall a node:

  * the DataChannel frame limit was a flat 64 MB applied BEFORE authentication,
    so an unauthenticated peer could announce a huge frame and dribble bytes
    into it. Unauthenticated peers now get 64 KB; the large budget is granted
    only after the GEK proof, where it is needed for uploads.
  * _do_stream_segment ran subprocess.run(..., timeout=30) directly in the event
    loop, stalling the entire daemon — every peer, every group — for up to
    thirty seconds per request. Now async, with a timeout and process kill.
  * ffmpeg was spawned per stream request with no cap. Both streaming paths now
    share a transport-wide semaphore.
  * POST /v1/nodes/{id}/webrtc/offer was reachable by any authenticated user for
    any node, with no membership check and no rate limit, making the target node
    allocate an aiortc PeerConnection and gather ICE on demand — remote resource
    exhaustion against a third party's machine. Now rate limited, capped per
    user, SDP size bounded, and the caller must share an active group with the
    node. That also closes the H4 gap where signaling ignored group status.
  * POST /v1/nodes/{id}/incoming took peer_ip verbatim, so any user could make an
    arbitrary node emit UDP packets to an address of their choosing. The probe
    target must now match the caller's own source address.

C4 (partial) — the pre-proof bundle window. GEK and keypair bundle fetches are
served before the GEK proof by necessity: the client needs its wrapped bundle in
order to compute the proof. That window is a disclosure surface a hub can reach
by forging a JWT. Bounded to 4 fetches per session and audited as
"pre_proof_fetch". The real fix is removing remote keypair bundles entirely,
which belongs to the native client (Phase 13.3).

11.5.3 — the node admin UI was unauthenticated because it binds loopback. But
any local process can reach it, and so can a page in the operator's browser via
DNS rebinding — and this API re-initialises group keys and reads the audit log.
H2 showed script execution there equals full control. Now gated by a per-run
token, printed at startup, accepted as ?t= or X-MeshBay-Token.

One test needed rewriting rather than adding: the first version asserted
"subprocess.run(" was absent from the source, which also matched the comment
documenting the old behaviour. It now parses the AST and checks the property.

Tests: 121 node, 142 hub+common. Regression suite 47 node + 10 hub.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: Phase 9.1–9.5 — WebRTC DataChannel transport for browser P2P</title>
<updated>2026-08-10T20:12:59Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-10T20:12:59Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=60c4570e72e36c2a9720593c8baec74ee2ab52d6'/>
<id>urn:sha1:60c4570e72e36c2a9720593c8baec74ee2ab52d6</id>
<content type='text'>
Browser clients can now connect P2P to nodes behind residential NAT via
WebRTC DataChannel with ICE/STUN. Validated on SFR Port-Restricted Cone
NAT + 4G CGNAT across three scenarios (WiFi LAN, 4G IPv6, 4G IPv4 STUN).
No TURN relay needed. Hub serves only as signaling relay (&lt;1 KB).

New files:
- webrtc_server.py: aiortc-based WebRTC transport (node side)
- signaling.py: SDP/ICE relay endpoint (hub side)
- transport.js: browser WebRTC client with msgpack framing
- webrtc-test.html: spike test page for browser→NAT→node validation
- test_webrtc_transport.py: 4 tests (handshake, file transfer, auth, guard)
- meshbay-draft-v4.md: architecture spec updated for web client

Modified:
- hub_client.py: WebRTC offer handling via hub WebSocket
- revocation.py: node_id from WS auth + webrtc_answer routing
- pyproject.toml: aiortc&gt;=1.9 dependency

123 tests passing (117 existing + 6 new).

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
