review: phase-gate review 001 — spec conformance of the v1 implementation

Findings + review doc: docs/reviews/001-implementation-review.md (the
alkcall house pattern). Closes tunnels/review-core-crates and
tunnels/review-impl.

Findings:
- U-1 [major, NOT fixed] — the local UDP adapter is not the framed
  adapter ADR-003 mandates: codec-framed bytes reach real targets,
  empty datagrams are EOF-shaped at the adapter (tunnel teardown),
  >8 KiB datagrams split, unframed target-initiated datagrams are
  dropped. Executable-pinned by real-socket probes (temporary test,
  deleted after the run). Remediation task: tunnels/fix-udp-framed-adapter.
- C-1 [major, fixed] — AcceptQueue::pop lost wakeup in the
  check→register window (open op hangs to the establishment bound);
  fixed via the tokio notify_waiters contract (Notified created before
  the check each iteration) + multi-thread regression test.
- N-4/N-5/N-7/N-8/N-9/N-10/N-11 [minor, fixed] — serialize TunnelParams
  in open_reverse_channel; stale doc ref; broken doc link; root
  re-exports (TunnelParams/Substrate/tunnel_open_spec/OP_TUNNEL_OPEN);
  README (publish dry-run was failing on the missing readme); harness
  comment; pump_against UDP framing doc note.
- N-2 retracted by executable falsification (codec buffering is
  bounded by construction); N-6 non-finding with rationale.

Verified: 63 tests default / 70 with --features local, 3x repeat-run
clean both configs; clippy -D warnings (all-targets + wasm32); fmt;
doc warning-free; wasm32 check; cargo publish --dry-run passes.
This commit is contained in:
2026-09-08 10:58:11 +00:00
parent 2efac9b609
commit a0f939c6df
10 changed files with 975 additions and 21 deletions
+82
View File
@@ -0,0 +1,82 @@
---
id: tunnels/fix-udp-framed-adapter
name: "U-1 remediation — make UdpHalf the FRAMED adapter (ADR-003 at the local boundary)"
status: pending
depends_on: [tunnels/review-impl]
scope: moderate
risk: medium
impact: component
level: implementation
tags: [local, udp, codec, adr-003, review-remediation]
---
## Description
Review 001 finding U-1 (`docs/reviews/001-implementation-review.md`):
the `local` feature's `UdpHalf` (`src/local/mod.rs`) is NOT the framed
adapter ADR-003 mandates at the substrate boundary — it is
boundary-preserving (one datagram per poll_read/poll_write) but raw.
The `[len: u16 BE]` codec exists only on the session side, so
UDP-over-`local` tunnels:
1. deliver codec-framed bytes to real targets (the target sees
`[len]payload`, not payload — executable-pinned in the review
probes);
2. tear the tunnel down on an empty datagram (a raw zero-length
datagram is `Ok(())` with 0 bytes filled = EOF-shaped to
`tokio::io::copy` — the F-2 violation end-to-end; the session-side
codec exists precisely to prevent this);
3. split datagrams > ~8 KiB at the target (`tokio::io::copy`'s
`DEFAULT_BUF_SIZE` bounds each read; the raw adapter sends each
chunk as its own datagram);
4. silently drop unframed target-initiated datagrams (the session
codec parses a raw datagram's first two bytes as a length header).
The session-side tests pass because the harness's
`framed_udp_echo_dial` frames symmetrically at the test boundary — a
correct-shape stand-in for what `connect_udp` itself must do.
### The fix
Apply ADR-003's placement: `UdpHalf::poll_write` frames the caller's
buffer (`frame_datagram`) and sends one datagram per framed frame;
`poll_read` de-frames (feed `DatagramReader`, emit the next payload).
Both halves of the association then speak the same framing; `len=0`
becomes a 2-byte frame (unambiguous with EOF — the F-2 fix
end-to-end).
### Verification gates (from the review)
1. A recording UDP echo server asserts the datagrams it receives are
**payload bytes only** and an **empty datagram round-trips**
(session `recv_datagram` yields `Some(b"")`, channel alive).
2. A >8 KiB datagram round-trips as ONE datagram at the target.
3. An unframed target-initiated datagram resolves at the session.
4. The existing `local_halves` suite stays green unchanged (its
session-level round-trips are framing-symmetric today).
5. `cargo test` + `--features local` + wasm checks as usual; 3×
repeat-run stable.
### Riders (from the same review, same file)
- U-2: `connect_udp` binds `("0.0.0.0", 0)` — resolve the target
family first (or document the v4-only posture).
- U-3: size the recv scratch to the codec's MTU discipline instead of
a per-tunnel 65535-byte allocation (or justify the bound).
## Acceptance Criteria
- [ ] `UdpHalf` frames on write and de-frames on read (ADR-003's
placement; the pump stays raw)
- [ ] The 5 verification gates pass; suites green 3× in both configs
- [ ] U-2/U-3 riders resolved or explicitly deferred with rationale
- [ ] Review 001's U-1/U-2/U-3/N-1 sections get resolution notes
## References
- `docs/reviews/001-implementation-review.md` §U-1 (executable-pinned
probe evidence), §U-2, §U-3, §N-1
- `docs/architecture/decisions/003-codec-and-udp-framing.md` (the
framed-adapter mandate + F-2), `docs/architecture/wire.md`
§Datagram substrate
- `src/local/mod.rs` (`UdpHalf`), `src/wire.rs` (the codec to compose)