<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/tests/test_quic_transport.py, branch 0.5</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.5</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.5'/>
<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>refactor(quic): share the unified handshake authorization</title>
<updated>2026-08-13T09:56:04Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-13T09:56:04Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=be1ff89465c9878f2fbd641fb0d4eba729439ac8'/>
<id>urn:sha1:be1ff89465c9878f2fbd641fb0d4eba729439ac8</id>
<content type='text'>
Phase 11.5.4 — QUIC half. Findings M1, M9 on this transport.

quic_server._do_handshake_sync was a second, weaker copy of the WebRTC logic:
group_id was optional, so omitting it skipped the membership check entirely and
fell back to the node's first group (M1); node-scoped daemon tokens were
accepted as client tokens (M9); and the checks could drift from the WebRTC path
independently, which is how they diverged in the first place. Authorization now
comes from meshbay_common.handshake, shared with WebRTC.

C6 IS STILL OPEN ON THIS TRANSPORT. There is no GEK proof here yet: a forged or
stolen token still reaches the node over QUIC and can inject chat without
holding the group key. What remains is the challenge/response and the mutual
node proof — quic_binding() is written and unit-tested for exactly this, and
11.5.6 (whether a certificate hash is the right anchor, or an RFC 5705 exporter
is reachable from aioquic) is still unproven. This commit narrows the gap to
the proof itself; it does not close the finding.

QUIC tests updated: default tokens are members of the test group, and clients
pass group_id, since it is mandatory now.

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 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>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>
