Release Notes
Fixed
- M1 —
cargo install nd300 can no longer fail on a read-only / hardened / sandboxed build cache. build.rs previously wrote the generated man pages into CARGO_MANIFEST_DIR/man/ with .unwrap()'d fs::create_dir_all + fs::write calls. On the primary install path (cargo install nd300), that directory is the registry extraction under …/registry/src/…, which is read-only on locked-down machines — the failing write would panic the build script and abort the install. build.rs now (a) renders both man pages into in-memory buffers (the only step that keeps its panic, since a failed render is a genuine bug), (b) writes OUT_DIR/man/*.1 strictly best-effort (create_dir_all(...).is_ok() guard + let _ = fs::write(...)), and (c) writes the committed repo man/*.1 only when a new is_dev_source_tree(CARGO_MANIFEST_DIR) check confirms the build is happening in a live source checkout (i.e. the manifest path is not under /registry/src/, /registry/cache/, /git/checkouts/, or /vendor/), and even then best-effort. Net: cargo install can never panic on a man-page write, while a normal local cargo build still refreshes the committed man/*.1 (so the dev tree stays in sync). Man pages still ship in release archives and the published crate via Cargo.toml's include = ["man/**"]; nothing reads OUT_DIR/man.
- H5 — Windows uninstall/update no longer reports binary removal before it actually happens (and no longer defeats the updater's shadow guard). On Windows the running
.exe can't be deleted in place, so the uninstaller spawns a background cmd /C … del that removes it after the process exits. Previously uninstall_path set binary_removed = true immediately on spawn — a false "removed" that, because the updater reuses uninstall_path for shadow-cleanup (actions/update.rs), silently bypassed the updater's Fatal "old install still shadows the new cargo binary" guard. CleanupReport now carries a distinct binary_removal_scheduled flag: the Windows branch sets it (and leaves binary_removed = false) on a successful spawn. uninstall reports "scheduled for removal (completes when this process exits)" and treats binary_removed || binary_removal_scheduled as success. The updater's cleanup_shadowing_current_install_after_cargo_success now returns Ok with an honest warning when removal was only scheduled (the new cargo binary wins in a new shell; manual cleanup instructions are printed if it doesn't), instead of either a silent success or a false Fatal. cleanup_current_install_for_cargo_retry stays Fatal when the file isn't actually gone — an immediate cargo retry needs it removed now — but now emits explicit "close this nd300 process and re-run nd300 update" instructions for the scheduled case.
- L3 — Windows uninstall now fully cleans the PATH entry even with a trailing slash.
remove_from_user_path now compares each PATH entry against the install dir ignoring case and a trailing \// (via a new pure path_entry_matches_target predicate, mirroring same_path in actions/update.rs), so an entry like C:\…\bin\ is removed instead of left behind as a dead PATH stub. Only the comparison is normalized; retained entries keep their original spelling.
- L4 — the Windows delayed-delete command is now hardened against shell metacharacters. The
cmd /C … del "<path>" string is built by a new build_delayed_delete_command helper that refuses (returns None, reported as a failure with an explanatory note) any path containing ", a newline/carriage-return, or a cmd metacharacter (& ^ | < >) — all of which are already illegal in real Windows paths — and escapes % to %% so cmd's environment-variable expansion can't mangle a path with a literal %.
Changed (be aware if you script against the tool)
nd300 uninstall --json gains an additive boolean field binary_removal_scheduled. The existing binary_removed field keeps its literal "is the binary gone right now?" meaning (so it now reads false on a successful Windows uninstall, where deletion completes on process exit), while success and the exit code key off binary_removed || binary_removal_scheduled. The field is purely additive and non-breaking on macOS/Linux, where it is always false and binary_removed is unchanged.
Install nd300 3.0.10
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/QubeTX/qube-network-diagnostics/releases/download/v3.0.10/nd300-installer.sh | sh
Install prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/QubeTX/qube-network-diagnostics/releases/download/v3.0.10/nd300-installer.ps1 | iex"
Download nd300 3.0.10