This crate's util::run/run_with_stdin/run_ok/Output was cited as the one
correct, timeout-guarded subprocess implementation in the ecosystem worth
sharing — it's now promoted verbatim into bread-utils and re-exported here
so every existing crate::util::{run, ...} call site (notify.rs, nm.rs,
status.rs, tailscale.rs) keeps working unchanged. write_atomic similarly
delegates to bread_utils::atomic::write_atomic (path dependency for now,
see the TODO in Cargo.toml). home_dir/command_exists/timestamp stay local
— they're breadcrumbs-specific, not duplicated elsewhere.
New worktree for this repo (none existed from tonight's earlier passes,
since breadcrumbs needed no audit fixes then).
Builds clean; all 74 unit tests + 25 CLI integration tests pass.
ensure_core_profiles() was unconditionally backfilling home/work/away
into the in-memory config on every load, even when the user had
already defined their own profiles (e.g. Home/Away/School). This
showed up as duplicate/phantom lowercase entries in `breadcrumbs
profile list`, and downstream in breadbar and bos-settings.
Now the self-heal only fires when the profile set is completely
empty (a genuinely fresh or corrupted config), never padding an
existing customized set.
"(exit: , optional)" printed with nothing after the colon whenever no
Tailscale exit node was configured (the default). Now renders "none",
and relabels "exit:" to "exit node:" -- the abbreviated form read as an
exit *code* at a glance, which is what led to this being misdiagnosed
as a process-exit-code formatting bug in the first place.
graphical-session.target ships RefuseManualStart=yes and BOS has no
session manager to activate it properly (the same issue worked around
for breadclipd) - breadcrumbs doesn't need a Wayland session anyway,
so default.target avoids the problem entirely.
breadcrumbs had a watch subcommand meant to run continuously but no
systemd unit anywhere, so bakery installs never actually started it -
Wi-Fi profile config in bos-settings had no daemon consuming it.
Features:
- Introduce a Backend trait + System impl so flow/status/watch can be unit
tested against a fake; add 11 connect-state-machine tests.
- Captive-portal detection: status::connectivity returns Online/Portal/Offline;
surfaced in status, JSON, connect notes, and a dedicated watch state.
- `status --json` for bars/scripts; `profile add`/`profile remove`; detect now
scores by number of in-range markers.
Robustness:
- Pin LC_ALL=C/LANG=C on child processes for locale-independent parsing.
- Atomic config/state writes (temp + rename); 0600 config never world-readable.
- Transient PSK file written to $XDG_RUNTIME_DIR when available.
Fixes (from prior audit):
- Feed Wi-Fi PSK to nmcli via stdin/passwd-file, never argv.
- mask() no longer panics on multi-byte passwords.
- Connectivity check requires HTTP 204 (no captive-portal false positives).
- nmcli NAME,TYPE parsing handles escaped colons.
- Strip CIDR suffix from displayed IP; PKGBUILD/Cargo version aligned (2.1.0).