Commit graph

40 commits

Author SHA1 Message Date
Breadway
b4c1d0b233 Talk to NetworkManager over D-Bus instead of shelling out to nmcli
breadcrumbs now speaks `org.freedesktop.NetworkManager` on the system
bus directly (new `zbus` dependency) — no `nmcli` subprocesses for
connect, scan, status, or the watch loop.

Why:
- Wi-Fi PSKs and 802.1x passwords no longer touch a command line. They
  travel inside `AddAndActivateConnection2` / `Update2` settings
  payloads, so they are never visible to other local users via
  `/proc/<pid>/cmdline`. This fully supersedes the earlier
  "feed the PSK to `nmcli --ask` on stdin" approach.
- The watch loop reacts to real `Device.StateChanged` / connectivity
  signals instead of parsing `nmcli monitor` text.
- Connect waits on the device actually reaching the ACTIVATED state
  rather than trusting `nmcli --wait`.

Config: `settings.nmcli_wait` is renamed to `connect_wait`; the old key
is still accepted via `#[serde(alias)]`. `status.rs` loses its private
`ipv4()` nmcli helper in favour of `nm::ipv4_address`. `util::run_with_stdin`
stays (tailscale still uses it) but no longer carries secrets.
2026-08-31 15:12:21 +08:00
Breadway
13c7743d48 Add feature batch: captive-portal detection, schedules, exit-node failover, 802.1x, per-network DNS
Implements the planned feature sweep: tri-state connectivity with portal
detection, time-based profile schedules, priority exit-node list with
failover, enterprise (802.1x) network support, per-network DNS, signal-
aware selection, auto-learn markers, suspend/resume recovery, prune
command, scored detection, and richer bread events (network.changed,
tailscale.changed). CLI gains --json output, init --wait, and add --dns/
--eap/--identity/--ca-cert. Adds regression coverage for each feature;
141 tests pass and clippy is clean with -D warnings.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-31 15:12:08 +08:00
Breadway
c02360a873 Fix bugs from a full audit: Tailscale recovery, SSID verification, captive portals, config races
The watch loop could spin forever on a stopped Tailscale daemon (the
auto-start path was unreachable) while re-notifying every retry, report
"connected" when NM autoconnect won a race onto a different SSID, and
classify captive portals as healthy (200/302 accepted as internet). The
bread-bus subscription thread also read/wrote config and state files
concurrently with the watch loop. Fix all of those plus: EDITOR values
with arguments, scan --to silently ignoring unknown profiles, deleted
core profiles being resurrected, inline-network migration data loss,
login never retried, XDG-unaware install-service, detect persisting a
stale default profile, password length leaking through the mask, a
stdin/stdout pipe deadlock, and several minor UI/robustness issues.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-08-31 15:11:19 +08:00
Breadway
02e96126e0 Feed Wi-Fi PSK to nmcli --ask on stdin, never argv
All checks were successful
check / check (push) Successful in 1m7s
dev release / build (push) Successful in 1m28s
First connect (and reuse-with-password) no longer puts the secret on
nmcli's command line, so it is not visible in /proc/<pid>/cmdline.
networks.toml stays 0600; the local copy is still cleared after first
success.
2026-08-23 14:44:23 +08:00
Breadway
92fb40d69b CI: refuse unsigned bakery index; stop copying missing service unit
All checks were successful
check / check (push) Successful in 1m11s
dev release / build (push) Successful in 3m43s
beta (rc) release / build (push) Has been skipped
release / build (push) Successful in 2m2s
2026-08-16 00:50:22 +08:00
Breadway
5094677c4e Bump version to v2.1.7
Some checks failed
beta (rc) release / build (push) Has been skipped
dev release / build (push) Failing after 27s
release / build (push) Failing after 1m1s
2026-08-15 23:05:47 +08:00
Breadway
fe1198ed74 Pin bread-utils to bread-ecosystem v0.7.2
All checks were successful
dev release / build (push) Successful in 56s
2026-08-15 22:53:46 +08:00
Breadway
f999730a7d gitignore: exclude graphify-out local cache
All checks were successful
dev release / build (push) Successful in 32s
2026-08-15 22:32:36 +08:00
Breadway
7a58d4acab Remove CLAUDE.md (renamed to AGENTS.md)
All checks were successful
check / check (push) Successful in 48s
dev release / build (push) Successful in 31s
2026-08-15 22:04:00 +08:00
Breadway
3b2a6e827b Rename CLAUDE.md to AGENTS.md 2026-08-15 22:03:30 +08:00
Breadway
9009404536 Wire breadcrumbs into the bread event fabric (app id crumbs)
All checks were successful
check / check (push) Successful in 36s
The watch daemon publishes bread.crumbs.profile.changed and
bread.crumbs.health.changed on real transitions (not every poll tick)
and honors bread.command.crumbs.set_profile via the existing
state::set_profile path. BreadClient is fail-silent: if breadd is
down, breadcrumbs behaves exactly as before.

Document the contract in EVENTS.md. CLAUDE.md now points at
CONTRIBUTING (single-trunk, no three-branch model), bakery, and
EVENTS.md.
2026-08-15 21:38:16 +08:00
0f48b1499d Merge pull request 'CI: port breadcrumbs onto bread-ecosystem's shared Arch build image' (#1) from feature/shared-ci into main
All checks were successful
dev release / build (push) Successful in 24s
Reviewed-on: #1
2026-08-05 19:51:26 +08:00
Breadway
fe9ddbda57 CI: port breadcrumbs onto bread-ecosystem's shared Arch build image
All checks were successful
check / check (push) Successful in 41s
Adds ci/build.sh + ci/bread-ecosystem.rev (pinned to bread-ecosystem
147cfbb) following the pattern proven in breadpad, so releases build
inside the shared pinned container instead of installing toolchain
deps directly on the bare runner. Routes dev/rc/release build+test
steps through it and adds a check.yml for fast clippy/test feedback
on feature/fix branches. No ci/deps.txt — breadcrumbs' dependencies
(clap/serde/toml/serde_json) are pure Rust with no system library
needs; nmcli/tailscale/sudo/xdg-open are shelled out to, not linked.
2026-08-05 19:12:42 +08:00
Breadway
b3444337ab CONTRIBUTING.md: document single-trunk + RC-tag release model
All checks were successful
dev release / build (push) Successful in 1m24s
2026-07-31 11:08:41 +08:00
Breadway
f9da2e4652 CI: single-trunk model — dev triggers on main, beta becomes RC-tag-triggered
Replaces the dev/beta branch split with one trunk (main): dev-track
builds still publish on every push, but the beta track now publishes
from a vX.Y.Z-rc.N prerelease tag instead of a separately-maintained
beta branch. Removes the branch nobody reliably kept in sync.
2026-07-31 11:05:29 +08:00
Breadway
66892a49f9 Drop pacman packaging, bakery-only distribution
All checks were successful
Mirror to GitHub / mirror (push) Successful in 2s
dev release / build (push) Successful in 22s
bakery already fully covers what the PKGBUILD provided (binary, systemd
--user service where applicable, dependency declarations) except a LICENSE
copy, which bakery.toml's new license_file field now closes. Removes
packaging/arch/ and .forgejo/workflows/package.yml; adds the LICENSE
artifact to each release/dev-release/beta-release workflow's prepare
step. Not pacman-installed inside BOS today (BOS already consumes these
apps exclusively via build-local.sh's skel-staging), so this only removes
the option to `pacman -S` outside of BOS/bakery.
2026-07-23 10:25:12 +08:00
Breadway
2f0f3b9194 docs: add CONTRIBUTING.md
All checks were successful
dev release / build (push) Successful in 26s
Mirror to GitHub / mirror (push) Successful in 2s
Documents the dev/beta/main branch and release-track workflow shared
across the bread ecosystem. See bread-ecosystem's docs/release-channels.md
for the full policy this implements.
2026-07-22 19:40:43 +08:00
Breadway
e63e66fe3f ci: make beta a branch-triggered freeze track, not a one-off tag
Some checks failed
dev release / build (push) Failing after 26s
beta release / build (push) Successful in 20s
Mirror to GitHub / mirror (push) Successful in 4s
Beta is now a real stabilization branch: publishes on every push to
`beta` (mirroring dev's model, auto-versioned X.Y.Z-beta.<ts>+<sha>,
base version from the latest published tag) instead of a manual
beta-v* tag. Fixes made during the freeze land via fix/<issue> branches
merged into `beta` directly. The gen-index.sh clone for beta pulls
bread-ecosystem's default branch (main) rather than pinning to dev,
since beta is the more stable track and main now carries the
TRACK-aware script.
2026-07-22 18:37:27 +08:00
Breadway
629bb6c945 ci: base dev version on the latest published tag, not Cargo.toml
All checks were successful
Mirror to GitHub / mirror (push) Successful in 2s
dev release / build (push) Successful in 30s
Cargo.toml can drift stale relative to the actual last release (observed
on breadbox/breadpad/breadcrumbs/breadpaper), which made the auto-bumped
dev version sort as OLDER than what's already installed — bakery's semver
check correctly refused those "updates". Deriving the base version from
git ls-remote --tags instead is self-healing regardless of Cargo.toml
drift, with a Cargo.toml fallback only for a repo with no tags yet.
2026-07-22 13:52:03 +08:00
Breadway
d615bdce4b ci: use a unique temp dir for the bread-ecosystem clone in dev/beta CI
Some checks failed
dev release / build (push) Successful in 34s
Mirror to GitHub / mirror (push) Failing after 3s
The fixed /tmp/bread-ecosystem-ci path races when multiple repos' dev/beta
workflows run close together on the same self-hosted runner — one job's
rm -rf/clone can stomp another's in-progress checkout, causing the
regenerate-index step to fail intermittently. Switch to mktemp -d.
2026-07-22 10:24:23 +08:00
Breadway
c4e1618f79 ci: retrigger dev-track build now that BAKERY_MINISIGN_SEC_KEY_PATH is set
All checks were successful
dev release / build (push) Successful in 36s
Mirror to GitHub / mirror (push) Successful in 2s
2026-07-22 10:10:05 +08:00
Breadway
d2964ebcc2 ci: add dev/beta build track workflows
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
dev release / build (push) Failing after 26s
Adds dev-release.yml (publishes on every push to dev) and beta-release.yml
(publishes on a beta-v* tag), mirroring the pattern landing in
bread-ecosystem/bread. See bread-ecosystem/docs/release-channels.md for
the three-track policy.
2026-07-22 09:58:15 +08:00
Breadway
037c6e54c9 Harden breadcrumbs: fix real bugs, restructure as lib, stop storing PSKs twice
Bug fixes:
- mask() panicked on multi-byte UTF-8 passwords (byte-slicing a char
  boundary); now masks by char count and never echoes a real character
- `cd --shell` interpolated the config path into a shell -c string via
  Debug formatting, which doesn't neutralize shell metacharacters; now
  passed as a positional shell argument instead
- connecting to open (no-password) networks failed because an empty PSK
  was always sent to nmcli, which nmcli treats as secured-with-no-password
  instead of open; the password arg is now omitted entirely when empty
- five nmcli terse-output parse sites used a raw splitn(2, ':'), which
  mis-splits any device/connection name containing a literal ':'; unified
  on the existing escape-aware field splitter
- watch's health classifier silently read a config-deleted profile as
  "healthy" off a bare internet check instead of surfacing the misconfig
- the nmcli-monitor thread seeded its debounce clock with
  `Instant::now() - 10s`, which panics on the monotonic clock near boot —
  exactly when the generated systemd unit tends to start the watcher

Architecture:
- extracted src/lib.rs + src/app.rs so command logic can be exercised
  in-process by tests instead of only by spawning the compiled binary
- added a Runner trait (src/util.rs) so subprocess calls can be faked in
  tests; flow::run and watch::classify are now covered by real in-process
  tests of the connect state machine and health transitions, not just
  their pure helpers
- Wi-Fi passwords are no longer kept in breadcrumbs' config once
  NetworkManager durably holds them: NetworkDef.password is now optional,
  and a successful password-based connect clears + persists it
  immediately, so it's never sent again on subsequent connects
- saved networks (SSID + optional local password) moved out of
  breadcrumbs.toml into a separate networks.toml; old configs with
  inline [[networks]] still load and migrate automatically on next save
- corrected a false README claim that passwords are never in nmcli argv

Test count: 20 -> 89 (52 unit, 24 CLI integration, 13 in-process
state-machine tests). Full clean run: cargo build/build --release/
test/clippy --all-targets, verified from a `cargo clean` rebuild.
2026-07-22 06:58:47 +08:00
Breadway
d177cc8d82 Disable debug package so the main package publishes correctly
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 1m19s
makepkg's debug split produced a -debug pkg; the upload's head -1 could
grab it instead of the main package. !debug yields a single package.
2026-06-13 23:00:51 +08:00
Breadway
6ec21a84aa Use REGISTRY_TOKEN (scoped write:package) for registry publish
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 1m39s
2026-06-13 22:55:42 +08:00
Breadway
d8ddf311e5 Disable LTO in PKGBUILD (vendored ring/mlua static libs vs makepkg -flto) 2026-06-13 17:06:56 +08:00
Breadway
e484fd014a Clone from public URL, not GITHUB_SERVER_URL (resolves to localhost in runner)
The Forgejo runner injects GITHUB_SERVER_URL as http://localhost:3002, which
is unreachable from inside the job container. Use the public URL instead.
2026-06-13 16:14:15 +08:00
Breadway
be53cb6cd6 Rename mirror secret to MIRROR_TOKEN (GITHUB_ prefix is reserved)
Forgejo/gitea rejects user secret names starting with GITHUB_.
2026-06-13 16:10:50 +08:00
Breadway
f5c47a877e Fix Forgejo workflows for the actual server capabilities
- package.yml: correct Arch registry upload (octet-stream + binary body),
  drop --privileged, manual shell clone (archlinux image has no Node),
  built-in Actions token, --nocheck
- mirror.yml: clone --mirror + explicit refs push with --prune
2026-06-13 16:02:23 +08:00
Breadway
076e175672 Add packaging/arch PKGBUILD and Forgejo Actions workflows
- packaging/arch/PKGBUILD: builds and publishes breadcrumbs to [breadway] repo
- .forgejo/workflows/mirror.yml: mirrors every push/tag to GitHub
- .forgejo/workflows/package.yml: builds on tag, publishes to Forgejo registry

Requires FORGEJO_TOKEN and GITHUB_MIRROR_TOKEN secrets in Forgejo.
2026-06-13 12:12:42 +08:00
Breadway
9c963424bd chore: update Cargo.lock for v2.0.1
Some checks failed
release / build (push) Failing after 8s
2026-06-11 14:28:06 +08:00
Breadway
5939362fcc chore: bump version to 2.0.1 2026-06-11 14:21:47 +08:00
Breadway
690bcad697 fix: move tailscale/sudo/xdg-utils to optional_system_deps
Core WiFi management works without Tailscale. tailscale, sudo, and
xdg-utils are only needed for Tailscale login and URL-open features,
so they become optional (warn, don't block) instead of required.
2026-06-11 13:38:06 +08:00
Breadway
ef77a02e77 Fix update looping and nmcli duplicate profiles 2026-06-07 10:14:18 +08:00
Breadway
586bc3a285 fix: use relative symlink for latest to work inside Docker containers 2026-06-07 09:02:38 +08:00
Breadway
af7fc462e1 fix: add contents: write permission for GitHub Release creation
Some checks failed
release / build (push) Failing after 3s
2026-06-07 00:00:50 +08:00
Breadway
294bb4a5d4 fix: create GitHub Release before uploading artifacts 2026-06-06 23:52:49 +08:00
Breadway
7b9553e4cd fix: add missing build deps for hestia (Ubuntu) runner 2026-06-06 23:20:02 +08:00
Breadway
248b97c92f Add bakery.toml and release workflow; improve connect error reporting
- bakery.toml: describes breadcrumbs for bakery install
- release.yml: builds on hestia self-hosted runner, publishes binary to
  dl.breadway.dev and GitHub Releases on v* tags
- flow.rs/nm.rs: connect_and_verify now returns Result<(), String> with
  a descriptive error message instead of a bare bool
2026-06-06 22:31:29 +08:00
Breadway
3422c12379 Initial commit: breadcrumbs — profile-driven Wi-Fi + Tailscale state machine 2026-05-19 11:52:46 +08:00