Files
alktunnels/tasks/tunnels/coverage-weak-spots.md
T
glm-5.3-flash 0ceecf582b docs: remove em dashes from repo prose and forbid them going forward
- Rewrote the remaining em dashes outside docs/reviews/ (preserved as
  historical record, matching the alktty precedent): tests/ (313),
  fuzz/ (34 plus one shell comment), tasks/ (671 plus 12 kept in
  fences), docs/research + sdd_process + plans (525 plus 25 in
  fences), docs/architecture/overview.md fence labels (13), README,
  CHANGELOG, AGENTS.md, fuzz/README.md (176), and the
  .opencode/agents prompts (110)
- Rewrote fenced content too: ASCII tree and module-map label
  separators, Rust snippet comments, and template placeholders; wire
  data, JSON/BAST examples, and transcripts survive verbatim
- Rewrote 6 assert/expect message literals in tests/ and 2 format
  strings in fuzz/shared/src; no test data changed
- Added Project Convention 18: no em dashes in prose (doc comments,
  markdown including docs/ and tasks/, agent prompts, commit
  messages); fence content rule, en-dash clause rule, and the
  no-spaced-hyphen prohibition follow alktty's convention 15

Follows 6b20924 (src doc comments) and cd0afe0 (docs/architecture).

Verification: cargo test (141 pass); cargo clippy --all-targets -D
warnings; cargo fmt --check; cargo doc --no-deps; wasm check and
clippy for wasm32-unknown-unknown with -D warnings; em dash grep over
the repo returns matches only in docs/reviews/
2026-11-03 14:12:46 +00:00

7.0 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
tunnels/coverage-weak-spots Coverage weak spots, CLOSED (2026-09-09 second pass): the UdpHalf sender-block recipe found, feed infallible, wrappers covered completed
tunnels/review-impl
single low component implementation
tests
coverage
udp
review-remediation

Resolution (2026-09-09, second pass)

The 2026-09-09 first pass (commits 4014ba6, 8f14fd1) closed the behavioral gaps and left this task with the option-1-vs-3 decision. The second pass found the sender-block recipe, took option 1, and coverage moved 92.86% → 93.91% lines (50 → 41 uncovered). Three commits:

  1. DatagramReader::feed is infallible, the same zombie category as 4014ba6's InvalidLength: with the oversize bound enforced at frame time, the incremental decode cannot fail, so the Vec<Result> shape and local/mod.rs's dead InvalidData mapping were removed (pre-consumer window open per ADR-005's N-3).
  2. The sender-block machinery test (udp_half_write_side_blocks_ stashes_and_drains_on_resolve): the recipe that reached the WouldBlock stash, the readiness-Pending arms, AND the high-water backpressure in one coherent behavior (option 1).
  3. The thin wrappers, connect_udp's resolve-failure arm (.invalid NXDOMAIN → dial_failed) and the no-witness tunnel_establisher (a harness DialNoWitness mode + a full open round-trip through the wrapper).

The sender-block recipe (the host-blocking finding, RESOLVED)

UdpHalf's write-side machinery needed a UDP socket whose try_send persistently reports WouldBlock/ENOBUFS. The recipe (validated 3/3 deterministic on this host, kernel 6.8.0-110-generic, tokio 1.53.1, socket2 0.6.5):

  • A veth pair with the peer address UNASSIGNED + a flushed neighbor table. The connected sender's datagrams queue on the unresolved neighbor while charged to sk_wmem_alloc; with a shrunken SO_SNDBUF the charge exceeds the buffer → persistent EAGAIN/ENOBUFS (the drain reports 105=ENOBUFS alongside EAGAIN; both mean "the socket cannot take this datagram now", which the pump_queue_to_socket stash arm now matches too).
  • Jumbo MTU (65535) on the fixture: a 60 KB datagram crosses as ONE frame, with no IP fragmentation, so no fragment-reassembly races at the peer (fragment-ID collisions under the drain burst merged datagrams on an MTU-1500 veth; the peer reassembled 5-6 datagrams into single ~43947-byte payloads).
  • The block-state probe runs on a THROWAWAY socket: an oversized probe datagram's partially-built skb chain stays corked in sk_write_queue on EAGAIN and flushes on the next successful send, poisoning the socket with a stale partial datagram. The test's real socket is created fresh after the probe.
  • Assigning the peer address + binding the peer resolves ARP; the queued/stashed datagrams drain and DELIVER (the resolve step).
  • Root-gated (ip link add): the fixture tries bare ip then sudo ip and auto-skips loud-free without either.

The first pass's kernel findings still hold and are why the loopback recipes failed there: a non-reading peer's full receive queue DROPS datagrams silently (loopback/veth/netem: the sender never blocks); netem with limit still did not block (2M sends Ok in a probe).

Negative result: the ICMP ECONNREFUSED arm is unreachable through the poll drive

A connected UDP socket + a closed peer port elicits an ICMP port unreachable that ECONNREFUSEDs the next recvfrom (a plain std nonblocking recv surfaces it deterministically; probed rootless). But tokio 1.53 structurally masks it out of the poll drive (the adapter's shape): the EPOLLOUT|EPOLLERR event maps to WRITABLE|ERROR|WRITE_CLOSED; poll_recv_ready's Direction::Read mask is READABLE|READ_CLOSED (ERROR excluded) → Pending forever; try_io(READABLE) intersects empty → WouldBlock. Only the async recv() (async_io with READABLE|ERROR) surfaces ECONNREFUSED, but UdpHalf::poll_read is a poll impl. Verified by probes (poll_recv, poll_recv_ready, try_recv all Elapsed; the async recv surfaced it exactly once, racing the waiter registration, hence nondeterministic). local/mod.rs:356 therefore joins the defensive list: no deterministic test can reach it through the pump's drive on tokio 1.53.

The final uncovered-line inventory (41 lines, all deliberate)

  • src/local/mod.rs:136-137, the no-addresses resolve arm: a name that RESOLVES to zero addresses is unreachable via getaddrinfo (NXDOMAIN errors first; the .invalid test hits the error arm).
  • src/local/mod.rs:321-333: the Oversize mapping at the recv scratch (a >65535-byte datagram cannot exist on a real wire; the IP theoretical max is 65507).
  • src/local/mod.rs:351-352,356, the recv-side readiness-Pending arms (genuine WouldBlock) plus the ICMP error mapping (the negative result above).
  • src/local/mod.rs:378-379,383: the high-water drain's Ready(Ok)/Ready(Err) sub-arms (the observed over-line poll rides the Pending sub-arm; the Ok sub-arm needs the drain to succeed within that single poll, the FAILED-cycle release timing).
  • src/local/mod.rs:476-477, pump_queue_to_socket's poll_send_ready Ready(Ok)/Err sub-arms (the Pend sub-arm is the covered one).
  • src/consumer.rs:91-94,405-406: serde_json::to_value failures on TunnelParams (impossible by construction).
  • src/consumer.rs:205,290, unreachable! guards on spent sessions.
  • src/consumer.rs:285, the stale-pump abort (defensive only).
  • src/consumer.rs:325-330, the pump JoinError telemetry arm (needs the spawned pump to panic/abort, which is not producible through the session API).
  • src/producer.rs:85-86: the HandlerError mapping (the schema gate preempts it; pinned by schema_gate_rejects_missing_substrate_…).
  • src/producer.rs:338-347, the pump-handler telemetry early-returns (accept_bi failure needs a dead channel; the plan is always TargetHandle; Arc::try_unwrap needs a second clone).
  • src/wire.rs:77-79: the Default impl shim (clippy's new_without_default).
  • src/wire.rs:106, the unreachable! invariant in feed's loop.
  • src/wire.rs:177, a unit test's own panic line (the negative branch of datagram_split_across_awkward_chunks_reassembles).

Verification (2026-09-09, second pass)

  • cargo llvm-cov --all-features --workspace --summary-only reports 93.91% lines (from 92.86%; 50 → 41 uncovered, all deliberate).
  • cargo test --all-features passes with 91 tests green (15 lib
    • 16 consumer_session + 18 end_to_end + 13 doc/lib + 19 local_halves
    • 9 producer_listen + 13 producer_open_op + 1 doc-test compile_fail).
  • cargo test (default) is green; the root-gated veth test skips loud-free without root.
  • cargo clippy --all-targets --all-features -- -D warnings and cargo fmt --check are clean.
  • cargo check --target wasm32-unknown-unknown + cargo clippy --target wasm32-unknown-unknown -- -D warnings are clean (the default crate stays wasm-clean).