Finding
MeshRouter::process_timeouts is the only production path that turns timeout events into DeliveryFailure::MaxRetries records, and it is untested. The existing router tests cover nak_triggers_retry_then_failure, which exercises the NAK branch (outbound.handle_nak), but no test drives the timeout chain outbound.check_timeouts -> outbound.retry -> delivery.mark_failed. There is no time-based test (#[tokio::test(start_paused = true)] or any time-advance) that calls process_timeouts with a timed-out inflight packet and asserts the resulting failure state.
Evidence
crates/kerykeion/src/router.rs:187:
pub fn process_timeouts(&mut self) -> Vec<PacketId> {
This function (router.rs:187-200) is the sole producer of DeliveryFailure::MaxRetries. The router.rs mod tests contains no #[tokio::test(start_paused = true)] test and no time-advance covering this function; coverage of the failure path comes only from nak_triggers_retry_then_failure, which routes through the NAK branch rather than the timeout branch.
Why this matters
process_timeouts is the primary durability gate for the outbound queue under radio silence: when a mesh node stops ACKing, this path decides whether messages are retried or marked failed. Under the counter-surveillance threat model, a node going dark (jamming, seizure, or an adversary suppressing ACKs) is an expected condition, not an edge case. A regression here — double-retry, delivery state not updated, or the wrong packet ID returned — would silently corrupt the delivery log: the operator could believe a message was delivered when it was lost, or retry a message that should have been abandoned. Because no test exercises the chain, such a regression is invisible to CI.
Desired correction
Add a #[tokio::test(start_paused = true)] test to the router.rs test module that: sends a packet, tracks it as inflight with a short ACK timeout, advances virtual time past the timeout, calls process_timeouts, and asserts that (a) the returned Vec<PacketId> contains the sent packet's ID, and (b) the delivery tracker reports Some(DeliveryStatus::Failed { .. }) for that packet. Cover both the single-timeout-to-retry and the retry-exhaustion-to-failure transitions.
Done when: a time-based test for process_timeouts exhausting retries passes and is part of the router test module.
Finding
MeshRouter::process_timeoutsis the only production path that turns timeout events intoDeliveryFailure::MaxRetriesrecords, and it is untested. The existing router tests covernak_triggers_retry_then_failure, which exercises the NAK branch (outbound.handle_nak), but no test drives the timeout chainoutbound.check_timeouts -> outbound.retry -> delivery.mark_failed. There is no time-based test (#[tokio::test(start_paused = true)]or any time-advance) that callsprocess_timeoutswith a timed-out inflight packet and asserts the resulting failure state.Evidence
crates/kerykeion/src/router.rs:187:This function (router.rs:187-200) is the sole producer of
DeliveryFailure::MaxRetries. Therouter.rsmod testscontains no#[tokio::test(start_paused = true)]test and no time-advance covering this function; coverage of the failure path comes only fromnak_triggers_retry_then_failure, which routes through the NAK branch rather than the timeout branch.Why this matters
process_timeoutsis the primary durability gate for the outbound queue under radio silence: when a mesh node stops ACKing, this path decides whether messages are retried or marked failed. Under the counter-surveillance threat model, a node going dark (jamming, seizure, or an adversary suppressing ACKs) is an expected condition, not an edge case. A regression here — double-retry, delivery state not updated, or the wrong packet ID returned — would silently corrupt the delivery log: the operator could believe a message was delivered when it was lost, or retry a message that should have been abandoned. Because no test exercises the chain, such a regression is invisible to CI.Desired correction
Add a
#[tokio::test(start_paused = true)]test to therouter.rstest module that: sends a packet, tracks it as inflight with a short ACK timeout, advances virtual time past the timeout, callsprocess_timeouts, and asserts that (a) the returnedVec<PacketId>contains the sent packet's ID, and (b) the delivery tracker reportsSome(DeliveryStatus::Failed { .. })for that packet. Cover both the single-timeout-to-retry and the retry-exhaustion-to-failure transitions.Done when: a time-based test for
process_timeoutsexhausting retries passes and is part of the router test module.