Plan from a full-project review (code, docs, CI, and a feature-gap analysis against SwiftFTR 0.13.0) against Rust best practices as of mid-2026. Sections are stack-ranked — top is next; each is a shippable unit. Delete sections as they merge (git has the history).
Context: ftr is in maintenance mode (SwiftFTR is the primary macOS client), but has external users (GitHub stars, crates.io, APT repo, one open issue — #22 requesting IPv6). The v0.8.0 release (PRs #23–#35) covered docs accuracy, correctness fixes, dependency updates, CI/supply-chain hardening, IPv6 validation spikes, the breaking API cleanup, edition 2024, system DNS resolvers, and the tests lint-debt payoff; what remains is below.
DnsError::Truncated
exists; nothing retries over TCP). Windows system-resolver discovery
(GetAdaptersAddresses). Automatic DNS-config change watching to
complement dns::refresh_system_dns() — macOS via notify(3) on
com.apple.system.SystemConfiguration.dns_configuration (Chromium’s
approach, https://issues.chromium.org/issues/40182831; the c-ares
maintainers catalog per-platform equivalents in c-ares/c-ares#613),
Linux via inotify on resolv.conf. #[non_exhaustive] on
ReverseDnsError/DnsRecord (skipped in #33 to avoid cross-PR
conflicts).release.yml for rust-lang/crates-io-auth-action. Restructure the
two-phase draft-release flow so tagging can’t leave crates.io/APT silently
unpublished. Add macOS release artifacts (brew tap currently builds from
source).continue-on-error: true at introduction).rust-version = 1.86 — bump
together with the next MSRV raise.macos.rs only implements raw ICMP
(root-gated by Darwin), but macOS supports unprivileged SOCK_DGRAM
ICMP — SwiftFTR does full traceroutes without root this way, and the v6
spike proved DGRAM receives Time Exceeded unprivileged
(docs/IPV6_DESIGN.md). Add a DGRAM fallback like Linux’s; falls out
naturally from IPv6 integration, which needs the DGRAM path anyway.
Remember Darwin demuxes v4 DGRAM ICMP by identifier (SwiftFTR’s 0.8.0
regression) but does NOT for v6.Maintainer directive (2026-07-17): as an overall theme, reduce the size and complexity of the dependency tree — SwiftFTR’s zero-third-party-deps is the aspiration. Every new dependency needs justification; prefer hand-rolled minimal implementations for narrow needs (the 0.7.0 hickory/reqwest/pnet replacements are the model). Baseline 2026-07-17: 78 transitive crates from 10 direct (macOS; Linux adds vendored OpenSSL). Ladder, biggest win first:
cdn-cgi/trace endpoints are useful only if an HTTPS fallback survives.)
Also removes the vendored-OpenSSL Linux build and the TLS provider
fragility (a runtime panic lived there until PR #39).std::hash::RandomState per-process entropy hashed with a counter
suffices for these non-crypto IDs (document the security posture: DNS ID
is anti-spoofing defense-in-depth alongside source-port randomization).lexopt-style
single-crate) with hand-written –help. Trade-off: loses completions and
polish — do last, only if the theme still has appetite.Display/Error impls. Low value per churn — optional.Do NOT batch these with feature work; each rung is its own PR with
before/after cargo tree counts in the body.
linux.rs, macos.rs, bsd.rs) with
tokio AsyncFd readiness — the dominant avoidable CPU cost; also fixes
detached receiver tasks outliving the trace (tie receivers to the engine’s
JoinSet), removes env::var("CI") reads inside poll loops, and the
per-packet throwaway struct allocations.docs/IPV6_DESIGN.md —
mandatory for v6 on Darwin, and SwiftFTR’s 0.8.0 v4 regression).tokio::RwLock around internally
locked AsnCache/RdnsCache; make RdnsCache::get not take a write lock
per read.src/socket/icmp.rs
(reject IHL < 5 while at it) and the DNS parser; unit tests for the unsafe
recvmsg/CMSG path (linux) and Windows reply-struct reinterpret; gate live-
network tests behind an env var and serialize them (SwiftFTR’s
NetworkTestGate pattern) instead of letting them flake CI.IPv6 traceroute ships on every supported platform as of 0.10.0 (macOS, Linux, BSD in 0.9.0 via PRs #38–#43; Windows in 0.10.0 via #50), each live-validated on real hardware/VMs with external v6. Remaining:
ftr user isn’t in wheel; run from console or pw group mod wheel -m
ftr, then ftr -6 2001:4860:4860::8888). OpenBSD’s VM has no external
v6, so its live multi-hop trace needs a v6-connected host. macOS
root-mode RAW-vs-DGRAM comparison (sudo cargo run --release --example
spike_traceroute6).windows.rs and
bsd*.rs dead-code/lints surface only when someone compiles those
targets (three separate cleanups so far). Add windows-target (and ideally
a BSD-target) clippy --all-targets cross-check to CI.AI_V4MAPPED-style synthesis for
v4 literals on v6-only networks); first-class zone-scoped (fe80::%if)
targets; hop-level zone display.Stack-ranked by fit for a traceroute tool with external users:
impl Stream<Item = StreamingHop> emitting hops
in arrival order with a re-probe phase for rate-limited routers. Best
library-consumer win; SwiftFTR’s StreamingTrace is the reference.ECONNREFUSED, no privileges) and non-blocking TCP connect.
Small, self-contained.