The guard emitted nothing when it passed, so its success was indistinguishable
in the CI log from the step never running at all — the same silent-skip failure
mode it exists to catch, one level up. Confirmed on run 332: the job was green
and the log carried no trace of the step either way.
Each crate/target check and the canary now echo their result, followed by a
count and the exit code, so a reader can see the guard ran and what it proved.
Verified by extracting the run: block from the workflow and executing it
verbatim under bash -e: 4 checks, canary found, exit 0.
cargo update -p rustls-webpki -p tar moves rustls-webpki 0.103.9 -> 0.103.13
and tar 0.4.44 -> 0.4.46, both within the existing Cargo.toml bounds. They sit
under tauri-plugin-updater, which downloads and unpacks application updates, so
all six of their advisories were reachable in the shipped binary.
The remaining three can neither be fixed nor reached. quick-xml (2x 7.5 high)
is pulled by plist, which tauri only needs for Apple bundling: its per-target
trees are empty for both shipped targets and it appears solely under
x86_64-apple-darwin. Its fix is >= 0.41.0 while plist requires ^0.38, a
semver-incompatible boundary [patch.crates-io] cannot cross. rsa has no
published fix at all and is never compiled — its only parent is sqlx-mysql, an
artifact of sqlx's multi-backend graph on a SQLite project.
Leaving those three to red the daily gate forever would reproduce the signal
loss that #232 removed the `|| true` to fix, so they move into a versioned
.cargo/audit.toml. Entries are keyed by advisory ID, never by crate, so a new
advisory against the same crate still reds the gate; each carries its
reachability proof and its removal condition.
A blocking step in check-rust.yml re-proves that justification on every PR
touching src-tauri/ or .cargo/, and fails if a suppressed crate enters a
shipped target's graph — the scenario that would rot the list is itself a
src-tauri change. It separates cargo tree's exit status from its output (an
absent crate and a failed invocation both print nothing) and asserts a canary
crate is still found, so its silence proves something.
cargo audit: 9 vulnerabilities -> 0, warnings unchanged at 23
(cargo-audit 0.22.2, advisory-db 0bfde9d6 of 2026-07-27).
cargo check + cargo test green (106 tests); npm build + 871 vitest green.
Resolves#310
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rust job cost 21m44s on every PR while only ~1 PR in 40 touches
src-tauri/, and the runner has capacity 1 — the frontend job queues behind
it, so every PR paid ~24.5 min of feedback.
Measured on run 326 (2026-07-21), 12m15s of that was pure waste:
- 6m54s tarring target/ and the cargo registry for saves that time out
against the runner's unreachable cache server (#234). The restore times
out into a miss too, so nothing was ever cached at either end.
- 4m41s recompiling cargo-audit from source on every run.
- ~40s on the two doomed restores.
Split check.yml into check-rust.yml (paths: src-tauri/**) and
check-frontend.yml (paths-ignore denylist), drop every actions/cache step
until #234 is fixed, and install cargo-audit as a prebuilt binary via
taiki-e/install-action. The audit step keeps continue-on-error — advisories
are informational and can land on unrelated crates — but loses the `|| true`
that also hid tooling failures; the install step is blocking.
The frontend filter is a denylist on purpose: that job costs ~2.5 min, so
running it needlessly is cheap while silently not running it is not. The
expensive job keeps a strict allowlist.
Neither workflow filters on `branches:` anymore. `branches: [main]` never
matched a PR stacked on another feature branch, which is what /autopilot
produces: PRs #305-#308 of the feature-gating milestone ran no CI at all.
Adds audit.yml for daily RustSec coverage, since check-rust.yml now only
runs on Rust PRs. It skips the Rust toolchain entirely — cargo-audit only
reads Cargo.lock — so it costs ~1-2 min rather than the ~22 a scheduled
check-rust would burn daily on a capacity-1 runner.
The GitHub mirror is left untouched (#233: it receives no PRs).
Expected: Rust PR ~9-10 min, frontend-only PR ~2.5 min instead of ~24.5.
Resolves#232