42 KiB
status, last_updated, reviewed_artifacts, tool, reviewer, scope_note
| status | last_updated | reviewed_artifacts | tool | reviewer | scope_note | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| resolved | 2026-09-27 (the residue round closed — S-1/N-1/N-2 doc notes, D-1/D-2/D-3 + the N-8 probes landed as tests, the frontmatter YAML fixed; every finding closed or re-dispositioned) |
|
manual source read + cargo test/clippy/fmt/doc/wasm/publish-dry-run + cargo-llvm-cov + alktunnels 0.2.0 surface cross-checks | general implementation review (correctness + security + smells + coverage) | the batch-2 assembly layer only — the five new modules plus the batch-2 additions to consumer.rs/producer.rs; the batch-1 core was reviewed by review 002 and is not re-litigated here |
Review 003 — The Assembly-Layer Implementation (Post-Landing Full Review)
Purpose
General review of the batch-2 assembly layer after landing — the
eight-task group (tasks/implementation/{local-*,door-*,composed-*, assembly-integration-suite,review-assembly-layer}.md, commits
a867f0c..04c76e3). The narrow review
(tasks/implementation/review-assembly-layer.md) checked the eight
gate criteria (never-binds, seam contracts, door fidelity, graduation
shape, conventions, feature hygiene, POC fidelity, docs sync) and
fixed R-1/R-2 inline; this one asks the four questions that review
did not, following review 002's template:
- Correctness — hazards in the landed door/provider behavior itself: teardown races, pump-lifetime paths, protocol-state corruption, error-shape fidelity at the door boundary.
- Security — resource exhaustion on the kernel-socket paths the batch-2 code newly opens (doors, producer backend), gate fidelity, panic surfaces, log/credential handling.
- Code smells — convention compliance plus the structural smells an 8-task implementation round leaves behind (dead surface, duplication, doc drift, test-side posture).
- Coverage (
cargo-llvm-cov) — important gaps, attributed to specific behaviors and their risk.
Method note: line-level over the five batch-2 modules + the batch-2
diff surface of consumer.rs/producer.rs, with cross-checks against
alktunnels 0.2.0 (make_forwarded_op_handler, ForwardedHandler,
TunnelListener, TakenHalves) and the ADR set 003–014. The RFC
1928 core and the protocol-layer pump are re-read only where batch 2
calls into them.
Verification Baseline
All commands on the reviewed tree (post-fix; the review change itself):
cargo test: 375 green (default; the batch-2 suites are feature-gated out of the default build).cargo test --all-features: 620 green (up 5 from the gate's 615 — the review's pinning test + the UDP-door exit change).cargo clippy --all-targets --all-features -- -D warnings: clean.cargo fmt --check: clean.cargo doc --no-deps: clean (0 warnings).cargo publish --dry-run --allow-dirty: completes.- Wasm checks: default +
--features composedclean (check + clippy);localon wasm fails with exactly the expected mio unsupported-wasm error (the alktty posture, observed at the gate and re-verified). cargo llvm-cov --all-features: 93.68% lines / 91.01% functions / 92.97% regions (6485 covered / 410 missed).
Coverage breakdown
| Module | Lines | Functions | Regions |
|---|---|---|---|
| composed/mod.rs | 77.32% | 65.31% | 80.45% |
| consumer.rs | 95.25% | 93.60% | 93.88% |
| door.rs | 81.45% | 81.08% | 79.05% |
| egress.rs | 99.67% | 100.00% | 99.70% |
| error.rs | 100.00% | 100.00% | 97.48% |
| local/mod.rs | 84.91% | 74.29% | 86.94% |
| local/producer_door.rs | 76.98% | 84.21% | 77.46% |
| params.rs | 100.00% | 100.00% | 100.00% |
| producer.rs | 95.70% | 91.83% | 96.74% |
| rfc1928/ (all five) | 96.5–100% | 95.65–100% | 78.6–99.6% |
| wire.rs | 96.58% | 97.06% | 97.19% |
| TOTAL | 93.68% | 91.01% | 92.97% |
Healthy overall; the batch-2 modules carry the lower numbers (D-1, D-2, N-8 attribute them). The protocol core's residue is unchanged from review 002's attribution; the assembly layer's gaps are the findings below.
Summary Statistics
| Severity | Count | IDs |
|---|---|---|
| Critical | 0 | — |
| Major | 2 | F-1, F-2 |
| Minor | 4 | S-1, D-1, D-2, D-3 |
| Observation | 8 | N-1..N-8 |
No critical findings. The two majors (F-1, F-2) are door-boundary
fidelity/teardown corrections, both fixed in the review change:
F-1 is the cred-bearing door silently swallowing the in-band
refusals' mapped reply codes (a vanilla client got a bare EOF where
ADR-007 pins a reply-code-shaped refusal); F-2 is the UDP door's
fatal-I/O swallow (serve_on returned Ok(()) on a relay-socket
failure the docs call fatal). One coverage finding (D-2) is the
batch-2 analogue of review 002's D-2 (the spec'd surface unexercised);
the rest are small.
Resolution (2026-09-27): the residue round closed the review —
S-1/N-1/N-2/N-3 as the recommended doc notes, D-1/D-2/D-3 as the
recommended tests, N-8's worthwhile probes landed (the remainder
accepted-uncovered with the disposition recorded per section); the
frontmatter's invalid YAML (plain-scalar colons in
reviewed_artifacts) fixed. Full verification green; see the
disposition table for commit pointers.
Prefixes follow the review-002 legend: F (correctness, fixed
inline — continuing 002's C family with the batch's review-fixed
disposition), S (security posture), D (dead surface/coverage), N
(observations/notes/smells).
Part A — Findings
F-1 [major, fixed] — The cred-bearing door swallowed every in-band refusal's mapped reply code: a vanilla client got a bare EOF where the RFC (and ADR-007's failure mapping) promises a reply-code-shaped refusal
Files: src/door.rs (cred_bearing's CONNECT/BIND session-open
error arms + bind_quiet_and_pipe's accept-stage error arm;
pre-fix state at git 04c76e3)
Problem: ADR-007 pins the failure mapping as RFC-faithful end to end: factory failure → reply#1's mapped code; accept-stage failure → reply#2's mapped code. The producer honors this in-band — but the cred-bearing door sat between the in-band conversation and the vanilla client and dropped the mapped code on the floor at three sites:
connect_with_tokenrefused (dial refused per target policy — the in-band CONNECT reply carried 0x05/0x02/0x03/…) → the door returnedDoorExit::Open(err.to_string())and the vanilla connection closed with no reply at all.bind_with_tokenrefused (the in-band BIND command gate's 0x02 — an identity withsocks5:openbut notsocks5:bind) → same: bare EOF where a vanilla client expects reply#1ConnectionNotAllowed.await_inbound()'s accept-stage failure (Err) — the quiet wait's accept refused per policy — the door closed the connection with no reply#2.
The producer-side in-band paths (the pump handler, serve_socks5_over)
write the RFC reply before returning the session error; the door —
the one surface whose whole job is RFC codec translation — discarded
it. The observable: curl --proxy socks5://user:pass@host against a
target-policy refusal hangs-then-drops instead of printing
"proxy CONNECT aborted" with a SOCKS error — and, worse, a BIND
command-gate refusal (the ADR-006 security boundary working as
designed) was indistinguishable from a crashed proxy. The door's own
module doc promises "the RFC codec lives only here" and "zero protocol
translation" of payloads — refusal re-encoding is the codec's job.
Fix (landed in this review change): a write_refusal_reply helper
(the door's boundary codec, best-effort — a failed write means the
client is gone either way) re-encodes SocksSessionError::Rfc( ReplyError)-shaped refusals to the vanilla client with the RFC's
placeholder BND.ADDR (0.0.0.0:0, the same form reply_error uses),
at all three sites (CONNECT open, BIND open, the accept-stage Err).
Non-reply-code shapes (open/transport/I-O) stay a bare close (nothing
RFC-shaped to encode). Pinned by cred_door_in_band_refusal_ surfaces_the_reply_code (a socks5:open-only credential BINDs →
reply#1 carries 0x02 + the placeholder address, within a timeout —
the old shape failed the test by never writing a reply).
Lift: closes the last wire-fidelity gap between the in-band and
vanilla surfaces. Every other door path re-encodes its reply
(pipe_connect_plane, pipe_bind_plane, the UDP door's codec); the
refusal paths were the asymmetric ones.
F-2 [major, fixed] — UdpFrontDoor::serve_on returned Ok(()) on a fatal relay-socket I/O failure, against its own contract
Files: src/door.rs (UdpFrontDoor::serve_on's final Ok(()),
pre-fix at 04c76e3); doc: "Runs until the association ends (the
in-band channel EOF, the client idle bound, or a fatal I/O
failure)"
Problem: the two-pump select! resolves with a UdpDoorExit; an
Io exit (a real relay-socket failure — recv_from erroring on a
non-idle socket) is documented as one of the run's fatal outcomes,
but the method mapped every exit to Ok(()). The caller
(assembly wiring, the serve wrapper) cannot distinguish "the
association ended cleanly" from "the relay socket died" — the exact
distinction the doc's contract claims to carry. The TCP door has the
same return shape but its per-accept isolation posture makes
per-connection I/O failure genuinely non-fatal (the loop continues);
the UDP door is one association per call — an Io exit there is
the call's outcome. Latent: nothing in the suite exercised a
relay-socket error, so the swallow passed every test.
Fix (landed in this review change): the exit match surfaces
UdpDoorExit::Io as Err(err); the idle bound, the association end,
and a session error stay clean Ok(()) (the association's own ends —
each already logs at debug). All UDP-door tests unchanged and green
(the idle-bound and teardown tests assert clean exits, which the
match preserves).
Lift: the caller-visible contract matches the doc; an assembly
monitoring serve() can now distinguish fatal from graceful.
S-1 [minor, closed 2026-09-27] — The UDP door's reply path trusts the recorded client address for the association's whole lifetime: a spoofed first datagram hijacks every subsequent reply
Files: src/door.rs (UdpFrontDoor::serve_on's client_addr
capture — the first inbound datagram's source wins permanently)
Problem: the door serves one association per relay socket and "learns" the client's source address from the first datagram, using it for every reply. Two residual shapes:
- An off-path spoofed datagram arriving first (before the real client's) pins the replies to the spoofer's address. For the documented posture this is near-moot: the relay socket is bound loopback by the builder's posture (a wildcard bind is the caller's explicit variant), and an attacker who can inject datagrams into the loopback path owns the host anyway. But a deployment that does spell the wildcard bind gets a one-datagram reply-hijack primitive per association.
- A client that changes source port mid-association (NAT rebinding) silently stops receiving replies (replies go to the learned address).
Recommendation: accepted-uncovered posture note rather than a fix
— RFC 1928's own ASSOCIATE has the same per-association peer
expectation (the RFC's relay is expected to drop datagrams from
non-expected peers; learning-on-first is the v1 shape the POC
validated). One doc line on serve_on naming the residual ("the
client's source address is learned from the first inbound datagram
and pinned for the association's lifetime — a wildcard-bind deployment
accepts the off-path-first-datagram shape, the RFC's own posture")
so the next reader does not mistake it for a bug. Filing now so the
residual is a named decision, not an accident.
Closed (the residue round): the recommendation landed — the
accepted-uncovered posture note is on UdpFrontDoor::serve_on's doc
(commit 87afe70).
D-1 [minor, fixed 2026-09-27] — associate_with_token remains 0%-covered dead surface (the batch-2 completeness twin with no caller)
Files: src/consumer.rs:450-475 (associate_with_token —
uncovered; contrast connect_with_token/bind_with_token, both
covered via the door tests), the doc claim: "the session family's
completeness … and the wrapper-aware deployment's surface"
Problem: the TCP door refuses ASSOCIATE before any session; the
UDP door rides AssociateSession::associate (no token — the UDP door
is NoAuth by construction). No test drives the token twin. This is
review 002 D-1's shape again — spec'd machinery with zero callers —
but here the doc already carries the honest posture (the door does
not call it), so this is not doc-vs-code drift. Still: a
constructor-twin whose negotiation body could drift from
associate's (e.g. the DST.ADDR form) would pass the suite.
Fix (small): one test mirroring bind_session_with_token_round_ trip's shape (drive associate_with_token directly against the
token-provider topology) — or an explicit accepted-uncovered note on
the method. Either closes the review-002-D-1-class trigger before it
fires a third time.
Fixed (the residue round): associate_session_with_token_round_trip
(tests/door-tcp.rs, commit 59e8fb1) — the probe drives the token
twin against the token-provider topology (the CF-005 open, the
sentinel BND.ADDR, a datagram round-trip through the echo egress,
shutdown reap). The review-002-D-1-class trigger is closed with the
test, not the note.
D-2 [minor, fixed 2026-09-27] — ComposedEgress's failure/edge matrix is the batch-2 coverage gap: the LRU's structural Err arm, relay_read's sender-closed exit, and the eviction-vs-live-relay accounting are untested
Files: src/composed/mod.rs (module total 77.32% lines / 65.31%
functions — the suite's lowest), tests/composed-egress.rs (6 tests,
all happy-path or one-shot EOF)
Problem: the composed egress carries several load-bearing failure shapes that no test drives:
entry_for's post-insert invariantErr(the structural diagnostic; unreachable by construction — pinned nowhere, not even by anunreachable-class comment beyond its own doc).relay_read'stx.send(..).is_err()early return (the shared queue closed with the egress — the stage exiting mid-relay). TheInbound::Endedpath is tested (closed_queue_yields_err_...), but the sender-closed path is a different exit.- The interaction between LRU eviction and
live_relays: evicting an entry drops itsTableEntry(session + write half), which EOFs the tunnel and ends the relay task → anEndedmarker → the count decrements. An association that has evicted all of its (capped) tunnels while parked innext_replywould then trip theever_opened && live_relays == 0association-end — correct, but the eviction-drives-association-end composition is unpinned (the existing tests evict and re-dial within a live set). inner_bytes' oversize guard (EgressError::Generalon a reply over the joint bound) — the tunnel codec caps at 65535 inner bytes upstream, so the guard should be unreachable, but nothing pins the guard fires (or that the tunnel codec's cap makes it unreachable).
Recommendation: one small test round before release polish: (a) an
egress with max_tunnels: 1 whose single tunnel's far side EOFs →
the association-end Err fires through the eviction path; (b) a unit
probe on the invariant-Err arm's message shape (or fold it into
(a)). The module's 17 uncovered functions are nearly all these two
regions.
Fixed (the residue round): commit b43bf54 — (a) landed as
eviction_to_a_failed_dial_ends_the_association_when_the_relay_ends
(tests/composed-egress.rs; the genuine eviction→association-end
shape is the cap-1 eviction whose replacement dial fails — the far
side EOFs the evicted tunnel, the count reaches 0, the parked
next_reply returns the association-end Err; the originally
suggested far-side-EOF shape cannot reach 0 live relays because the
replacement tunnel's relay is always live — the test taught the
composition); the relay-exit pair pinned directly in
src/composed/mod.rs's egress_unit_tests (the sender-closed silent
exit + the EOF→Ended path, with Inbound gaining #[derive(Debug)]);
the oversize guard pinned at the bound edge; the Ended-marker
saturating_sub discipline pinned (a live relay keeps the stage serving
beside an ended one). Module coverage: 77.32% → 85.49% lines.
D-3 [minor, fixed 2026-09-27] — The local providers' refusal-mapping tables are partially uncovered: dial_error_of's TimedOut/PermissionDenied arms and bind_accept's Shortage-arm splits are compile-checked only
Files: src/local/mod.rs:76-81 (dial_error_of's
NetworkUnreachable/HostUnreachable/TimedOut/PermissionDenied
arms — unreachable from the loopback tests, which can only produce
ConnectionRefused), src/local/mod.rs:253-259 (the bind-map's
PermissionDenied/AddrNotAvailable/_ arms — the tests drive
AddrInUse only), src/local/mod.rs:108-110 (the "no addresses
tried" terminal — unreachable: the resolved set is never empty after
the empty-check), src/local/mod.rs:63-64 (the domain-resolve
"no addresses" arm), src/local/mod.rs:214 (try_recv_from's
non-WouldBlock error arm)
Problem: the task notes record the mapping table as the
deliverable, and to_reply_error() is table-tested — but the io
error kind → SocksDialError / io kind → BindAcceptFactoryError
splits themselves are only half-driven. A refactor that swaps
TimedOut into the _ arm (losing the 0x03 mapping) would pass the
suite. Same class as review 002's N-8 single-arm cosmetics, but
these are security-adjacent (the refusal vocabulary is the target
policy's observable surface).
Fix (small): table-driven unit tests on dial_error_of and the
bind-map's closure (they are pure functions of io::ErrorKind —
construct errors of each kind with io::Error::new); two tests, no
new harness. The two structural arms (no addresses tried, the
resolve-empty arm) stay accepted-uncovered with a note each.
Fixed (the residue round): commit 59e8fb1 — four table tests in
src/local/tests.rs: the dial_error_of kind→arm table (all six
arms, incl. the TimedOut-shares-NetworkUnreachable and the
PermissionDenied→General shapes + the context rides the message),
the dial vocabulary's reply codes, the bind-map's kind→variant table
(AddrInUse/PermissionDenied→Shortage, AddrNotAvailable→
Refused, the _ catch-all→General), and the bind map's reply
codes. The two structural arms (no addresses tried, the
resolve-empty arm) stay accepted-uncovered as recommended.
N-1 [observation, closed 2026-09-27] — ProducerDoorGuard::close's drop(self)-then-await shape is correct but non-obvious: one doc line would prevent a "simplification" that deadlocks
Files: src/local/producer_door.rs:194-202
Problem: close drops self (releasing the watch::Receiver)
before awaiting the loop task — load-bearing: the loop's
done_tx.closed() only resolves when all receivers are dropped, so
holding the receiver across the await would deadlock the graceful
stop. The code is correct; the doc says "ends the accept loop
gracefully" without naming why the drop precedes the await. A future
refactor that "simplifies" the drop(self) away (it looks redundant
next to the field-Noneing above it) reintroduces a hang.
Fix (one line): extend close's doc: "the receiver is dropped
before the await — the loop's done_tx.closed() fires only when
every receiver is gone; holding it here would deadlock." Zero
behavior change.
Closed (the residue round): the doc line landed on close
(commit 87afe70).
N-2 [observation, closed 2026-09-27] — bindfirst_accept's factory errors map to reply#1 codes whose vocabulary is wider than the producer's gate: NotAllowed/Shortage from a listen resource deserve a doc cross-check against the producer-side bind_policy gate
Files: src/composed/mod.rs:718-820 (the factory's
Refused/NotAllowed/Shortage mappings)
Problem: the composed factory returns BindAcceptFactoryError
variants that the producer maps to reply#1 codes — including
NotAllowed (0x02), the same code the ADR-006 command gate uses for
the ACL refusal. On the channels path the two layers stack: an
identity without socks5:bind never reaches the factory (the gate
precedes the seam), so a factory-side NotAllowed can only mean the
tunnel layer's per-listener ACL — semantically distinct, wire-identical.
That is RFC-faithful (0x02 is the ruleset code) and the composed
variant's per-listener ACL is a real policy source (ADR-007's
per-listener ACL for free), so the behavior is correct — but nothing
in the composed module's doc names the stacking ("the factory's
0x02 can also mean the tunnel layer's ACL, distinct from the command
gate's"). An operator debugging a refused BIND sees one code with two
policy sources.
Recommendation: one doc line on bindfirst_accept naming the
layering. No code change.
Closed (the residue round): the layering note landed on
bindfirst_accept's doc (commit 87afe70).
N-3 [observation, closed 2026-09-27] — FrontDoor::serve_on's per-accept task holds the session-cap permit for the connection's whole life, but the idle-first-byte timeout does not release early: a 256-cap door parks at "cap reached" for connections that are merely slow readers
Files: src/door.rs:338-374 (the accept loop + Semaphore),
src/door.rs:393-401 (the idle-first-byte gate)
Problem: the permit is acquired at accept and dropped at task
end — correct for the cap's purpose (bounding concurrent sessions).
The residual: a connection that passes the idle gate (sent one byte)
but is then slow consuming the producer's conversation holds its
permit for the RFC conversation's full lifetime — the cap counts
accepted connections, not active sessions. That is the cap
working as designed (ADR-014 knob 2 bounds concurrent connections,
which is the slowloris-relevant resource), so this is a naming
residual only: the builder doc says "max-concurrent-sessions" where
the mechanism is "max concurrent connections" (including idle-past-
first-byte ones). Same shape on ProducerDoor.
Recommendation: one doc word ("connections" not "sessions") on both builders, or leave as-is — the knob's name is the docs' vocabulary, not a contract. Zero code.
Closed (the residue round): both builders' max_sessions docs now
say "max-concurrent-connections" with the mechanism named (commit
87afe70).
N-4 [observation] — The cred-bearing door's local_rfc1929_half check closure writes the mapped identity through a std::sync::Mutex witness even when the check rejects: the None slot survives a failed check (harmless, but the witness's semantics are "last lookup", not "accepted identity")
Files: src/door.rs:530-557
Problem: the checker sets *slot = mapped (including None on a
miss) before returning accepted; the later .take().ok_or(...)
correctly treats None as rejected. Residual: a checker that ran
twice (upstream's accept_password_auth calls it once per
conversation — fine here) would let a later miss overwrite an
earlier hit. Reachable only through API misuse (the closure runs
once per conversation by construction). Harmless as landed; the
"the check IS the table lookup — one table, one truth" doc claim is
accurate for the single-call shape.
Recommendation: none. Recorded to bound re-review (the shape is
the sync-witness pattern's own; a second call site would need
Option::take-semantics discipline).
N-5 [observation] — The two doors' accept loops duplicate the idle-peek + semaphore-cap + per-accept-isolation shape (FrontDoor::serve_on vs ProducerDoor's serve_on_parts) — a third door shape should extract it
Files: src/door.rs:338-374, src/local/producer_door.rs:261-294
Problem: ~35 lines of structural duplication (the
Semaphore::try_acquire_owned cap refusal, the spawn +
_permit-guard shape, the accept-error isolation) — the same N-5
class as review 002's harness consolidation, across a feature
boundary this time (door.rs and local/producer_door.rs could
share a helper; both are local-gated so no feature-gate obstacle).
Deliberately not fixed inline: the two loops differ in the producer
injection (serve_socks5_over vs the variant split) and a third
consumer doesn't exist yet; a premature extraction would trade two
readable loops for one parameterized one.
Fix (small, when a third shape lands): a
crate::local::accept_loop-shaped helper (idle gate + cap + spawn +
isolation) consumed by both. Until then, the duplication is honest.
N-6 [observation] — InbandBridge::recv's 16 KiB scratch allocates per call (per datagram when the queue is empty) — bounded, but the retained-capacity note from review 002 S-1 applies one layer up
Files: src/door.rs (InbandBridge::recv's vec![0u8; 16 * 1024])
Problem: each decode call allocates a fresh 16 KiB read buffer
(the AssociateSession::recv_datagram shape it mirrors does the
same). Bounded per call, dropped per call — fine; the S-1-style
residual (a 65507-byte frame's BytesMut retaining ~64 KiB of
capacity in the bridge's reader for the association's lifetime) is
inherited from DatagramReader's design and already recorded in
review 002 S-1. Per-association bounded, unshrunk — same accepted
posture, now with two owners (the session and the door's bridge).
Recommendation: none (the review-002 posture covers it). One line
on InbandBridge's doc pointing at the shared posture, if the next
touch lands.
N-7 [observation] — ProducerDoor::builder() requires .producer but not .bind — the bind decision moves to serve(), an asymmetry with FrontDoor's builder (where .bind is required at build time)
Files: src/local/producer_door.rs:144-155 + 222-239 vs
src/door.rs:279-288 + 305-309
Problem: two builder shapes for sibling types: FrontDoor's
missing-bind is a build()-time error (DoorBuildError:: MissingBindAddr); ProducerDoor's is a serve()-time error
(ProducerDoorError::MissingBindAddr). The producer door's split
exists for a reason (its doc says so — serve_on needs no bind), but
FrontDoor could have made the same split and didn't. The
asymmetry is documented on both sides; a deployer writing both
shapes hits the difference on the first compile error and reads two
docs.
Recommendation: none (both postures are typed, convention-2 compliant, and documented). Recorded to bound re-litigation: the split-vs-eager-bind choice is per-type, not a pattern to propagate.
N-8 [observation, closed 2026-09-27] — Coverage residue worth one line each (or accepted-uncovered with a note), beyond D-2/D-3
The --all-features --show-missing-lines sweep attributed; these are
the residuals beyond the findings (each small, named so the next
coverage run needs no re-derivation):
door.rs:160-168—CredentialTable::len/is_empty: observability accessors, no caller (one probe or an accepted-uncovered note).door.rs:194-196—DoorExit::LocalRfc's Display arm (the cred-bearing door's local-RFC exit is reached in tests, but that variant's arm render is not asserted): cosmetic.door.rs:305-309—FrontDoor::serve(the bind-then-serve wrapper; every test drivesserve_on): one test or a "the suite drivesserve_on" note.door.rs:414— the(Some(_), None)unreachable-by-construction arm: accepted-uncovered by design (convention 2's exhaustive-match shape), fine.door.rs:483-487—raw_pipe's open-failure exit (a NoAuth door whose channel open fails): one probe would pin it.door.rs:595-611—pipe_connect_plane's Domain-reply form + theNone-reply + write-failure arms: the suite drives v4 replies only; a domain-reply unit probe or accepted-uncovered.door.rs:636-656—pipe_bind_plane's Domain-form reply wire (the BIND door's domain-BND re-encode): the suite's BIND tests drive IP forms; the Domain arm is hand-written wire code with no test — the batch-2 suite's most substantive single-arm gap.door.rs:722—write_refusal_reply's_ => returnarm (a non-reply-code error stays a bare close): one probe.door.rs:755-758—UdpDoorExit's Display arms: cosmetic.door.rs:810-814—UdpFrontDoor::serve(same as the TCP door's).door.rs:842-845—serve_on's spent-splitarm (Ok(())on a spent association): one probe.door.rs:886— theclient_addr-already-set skip;door.rs:908- 913— the reply-before-first-inbound park (continuewhen no client address is known): both single-arm, timing-shaped.door.rs:941— theIo-exit-as-Errarm (F-2's new shape): the fix landed untested (a relay-socket read error is not producible over a test duplex without a poisoned socket) — accepted-uncovered with this note, or aUdpSocket-pair probe.door.rs:1005-1048— the bridge's error arms (a decode garbage in a later batch frame, theAddressvariant): the unit tests pin the happy shapes; one garbage-later-batch probe.consumer.rs:1145-1147—TokenClient's Debug: cosmetic.consumer.rs:1185— the spent-shape assert'serr().map(to_string)formatting arm: cosmetic.local/mod.rs:63-64, 108-110, 214, 257-259— D-3's terminal arms.local/producer_door.rs:71-72—BackendExit::Session's Display arm;:121-124— the builder'sidle_first_byte/max_sessionssetters (the tests drive both — viaserve()'s defaults only);:200—close's already-closed arm;:222-239—serve'sMissingBindAddr/Binderror arms;:269-271— the accept-error continue arm;:314— the idle-peekIoarm.composed/mod.rs— D-2's matrix (the module's own gap).egress.rs:518— the sync-Errfactory test's panic arm (the match'sOkarm — unreachable in the passing test): cosmetic.
The headline gaps: the BIND door's Domain-form reply wire (D-2's
neighbor), the composed egress's failure matrix, and the
local/mod.rs mapping-table arms.
Closed (the residue round, commit b43cbd2 + the D-2/D-3 commits):
the worthwhile probes landed; the timing-shaped/structural remainder
stays accepted-uncovered:
- Probed:
CredentialTable::len/is_empty(credential_table_len_and_is_empty_accessors);FrontDoor::serve(front_door_serve_wrapper_round_trips) andUdpFrontDoor::serve(udp_door_serve_wrapper_round_trips) — both bind-then-serve wrappers now round-trip;write_refusal_reply's_ => returnarm (write_refusal_reply_skips_non_reply_code_shapes) AND the re-encode's exact wire bytes pinned (write_refusal_reply_encodes_the_mapped_code); the bridge's garbage-in-a-later-batch probe (garbage_in_a_later_batch_frame_fails_loud); the BIND door's Domain-form reply wire — the batch-2 suite's most substantive single-arm gap — closed by extracting the hand-written wire intobind_reply1_wire(a pure function) and pinning both forms' bytes (bind_reply1_wire_forms); D-2's matrix and D-3's tables (their own sections above). - Accepted-uncovered (unchanged): the
DoorExit/UdpDoorExit/BackendExitDisplay arms andTokenClient's Debug (cosmetic); the(Some(_), None)unreachable-by-construction arm (by design); the timing-shaped UDP-door single arms (theclient_addr-set skip, the reply-before-first-inbound park, the spent-splitarm, the F-2Io-exit arm — not producible without a poisoned socket); thelocal/mod.rsstructural terminals (D-3's accepted-uncovered pair); theproducer_door.rsaccept-loop/error arms of the same timing-shaped class;egress.rs:518's test-internal panic arm;consumer.rs's two formatting arms;raw_pipe's open-failure exit andpipe_connect_plane's Domain/None-reply arms (the NoAuth open-failure shape needs a poisoned topology the harness cannot produce; the CONNECT Domain reply rides the codec's ownnew_reply-adjacent path, lower-value than the BIND wire). - Total coverage moved 93.68% → 93.94% lines (92.67% functions /
94.74% regions);
composed/mod.rs77.32% → 85.49%,door.rs81.45% → 85.84%,local/mod.rs84.91% → 89.19%.
Part B — Non-findings (verified correct, recorded to bound the re-review)
- The never-binds posture survived batch 2 (re-swept): the
protocol layer names no kernel-socket type; every bind is a
local-gated constructor's explicit decision; the default + composed wasm checks stay clean;local-on-wasm fails with the expected mio error. The doors' binds are builder-.bind()-driven;LocalEgress::bind's loopback andbind_accept's explicit host are the doc-pinned explicit shapes. - The cred-bearing door's re-origination holds under adversarial
reading: the door's RFC half consumes greeting + credentials +
one command; the in-band conversation is fresh (the never-pipes-
raw pin); the token is the mapped identity's id riding the open-op
auth_tokenpayload (CF-005 precedence (1)); the password never crosses the channel and never reaches a log line (swept: no credential is ever in atracingcall). - The UDP door's InbandBridge carries the ADR-003 reader-state contract (the gate review's R-1 fix verified independently): the pending queue drains in order, partial frames survive call boundaries, EOF mid-frame fails loud — the three unit pins all fail against a per-call reader, and the end-to-end doubled-echo test guards the class through the real stack.
- The composed accept's teardown-at-birth is structural: the
TunnelListenerrides inside the write payload (ForwardedOwner); the disjoint-capture trap is doc-pinned and the whole-struct rebinding is in place; the client-gone select! drop tears the listener and the oneshot down together; a correlation miss drops the forwarded channel at birth (pinned). - The forwarded handler's inline pump await (R-02) is real: the
handler's task lives exactly as long as the data plane (either-
EOF completion), the wrapper's inline await tracks it — verified
against alktunnels'
make_forwarded_op_handler(the inlinepump.await), not just the doc comments. - The composed egress's readiness contract is count-based and
sound: the
ever_openedguard (the assembly suite's drift fix) is correct — a never-opened table parks (the stage's channel branch governs); the ended-relayErrfires only after a tunnel existed and every relay ended;saturating_subbounds the count; the closed-queue test awaits theErr(never a hotOk(None)). - The sync-bound wrinkle's Sync proofs are no-unsafe: both
SyncHalvesandOwnedWriterideMutex<T: Send>(SyncforT: Send, std guarantee); poisoned locks unwrap viainto_inner(convention 2); contention is structurally impossible (one pump task at a time — the doc says so and the pump shapes confirm). - No panics in non-test code (re-swept across all of
src/, including the batch-2 modules): everyunwrap/expect/panic!hit is in a#[cfg(test)]region or a test file. The batch-2expectsweep (gate review R-2) held through the review's read. - Wire-driven allocation is bounded in the batch-2 code: the
doors' scratch buffers are fixed (1-byte peek, 64 KiB relay, 16 KiB
bridge chunk);
parse_udp_request's domain arm stays 255-bounded; the UDP door's 65535-byte recv is the kernel's datagram bound; the cred-bearing door's username/password reads are 1-byte-bounded by the RFC 1929 length fields (the forked codec's bounded-read posture). No unbounded wire-driven allocation exists. - The doors' failure isolation is real: per-accept spawn, the accept loop continues on per-connection failure (both doors + the producer door, each pinned); a cap-refused accept closes the socket with no channel opened; the idle gate fires before any channel opens (witnessed by the channel-count probes).
pump_bidiis awaited inline everywhere in batch 2 (the CONNECT/BIND doors'copy_bidirectionalagainst taken in-band streams; the composed accept's middle pump; the producer door ridesserve_socks5_over's own inline await) — no spawn-and-forget data plane exists.- MSRV, wasm, publish:
cargo publish --dry-runcompletes; both wasm checks clean;rust-version = "1.88"unchanged (the batch-2 additions are plain 2021-edition async/await; no let-else/OnceLock or other MSRV-relevant surface). - License/provenance posture unchanged:
src/rfc1928/LICENSEand the module docs still carry the full fork-point statement; batch 2 touched no forked file exceptserver.rs's already-pinnedaccept_password_authconsumption (doc-level only).
Part C — What's Good
- The door boundary is where the complexity belongs, and it is
contained. The entire RFC-codec surface (1929 negotiation,
reply re-encoding, the UDP header codec) lives in
door.rs(1135 lines, 70% tests) behind one feature gate; the protocol layer's growth for all of it wasTokenClient+ three constructor twins + areply_addraccessor. The F-1 fix was possible because the codec lives at the door — one helper closed all three sites. - The provider/producer split is honest.
ProducerDooris pure accept-loop assembly over the landedserve_socks5_over(zero new protocol-layer code, the module doc's claim verified line by line); the ADR-014 knobs are twolocaltypes (peekgate,Semaphore) with door-side refusals — the protocol layer never learned about timers, exactly per ADR-014. - The Sync-bound wrinkle's resolution is textbook: no unsafe, no new trait, two small adapters with the Sync proof in the type system, the owner riding inside the payload so the compiler enforces the teardown — and the whole thing is pinned by a compile-shape test against the real alktunnels surface.
- The assembly integration suite is the batch's real deliverable.
It surfaced the one genuine implementation drift
(
ComposedEgress's birth-killed association) that every per-component suite missed, and it pins the compositions the component tasks could not (doors + native + composed concurrent, the idle-bound teardown matrix, the domain-resolution pin). The mixed-assembly tests are exactly the roles-not-sides posture made executable. - The docs discipline held through an 8-task batch: the
reconciliations the tasks recorded (the
ever_openedfix, the TokenClient door-only contract, the one-command-per-connection posture, producer.md's local-backend rewrite) were all verified against the tree; the review found no further spec-vs-code drift beyond the ones already reconciled.
Suggested Disposition
The batch-2 gate closed with the crate feature-complete; this review found the residue a full-surface read always finds. Disposition (the residue round executed 2026-09-27 — every row closed except the per-item defers recorded in the sections above):
| Item | Action | Shape |
|---|---|---|
| F-1, F-2 | Fixed in this review change | the refusal re-encoding + the UDP-door exit match + the pinning test |
| S-1 | Closed — the accepted-uncovered posture note | UdpFrontDoor::serve_on's doc (87afe70) |
| D-1 | Fixed — the test, not the note | associate_session_with_token_round_trip (59e8fb1) |
| D-2 | Fixed — the failure matrix | the eviction→association-end + the relay-exit/oversize unit probes (b43bf54) |
| D-3 | Fixed — the io-kind tables | four table tests in src/local/tests.rs (59e8fb1) |
| N-1 | Closed — the doc line | the close drop-before-await note (87afe70) |
| N-2 | Closed — the doc line | the bindfirst_accept 0x02 layering note (87afe70) |
| N-3 | Closed — the doc word | "connections" on both builders (87afe70) |
| N-4 | none | recorded to bound re-review |
| N-5 | defer | extract when a third accept-loop shape lands |
| N-6 | none | covered by review 002 S-1's posture |
| N-7 | none | recorded to bound re-review |
| N-8 | Closed — the worthwhile probes landed, the remainder dispositioned | the BIND Domain wire helper + table, the refusal-recode pins, the serve() wrappers, len/is_empty, the bridge garbage probe (b43cbd2) |
Verification after the residue round: cargo test (default) and
cargo test --all-features green (15 suites); clippy (--all-targets --all-features and both wasm targets) clean; fmt/doc clean;
cargo publish --dry-run --allow-dirty completes; coverage 93.94%
lines (93.68% at review time).
The natural home for the residue is the release-polish task (publish prep, OQ-SK2-08) the batch-2 decomposition deferred — the review's test-shaped items ride alongside it; the doc-shaped items are one-line changes in the same round.
References
docs/reviews/002-protocol-core-implementation-review.md(the template; the C/D/S/N legend; the N-5/N-8 lineage this review's D/N items extend)tasks/implementation/review-assembly-layer.md(the narrow gate — its R-1 fix is this review's F-class context; its R-2 sweep is the no-panic posture re-verified in Part B)- docs/architecture/decisions/003/005/006/007/008/009/014 (the ADRs the batch-2 surface implements)
- alktunnels 0.2.0 (
producer.rsmake_forwarded_op_handler— the R-02 inline-await cross-check;ForwardedHandler's ownership shape) - ADR-014 (the accept-path defense obligations the doors inherit — the F-2/S-1/N-3 posture context)
- The POC crates (
/workspace/alksocks-{connect,udp,bind}-poc— the fidelity sources the gate review diffed; this review's POC-drift check found no further divergence)