docs(quic+nestsClient): post-implementation status + audio-rooms completion plan

Two new module-local plan docs (per CLAUDE.md's "plans live in the owning
module" rule) and a sweep of stale inline phase references.

quic/plans/2026-04-26-quic-stack-status.md:
  Post-mortem of the original docs/plans/2026-04-22 plan. Documents
  what shipped vs what was estimated, the actual package layout (~8.5k
  LoC, 39 test files, 5 audit rounds), the crypto delegation surface
  (Quartz only — no BouncyCastle, no JNI), interop verification status
  (aioquic + picoquic; nests not yet), and known deferred items
  (STREAM retransmit, Initial-key discard, etc.).

nestsClient/plans/2026-04-26-audio-rooms-completion.md:
  Punch list to ship audio rooms end-to-end:
    M1 Listener wire-up in Amethyst UI
    M2 Multi-speaker audience UX
    M3 Foreground service for backgrounded playback
    M4 Manual interop pass against nostrnests.com
    M5 MoQ publisher path (ANNOUNCE / TrackPublisher)
    M6 Capture → encode → publish pipeline
    M7 NestsSpeaker API
    M8 App polish (reconnect, leave cleanup)
    M9 Foreground service for speakers
  ~6 weeks for full audio rooms; ~2 weeks for listener-only MVP.

Inline doc cleanup:
  * Removed "Phase 3a/3c-1/3c-2/3c-3" / "Phase B/C/D-K/L" references
    from active code; replaced with "today" or pointers to the
    completion plan
  * Removed "Kwik-based stub" references; QuicWebTransportFactory and
    surrounding docs now describe :quic as the production path
  * TlsClient header reflects non-null certificateValidator + the
    JdkCertificateValidator / PermissiveCertificateValidator split
  * SendBuffer header documents the best-effort no-retransmit mode
    explicitly (was hidden behind a "Phase L will fix this" note)
  * MoqMessage / MoqObject / MoqSession reflect listener-side as
    shipped + publisher-side as Phase M5

CLAUDE.md:
  * Module list now includes :quic and :nestsClient (was 5 modules,
    now 7)
  * Architecture diagram + sharing philosophy explain what each new
    module owns

No production behaviour changes; doc + comment-only edits. Tests green.

https://claude.ai/code/session_01EC1tfXfap8k8GyKvrxkxZx
This commit is contained in:
Claude
2026-04-26 01:38:48 +00:00
parent 7f05fd6e2a
commit 4338e5e6c4
14 changed files with 529 additions and 45 deletions
@@ -33,8 +33,11 @@ import com.vitorpamplona.quic.tls.deriveQuicKeys
* TLS traffic secret + TLS cipher-suite identifier. The QUIC labels in
* RFC 9001 §5.1 (`quic key`, `quic iv`, `quic hp`) drive the expansion.
*
* For Phase BK we only support TLS_AES_128_GCM_SHA256 (16/12/16) and
* TLS_CHACHA20_POLY1305_SHA256 — the SHA-256 suites; nests speaks both.
* Supports the two SHA-256-keyed cipher suites required for QUIC v1
* interop with nests / aioquic / picoquic: TLS_AES_128_GCM_SHA256
* (16/12/16) and TLS_CHACHA20_POLY1305_SHA256. AES-256-GCM-SHA384 is
* omitted — Quartz's primitives don't ship SHA-384 and no interop target
* we've encountered requires it.
*/
fun packetProtectionFromSecret(
cipherSuite: Int,
@@ -27,14 +27,16 @@ package com.vitorpamplona.quic.stream
* Application code [enqueue]s payload bytes; the connection's send loop
* [takeChunk]s as much as it can fit in the next packet, given the
* remaining packet budget and stream-level / connection-level flow control
* credit. Sent bytes stay in the buffer until [acknowledge] (Phase F adds
* retransmission of lost bytes; for v1 we just trust the receiver and
* release on send).
* credit.
*
* For Phase D-K we run a "best effort" mode: bytes are released from the
* **Best-effort mode (no STREAM retransmit):** bytes are released from the
* buffer the moment they're handed off, on the assumption that the
* underlying network is stable. Phase L adds retransmit-on-loss (using the
* same send buffer that retains until ACK).
* underlying network is stable. A real loss event silently truncates the
* stream. Acceptable for MoQ over QUIC (audio rooms use OBJECT_DATAGRAM,
* which is loss-tolerant; STREAM is control-plane only). See the deferred
* items in `quic/plans/2026-04-26-quic-stack-status.md` — adding
* retain-until-ACK + retransmit is the first thing to add for general
* STREAM-heavy use.
*/
class SendBuffer {
/**
@@ -41,10 +41,12 @@ import com.vitorpamplona.quic.QuicWriter
* 2. After ServerHello arrives → install Handshake keys both directions.
* 3. After server Finished decoded → install 1-RTT (application) keys both directions.
*
* For Phase B we **do not yet validate the certificate chain or the
* CertificateVerify signature**. That's wired in during Phase C/L when we
* have a real server to talk to. We DO compute and verify the server
* Finished MAC.
* Certificate chain validation + CertificateVerify signature verification
* are delegated to [certificateValidator] (`JdkCertificateValidator` in
* production; `PermissiveCertificateValidator` for in-process tests). The
* validator parameter is non-null — passing `null` was a silent-MITM
* hazard and was removed in round-4 of the audit. We also compute and
* verify the server Finished MAC ourselves.
*/
class TlsClient(
val serverName: String,