You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Every row of conformance-matrix.md, and what covers
it, at Nowhere v3.0.1. Eighty-nine rows, in the matrix's own order.
A row is in one of two states, and there is no third:
covered — a named test or script. Run it and it either passes or it does not.
manual — no automated test, with the reason it cannot have one and what
to do instead. A reason, never "todo".
Test names are Class.method. Unless noted they are JVM unit tests run by
./gradlew testDebugUnitTest. (Portal) marks a JVM test that needs a live
Portal (eval "$(conformance/scripts/portal-for-tests.sh)") and skips without
one; (device) marks instrumentation, run with the arguments in
conformance/README.md; scripts are in conformance/scripts/.
The v1.8.2 map — 111 rows, including the TLS Mux and split-carrier sections v3
deleted, and the findings writing it produced — is cases/l1-coverage.md in
git history up to 8f16af2.
1. Authentication
#
Case
State
Covered by
1
Salt, root and both role keys match upstream's vectors
covered
AuthVectorTest.everyPositiveVectorIsReproduced, VectorFixtureTest.theAnchorVectorIsIntact; recomputed by verify-vectors.py
AuthVectorTest.plusIsALiteralPlusAndNotASpace, ImportLinkTest.a shared key's literal plus is not turned into a space
11
Tag comparison is constant time
covered
ConstantTimeComparisonTest.theAuthenticationTagIsNeverComparedWithAByteWiseEquality, .theTagComparisonUsesAConstantTimeCall — a source rule, because a timing-unsafe comparison passes every functional test
12
A wrong key is never answered
covered
oracle-diff.sh cases wrong_key (Morph on: the handshake fails, both sides) and nomorph_wrong_key (Morph off: the Portal closes, both sides), over both carriers; SessionAgainstPortalTest.aWrongKeyFailsBeforeAnythingIsAuthenticated(Portal); QuicAuthenticationTest.aWrongSharedKeyIsNotAnswered(device)
DedicatedTlsLaneTest.theOpeningIsOneWriteAndThePayloadWaitsForReady, .aRejectedFlowNeverSendsItsPayload, NowhereSessionTest.theFirstPayloadIsSentOnceThePortalAnswers; SessionAgainstPortalTest.theFirstPayloadReachesTheTarget(Portal) — the case that found it
30
One connection per flow
covered
DedicatedTlsLaneTest.aLaneCarriesExactlyOneFlow, NowhereSessionTest.eachFlowGetsItsOwnConnectionAndItsOwnId; oracle-diff.shtls_connections (exactly 16 for 16 held flows, both implementations); e2e-fakeip.sh on a device
oracle-diff.sh — every case over TLS and QUIC, Morph on and off; QuicPayloadTest.theSameBlobOverTlsAndOverQuicProducesTheSameDigest, QuicDatagramTest.*(device)
Set in the bridge (max_udp_payload) and in QuicConnection.open; observable only as the absence of loss on a 1500-byte path. The device and oracle runs carry 20 MiB with Morph on, which is where an oversized packet would show as a stall
60
Both modes interoperate; a mismatch fails
covered
oracle-diff.sh (all cases with Morph on and off); NowhereDialerAgainstPortalTest.aMorphMismatchFailsTheHandshake(Portal)
9. Configuration and certificates
#
Case
State
Covered by
61
Parse a share link
covered
NowhereUrlTest.theClientSchemeIsNowhere and thirty-five further cases
NowhereUrlTest.generatedUrlsParseBackToTheSameNode, NowhereUrlRoundTripFuzzTest.*. The dashboard half needs a running NowhereDash; NowhereDash at c753043 targets Nowhere 2.1.1 and does not yet emit v3 links
NowhereDialerAgainstPortalTest.aWrongPinIsRefusedAndNamesWhatWasPresented(Portal); QuicPinTest.oneWrongNibbleStopsTheHandshake(device) — the pin is the one the Portal logged, so a pass cannot be the client agreeing with itself
72
Refused by name on a device
covered
ChainVerificationOnDeviceTest.*(device). The acceptance half — a chain this device trusts — is manual: it needs a CA key a test can sign with, and committing one would make every debug build trust its reader. PortalLifecycleTest accepts a chain by name against a live Portal on the JVM
73
ALPN nw3
covered
oracle-diff.sh (every case negotiates it); DialReason.AlpnRejected is the observable mismatch — a Portal that refuses aborts the handshake instead, see CLAUDE.md fact 11
10. Dashboard integration
#
Case
State
Covered by
74
Fetch and parse
covered
SubscriptionFetcherTest.nodesAreFetchedAndParsed, against a real local HttpServer
SubscriptionEndpointTest.redactsTheToken and six further cases, SubscriptionFetcherTest.noFailureReasonEverContainsTheToken, FailureMessageTest.noReasonCarriesKeyMaterialMarkers
SubscriptionEndpointTest.appendsTypeVersionAndCapabilities, SubscriptionFetcherTest.capabilityParametersAreActuallySent — caps is now nw3,quic
11. Cross-cutting
#
Case
State
Covered by
84
Decoders survive arbitrary bytes
covered
DecoderFuzzTest.* over eleven decoders including MorphDatagram.open; DnsInterceptorTest.arbitrary bytes neither crash nor allocate without bound; NowhereUrlRoundTripFuzzTest.*; ImportLinkTest.arbitrary text neither throws nor produces something longer than it was given
85
Headers before variable data
covered
DecoderFuzzTest.aHostileLengthFieldNeverDrivesAnUnboundedAllocation, TargetVectorTest.aHostileLengthByteCannotDriveAnUnboundedRead, UdpOverTcpVectorTest.aDeclaredLengthCannotDriveAnUnboundedRead, DnsMessageTest.a label length past the end of the message does not read past it
oracle-diff.sh — 22 cases and 2 connection counts, every case over four carrier and Morph combinations. Found two defects on its first v3 runs; see below
88
Remote resolution on a device
covered
e2e-fakeip.sh — the origin is reachable only by a name that resolves on the Portal's docker network, and it hears only from the Portal
89
Coverage ≥ 90%
covered
koverVerifyDebug — 91.7% at this baseline
Summary
88 of 89 rows covered by an automated test or script, one manual with its
reason (row 59), and none blocked. Two rows are covered with a stated gap:
row 67's dashboard half, because NowhereDash does not yet emit v3 links, and
row 72's acceptance half, for the reason given there.
What the first v3 runs found
Each of these was invisible to the vectors, which agreed with the client the
whole time, and each looked like something other than what it was.
The first payload was riding the opening write. v1 allowed it and this
client did it on purpose, to save a round trip. A v3 Portal watches the
stream while it dials and ends the flow on an early byte ("target payload
arrived before READY"). Every TCP flow that had its first bytes in hand when
it opened — most of them — would have been torn down. Found by
SessionAgainstPortalTest.theFirstPayloadReachesTheTarget.
A refused AuthFrame over QUIC surfaced as a transport failure. v3
closes the connection on a bad tag. Over TLS that reached the client as an
end of stream, "no setup byte"; over QUIC the native connection error
escaped the stream's read, and oracle-diff.sh showed the oracle reading
the same event as "no setup result". The stream transport now presents a
dead connection as the I/O failure its contract promises.
The harness's pin came from a Portal that was not answering. A Portal
started inside $(…) recorded its PID in a subshell, outlived the run, and
held the port; the next run's Portal failed to bind after logging a
fingerprint of its own. Both implementations then agreed on every case —
that the certificate was wrong. Agreement on a failure is still agreement,
which is why the script now refuses to start on an occupied port.
Sixteen held flows counted as three connections. The burst's overlap
lasted only as long as the last arrival took to be answered, which was
shorter than the socket-table sampler's interval. The origin now holds its
answers for two seconds after the barrier.