fix(nests): address self-audit findings on the interop transport fixes

- QuicWebTransportFactory: re-throw CancellationException from the bounded
  handshake instead of wrapping it in WebTransportException, so a
  parent-scope cancellation no longer breaks structured concurrency.
  Mirrors the existing handling on the post-CONNECT path.
- NostrNestsHarness: correct two misleading comments — the dev endpoint's
  IPv4 guarantee comes from QuicWebTransportFactory's resolve step, not
  from `localhost` itself; and DEFAULT_REVISION is documented as tracking
  `main` (a known drift risk against the pinned moq-relay), not pinned.

https://claude.ai/code/session_01PoQupfdoKU3ryQwLwTeXeM
This commit is contained in:
Claude
2026-05-14 23:02:52 +00:00
parent ec92a82e4e
commit 5d406c5998
2 changed files with 24 additions and 4 deletions
@@ -143,6 +143,14 @@ class QuicWebTransportFactory(
conn.awaitHandshake()
true
}
} catch (ce: kotlinx.coroutines.CancellationException) {
// A parent-scope cancellation propagates out of withTimeoutOrNull
// (it only swallows its OWN TimeoutCancellationException). Wrapping
// it in HandshakeFailed would break structured concurrency — close
// the driver but re-throw the cancellation untouched. Mirrors the
// CancellationException handling on the post-CONNECT path below.
driver.close()
throw ce
} catch (t: Throwable) {
driver.close()
throw WebTransportException(
@@ -86,9 +86,17 @@ class NostrNestsHarness private constructor(
private fun isExternal(): Boolean = System.getProperty(EXTERNAL_PROPERTY) == "true"
/**
* Pin the nostrnests revision to a known-good SHA. Bump deliberately
* — drift on `main` should not silently change interop expectations.
* Override at runtime via `-DnestsInteropRev=<sha-or-branch>`.
* The `nostrnests/nests` revision the harness checks out — this is
* the repo that supplies the `moq-auth` token-minting sidecar.
*
* NOT currently pinned: it tracks `main`. That's a known drift risk
* — `moq-auth`'s JWT format must stay compatible with the
* `moq-relay` version pinned in [DEFAULT_MOQ_REVISION]
* (`moq-relay-v0.10.10`). If nostrnests advances `moq-auth` past
* what 0.10.10 accepts, the pair desyncs again and the relay
* rejects every connection with `failed to decode the token`. Pin
* this to a SHA known-compatible with 0.10.10 once one is
* identified. Override at runtime via `-DnestsInteropRev=<sha-or-branch>`.
*/
const val DEFAULT_REVISION = "main"
@@ -222,7 +230,11 @@ class NostrNestsHarness private constructor(
// there, and a strict relay (rustls) rejects an IP-literal SNI
// and then has no SNI to select its dev cert on — the handshake
// stalls. `localhost` is a valid hostname and matches the dev
// cert moq-relay generates. Resolves to 127.0.0.1 regardless.
// cert moq-relay generates. The UDP socket itself still goes to
// IPv4 loopback: QuicWebTransportFactory resolves the host with
// an IPv4 preference (`localhost` often resolves to ::1 first,
// and Docker's IPv6 UDP forwarding blackholes), while keeping
// `localhost` as the SNI name.
moqEndpoint = "https://localhost:$MOQ_HOST_PORT/",
)
}