cargo update -p rand@0.9.2 and cargo update -p rand@0.8.5 take the two pinned rand versions past the RUSTSEC-2026-0097 fix windows:
* rand 0.9.2 -> 0.9.4 (fix >= 0.9.3).
* rand 0.8.5 -> 0.8.6 (fix >= 0.8.6).
The advisory is reachable only with a custom logger that calls rand::rng() at trace/warn level and hits the 64 KB reseed path. We are not known to do that, but unblocking CI is reason enough.
The 1.0 bridge running on the async Dongle API from donglora-client 1.0.0 and the Protocol v2 wire format.
* Radio loop is now a tokio task, not a dedicated std::thread. Everything is async end to end.
* [radio] config schema: tx_power renamed to tx_power_dbm (plain i8, no "max" keyword), cad field removed (CAD is a per-TX flag in v1.0), default sync_word changed 0x3444 to 0x1424 to match the SX126x register encoding of MeshCore private sync byte.
* TX retry with backoff (new [tx] config section). Every TX runs through Dongle::tx_with_retry, retrying TX_DONE(CHANNEL_BUSY) and ERR(EBUSY) per PROTOCOL.md §6.10 / §C.5.5. Defaults: 3 attempts, 20-100 ms randomized backoff, doubling to 500 ms cap, 5 s per-attempt timeout. Configurable via max_attempts, backoff_min_ms, backoff_max_ms, backoff_cap_ms, backoff_multiplier, per_attempt_timeout_secs.
* TUI packet log shows retry state: in-flight retries render with a cycle marker in yellow and an N/M attempt counter, terminal TX failures render in red, post-retry success shows final attempt count.
* Stats gain tx_retries and tx_failures counters surfaced in StatsSnapshot.
* Measured airtime from TX_DONE replaces the theoretical estimate, feeding the rate limiter with the real on-air duration.
* The explicit 2 s liveness ping loop is gone. The Dongle runs a 500 ms internal keepalive, matching spec §3.4 inactivity window with 2x margin.
Once the bridge connects via mux, all subsequent reconnects use mux-only
mode (connect_mux_auto). Previously, each reconnect re-ran the full
mux→USB fallback chain, which could steal the serial port from the mux
during a brief disconnect.
Radio reconnection:
- Add connect_mux_auto() to donglora-client — mux-only connect that never
silently falls back to USB serial (matches Python client's sticky mux)
- Fix codec.rs read_frame() to handle WouldBlock alongside TimedOut
- Add liveness ping (2s) to detect dead mux connections
- Treat transmit errors as fatal (trigger reconnect)
- Faster backoff: 250ms initial, 5s max, resets after stable connection
TUI improvements:
- Redesign packet log: RF+Net columns show full packet path (RX→TX),
hash column with dedup ellipsis, fixed-width columns throughout
- Move activity charts to right column (fills remaining width)
- 1-second sparkline buckets instead of 10-second
- Radio panel shows "(disconnected)" with red border when mux is down
- Header: status pills left, clock with TZ right-justified, Ctrl-C quits
- Local time via jiff crate with proper timezone abbreviation
DHT strategy:
- Alone: read every 3s, merge-publish every 30s (preserves existing peers)
- Connected: publish authoritative [self + neighbors], purging stale peers
- Publish immediately on first neighbor join
Signal handling:
- SIGINT and SIGTERM both trigger graceful shutdown via cancellation token
- All paths go through swarm.shutdown() to update DHT before exit
Replace manually configured peer connections with a passphrase-based gossip
swarm. Peers sharing the same passphrase automatically discover each other
via mainline DHT and join an iroh-gossip topic.
Key changes:
- Add gossip.rs: iroh-gossip swarm with DHT bootstrap, heartbeat, and
graceful shutdown that publishes neighbor list
- Add setup.rs: interactive config wizard replacing generate-config
- Add rate_limit.rs: token-bucket TX rate limiter derived from LoRa air time
- Remove network.rs: old direct P2P connection management
- Config: remove [[peers]] section, add passphrase to [bridge], update
radio defaults to MeshCore US/Canada recommended values
- Packet: rename Envelope to GossipFrame, simplify wire format (drop
version byte and seq number)
- Router: unify dedup into single content-hash cache, add rate limiting
- Identity: use ephemeral keypair per launch instead of persistent secret key
- Radio: improve config negotiation (GetConfig-first strategy), add device
info tracking
- TUI: complete redesign with network/swarm panel, sparkline activity
charts, color-coded RSSI/SNR, and shutdown overlay
iroh QUIC datagrams for peer-to-peer networking with NAT traversal,
donglora-client for radio access (direct USB or mux), ratatui TUI
with four-panel dashboard (peers, radio config, stats, packet log).
- Packet envelope with origin tracking, sequence numbers, RSSI/SNR
- Dual dedup: iroh-level (origin+seq) and radio echo (blake3 hash)
- SNR filtering per PROTOCOL.md (forward GOOD+MARGINAL, drop rest)
- Auto-generate config + identity on first run
- Graceful mux config fallback (adopts locked config if SetConfig rejected)
- WouldBlock workaround for donglora-client socket timeout bug
- Reconnect with exponential backoff on dongle disconnect
- CLI: show-id, generate-config subcommands, --log-only headless mode