Closes the wave-3 gate's booked finding item 4 (review-wave-3
§Booked findings): register on an already-held token now refuses
fail-closed instead of silently replacing the live route — a collided
mint (the ADR-008 discipline's upstream failure) can never steal a
live adapter's arrival routes.
- ListenRouter::register returns Result<(), String>; collision → Err,
the held route untouched (src/tunnel_map.rs)
- Error surface decided + recorded: the wire-time collision is the
request-time decline disposition (RequestDenied, reason
token-collision), not a new AdapterError variant — a global-request
hook's Err propagates out of russh 0.65's packet loop and kills the
session, while a refused listen's vanilla contract is RequestDenied;
AdapterError::ListenRegistration keeps its construction-time class
(src/error.rs doc records the sibling)
- listen_request_dispatch: register moved before the bound-port
out-param write; on refusal the listener cap releases, the uniform
decline event emits, and the minted fabric listener tears down
immediately (never a half state) (src/handler.rs)
- Wire row a_collided_mint_is_refused_and_never_steals_the_live_route
pins the full shape through a mint-strategy construct on the fabric
double (MintStrategy::WithCollisions — the test forces what the
fabric's discipline prevents): second register refuses, first route
still serves end to end, refused endpoint never serves, count
released (tests/tunnel_mapping.rs)
Verification: cargo test (default + git/session/tunnel/sftp +
--all-features) · clippy ×2 -D warnings · fmt --check · cargo doc
--no-deps · taskgraph validate ✓ (35 tasks)