Skip to content

Split the operator TUI out of the detector's supply chain - #19

Merged
Ray-Rose merged 1 commit into
mainfrom
refactor/detach-watch-tui
Aug 17, 2026
Merged

Split the operator TUI out of the detector's supply chain#19
Ray-Rose merged 1 commit into
mainfrom
refactor/detach-watch-tui

Conversation

@Ray-Rose

Copy link
Copy Markdown
Owner

Why

Found auditing the repo as a whole rather than file-by-file — it is invisible from inside any single file.

flyingsquirrel-watch shares no code with the detector. It reads the JSON event log with its own permissive structs (deliberately, so a schema change can't break it). Yet as a [[bin]] in the root package, its dependency tree was welded to the safety-critical one:

Cost Detail
2 advisory suppressions ratatui → lru 0.12 put RUSTSEC-2026-0002 and -0253 in the detector's cargo audit. Suppressed as "ratatui's widget cache, NOT the detector" — true, but nothing in the build enforced it
The MSRV ratatui → instability → darling was the sole reason rust-version was 1.88 rather than 1.85
Shipped weight A terminal UI in every ARM cross-build, the Docker image, and fuzz/Cargo.lock

The last one is how it surfaced: the NMEA/MAVLink fuzz harness was getting Dependabot PRs for a TUI library (#17, ratatui 0.30). A security tool that decodes wire bytes had no business tracking a dashboard's dependencies.

What

Move it to watch/ as a detached workspace with its own lockfile — same pattern, same reason, as fuzz/.

A workspace member would not work: members share one Cargo.lock, so lru would remain in the detector's audit scope and the whole exercise would be pointless. That's why this is a detached crate.

Result: 34 crates leave the detector (288 → 254). lru, ratatui, crossterm, darling, instability are gone from the detector's and the fuzz harness's lockfiles — so the two lru ignores are deleted from ci.yml rather than argued. They now live in a new watch CI job scoped to the crate that actually pulls them. The boundary is structural instead of asserted.

MSRV: re-derived, not assumed

It stays 1.88. I expected it to drop to 1.85 and checked rather than claiming it — with ratatui gone the binding constraint moved to nmea → serde_with → time 0.3.47. Verified by a reachability walk over cargo metadata --filter-platform x86_64-unknown-linux-gnu excluding dev-deps, because the flat package list includes unlinked entries and gives the wrong answer.

That's a better place for the floor: a core functional dependency rather than an operator dashboard.

Also in this pass

Verified

  • Detector: cargo fmt --check, clippy --all-targets --all-features -D warnings, 182 lib tests, 35 integration tests across all 14 suites (run individually), 10 proptests.
  • watch/: cargo fmt --check, clippy --all-targets -D warnings, 4 tests.
  • Confirmed lru/ratatui/crossterm/darling/instability absent from both Cargo.lock and fuzz/Cargo.lock.

Not changed

No detector logic. Zero lines of detection, nav, MAVLink, or hardware-ingest code were touched — this is packaging, dependency scope, and docs.

🤖 Generated with Claude Code

`flyingsquirrel-watch` shares no code with the detector — it reads the
JSON event log with its own permissive structs, deliberately, so a schema
change can't break it. But as a `[[bin]]` in the root package its
dependency tree was welded to the safety-critical one, and that had real
costs:

  * `ratatui -> lru 0.12` put two unsoundness advisories
    (RUSTSEC-2026-0002, -0253) into the detector's `cargo audit`. Both
    were suppressed with the rationale "ratatui's widget cache, NOT the
    detector." True, and unenforced — nothing in the build made it so.
  * `ratatui -> instability -> darling` was the SOLE reason the declared
    MSRV was 1.88 rather than 1.85.
  * A terminal UI rode along in every ARM cross-build, the Docker image,
    and `fuzz/Cargo.lock` — the NMEA/MAVLink fuzz harness was receiving
    Dependabot PRs for a TUI library, which is how the coupling surfaced.

Move it to `watch/` as a detached workspace with its own lockfile, the
same pattern (and for the same reason) as `fuzz/`. A workspace MEMBER
would not do: members share one lockfile, so `lru` would stay in the
detector's audit scope and the exercise would be pointless.

Result: 34 crates leave the detector (288 -> 254). `lru`, `ratatui`,
`crossterm`, `darling`, `instability` are gone from both the detector's
and the fuzz harness's lockfiles, so the two `lru` ignores are DELETED
from ci.yml rather than argued. They now live in a `watch` job scoped to
the crate that actually pulls them — the boundary is structural.

MSRV stays 1.88. I re-derived it instead of assuming it dropped: with
ratatui gone the binding constraint moved to `nmea -> serde_with ->
time 0.3.47`, verified by a reachability walk over `cargo metadata
--filter-platform` excluding dev-deps. That is a core functional
dependency rather than a dashboard, which is the defensible place for it.

Also in this pass:
  * Dependency bumps that were open as separate PRs, applied together so
    the tree resolves once: toml 0.8 -> 1.1 and thiserror 1.0 -> 2.0
    (both major), tokio-stream, async-trait. Full suite green on both.
  * deploy/Dockerfile: the builder image had been bumped 1.88 -> 1.97
    while still carrying an "MSRV = 1.88, keep in sync" comment. The
    image tracks a current toolchain on purpose; proving the MSRV is the
    CI `msrv` job's duty. Split the two so a base-image bump can't
    silently invalidate the claim again.
  * Delete docs/sitl_driver.py — a deprecated prototype, superseded by
    deploy/sitl/sitl_harness.py, guarded to refuse to run, referenced by
    nothing. Git history keeps it.
  * README: document the dashboard (a shipped binary that had no docs at
    all) and correct the now-stale MSRV rationale.

Verified: detector fmt + clippy(-D warnings, --all-targets
--all-features) + 182 lib + 35 integration across all 14 suites + 10
proptests; watch crate fmt + clippy + 4 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant