Found in a bug audit of the just-merged friends-list feature. No crashes
or security holes, but five real state/correctness bugs:
- Host child dying on its own left the share campaign running, so it kept
pushing a now-dead ticket to friends (retrying offline ones forever) and
leaked share_status/met/share_code. The unexpected-exit path now captures
the stderr error, then routes through the full stop_host() teardown
(notably stop_share). (gui/mod.rs pump_host_events)
- on_friend_request downgraded an already-Accepted friend back to
PendingIncoming when they re-sent a request (e.g. after losing their
store). It now stays Accepted and re-confirms. (friends.rs)
- on_friend_accept advanced *any* known peer to Accepted, including a
PendingIncoming one — a peer could mark itself accepted without the local
user's consent. Now only a PendingOutgoing request we sent is honoured.
(friends.rs)
- A ShareCode redelivered by an ACK-loss retry fired a duplicate desktop
notification. push_notice now reports whether the code is new/changed and
only then toasts. (gui/mod.rs)
- An inbound control message could be delayed up to IO_TIMEOUT on a degraded
link because handle() awaited the sender's close before forwarding it.
Forward to the UI first, then await close so the ACK still flushes.
(control.rs)
Adds two friends-store transition tests (accept ignores a pending-incoming
peer; request doesn't downgrade an accepted friend). 47 gui / 8 headless
tests pass, clippy + fmt clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>