<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/src/meshbay_node/transport/quic_client.py, branch 0.10</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.10</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.10'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-08-13T10:24:54Z</updated>
<entry>
<title>feat(quic): GEK proof and mutual authentication — closes C6</title>
<updated>2026-08-13T10:24:54Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-13T10:24:54Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=146a6759fa73386e9b59570956aeedd7e1cfd978'/>
<id>urn:sha1:146a6759fa73386e9b59570956aeedd7e1cfd978</id>
<content type='text'>
Phase 11.5.4/5/6 — finding C6, the last open critical finding.

QUIC ran a JWT-only handshake: a forged or stolen token reached the node and
could inject chat without ever holding the group key. It now runs the same
challenge/response as WebRTC through meshbay_common.handshake — client nonce,
role-bound length-prefixed transcript, GEK proof, and the node proving itself
with a GEK proof plus an Ed25519 signature over the transcript (C3).

11.5.6 channel binding, resolved by spike and then by two findings the spike
could not predict:

  * aioquic 1.3.0 exposes no RFC 5705 exporter, and the peer certificate only
    via a private attribute. The server reads its own certificate from disk, so
    no internals are touched on that side; the client's access is guarded and
    fails loudly if an upgrade moves it.
  * A RESUMED TLS session carries no certificate — aioquic does not re-send it,
    so there is nothing live to bind to. The anchor therefore travels with the
    session ticket, which is sound because the ticket is cryptographically
    derived from the handshake where that certificate was presented.
  * The anchor had to travel with the ticket rather than live on the client
    object: resumption constructs a fresh client, so an instance-level cache
    was silently useless. Caught by the resumption test, not by inspection.

Both paths refuse rather than degrade. No certificate and no cached anchor
means the handshake fails; it never falls back to an unbound proof, which would
silently drop MitM detection (L4).

QuicChunkClient gains a peer_cert_der property and constructor argument,
mirroring how session_ticket is already carried by the caller.

Tests: 9 quic/multi-group, full node+common suite green.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: Phase 9 — Web client SPA with WebRTC P2P transport</title>
<updated>2026-08-11T02:13:53Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-11T02:13:53Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=e23e33adeaf8ee7439187d4451c856b37816a51f'/>
<id>urn:sha1:e23e33adeaf8ee7439187d4451c856b37816a51f</id>
<content type='text'>
Complete browser-based client: Preact SPA with login, group file browser,
encrypted download, video playback, group chat, i18n, and dark/light theme.
Browser connects P2P to nodes behind residential NAT via WebRTC DataChannel
(aiortc). Hub handles signaling only — all data flows E2E.

Performance: pipelined downloads (8-chunk sliding window), binary msgpack
wire format (no base64), redundant I/O elimination. Large file downloads
stream to disk via File System Access API (showSaveFilePicker).

Validated on SFR + Orange residential NATs, Chrome + Firefox, IPv4/IPv6.
132 tests passing. Deployed to meshbay.org + Orange node.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: Phase 7 — Node v2 (multi-group, Sender Keys, 0-RTT, chat, denylist)</title>
<updated>2026-08-10T01:07:56Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-10T01:07:56Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=4b3e8c3b8b9d10c8ac333dd8db614a7569052472'/>
<id>urn:sha1:4b3e8c3b8b9d10c8ac333dd8db614a7569052472</id>
<content type='text'>
Implements all 8 milestones (7.0-7.7):

- 7.0: JWT carries `groups` claim; node verifies group membership at
  MNP handshake (QUIC + TCP+TLS). Resolves security review C2.
- 7.1: QUIC 0-RTT session resumption via stored session tickets
  (17-21ms reconnect vs 47ms cold).
- 7.2: Hub→node WebSocket signaling for NAT punch coordination
  (`client_incoming`/`punch_ready`) + jti denylist push. Denylist
  class blocks revoked users/jtis at handshake.
- 7.3: Multi-group daemon — one QUIC port serves N groups with
  per-group GEK, shared_root, and index routing.
- 7.4: HLS streaming via QUIC (STREAM_SEGMENT message type, ffmpeg
  segment extraction).
- 7.5: Sender Keys protocol for group chat (Signal Groups approach).
  Each member has own sending chain key, HKDF chain ratchet, AES-256-GCM
  encryption, Ed25519 signing. Resolves security review C1.
- 7.6: Chat store (SQLite via aiosqlite), CHAT_MESSAGE MNP wire type
  with peer broadcast, web UI with WebSocket push.
- 7.7: Argon2id calibration CLI.

First security review included (first-review.md). 109 tests, demo-v3
validated against meshbay.org production hub.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(node): QuicChunkClient local_port + QuicChunkServer dual-stack</title>
<updated>2026-08-09T22:12:40Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-09T22:12:40Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=618d5b8515550a1b2d89e1cd045f7fba271f9374'/>
<id>urn:sha1:618d5b8515550a1b2d89e1cd045f7fba271f9374</id>
<content type='text'>
local_port=0 param on QuicChunkClient — specify for Port-Restricted Cone NAT
hole punching (client must send from the same port the node probed to).
QuicChunkServer default host '::' for IPv4+IPv6 dual-stack on Linux.

Co-Authored-By: Claude Sonnet 4.6 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(node): add QUIC transport (MNP v2) — quic_server + quic_client</title>
<updated>2026-08-09T03:13:51Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-09T03:13:51Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=88cfc139333ac3fe5789f39f3970065181df9043'/>
<id>urn:sha1:88cfc139333ac3fe5789f39f3970065181df9043</id>
<content type='text'>
QuicChunkServer/QuicChunkClient: same MNP protocol over QUIC/UDP.
Enables hole-punching (Spike 4 Cone NAT validated). Uses aioquic 1.3.0.

Bug found+fixed: asyncio.Event race condition in client recv loop
(quic_event_received overwrote _stream_events[0] after _recv
created it). Fixed with asyncio.Queue (no shared mutable state).

Server uses synchronous handlers in quic_event_received (avoids
ensure_future transmit timing issue). 3/3 tests. Full suite: 50/50.

Co-Authored-By: Claude Sonnet 4.6 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
