feat(ui): quieten the dashboard — mute checks, hide app noise, honest sparkline (v0.23.6-beta)

Closes #101, #103, #104, #106, #111. Partially addresses #96.

A batch of signal-to-noise fixes reported together. Individually small; together
they are the difference between a dashboard someone reads and one they learn to
ignore.

#101 — security heuristics can be muted
  A warning you disagree with and cannot dismiss discredits every other finding
  beside it. Cleartext API is the reported case: on a fleet reachable only across
  WireGuard, TLS adds nothing to the threat model, and the check is permanent noise.
  Missing input-chain firewall is the same on a switch behind a router — the message
  even says "confirm that is the case", while offering no way to record that you did.

  Checks can now be muted per device or fleet-wide. Muted findings are still listed,
  greyed and labelled, and excluded from the score — not hidden. Hiding them would
  make the posture unauditable, which is a worse failure than noise.

#103 — the app's own requests are hidden from Recent activity
  Audit entries for writes made through the UI are noise from an operations point of
  view. Off by default now, with a toggle that names how many are hidden, remembered
  per browser since it is a viewing preference rather than fleet configuration.

#104 — quick actions moved into the header strip
  Matching the Wireless page. "Things to handle" takes the full width it was already
  overflowing.

#106 — map lookups can be turned off
  Geocoding hits nominatim.openstreetmap.org and the map pulls OSM tiles. On an
  isolated network those hang; everywhere else they disclose where your devices are
  to a third party, which the report understates. A maps_enabled setting stops both
  requests; stored coordinates are still shown as plain text so nothing is lost.

#111 — the CPU sparkline says something
  It was drawn in one colour and auto-scaled to each device's own peak, so an idle
  device and a saturated one produced an identical picture. Now plotted against a
  fixed 0-100 scale, coloured by the band its peak falls into — a flat line low in
  the box is an idle device and looks like one.

#96 — groundwork
  TX-retry figures come from CCQ, which only the legacy `wireless` driver reports, so
  the panel is permanently empty on a RouterOS 7 fleet. The wireless package each
  device runs is now recorded, and a capabilities endpoint answers the fleet-wide
  question. The panel is dropped and the density chart takes the full width when
  nothing can supply the data — and shown when nothing has been polled yet, rather
  than hiding a panel that may populate a minute later.

Verified against the fleet: muting cleartext API moved a device's score from 87 to
90 with the finding still listed and marked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2GT-Rich
2026-08-22 14:18:41 -07:00
co-authored by Claude Opus 5
parent 4cc8c84ea6
commit dcd89fe86b
14 changed files with 327 additions and 70 deletions
+25
View File
@@ -958,6 +958,31 @@ router.get('/rf/signals', async (req: Request, res: Response) => {
res.json(rows);
});
/**
* GET /api/wireless/rf/capabilities — what the fleet's wireless hardware can report.
*
* TX-retry figures are derived from per-client CCQ, which only the legacy `wireless`
* driver exposes. On an all-RouterOS-7 fleet that panel can never have data, so the
* UI needs to know rather than rendering an empty box forever (issue #96).
*/
router.get('/rf/capabilities', async (_req: Request, res: Response) => {
const rows = await query<{ wifi_package: string | null; n: string }>(`
SELECT wifi_package, COUNT(*) AS n
FROM devices
WHERE wifi_package IS NOT NULL AND wifi_package <> 'none'
GROUP BY wifi_package`);
const counts = Object.fromEntries(rows.map((r) => [r.wifi_package ?? 'unknown', Number(r.n)]));
const legacy = counts['wireless'] ?? 0;
res.json({
packages: counts,
legacyRadios: legacy,
// Unknown means nothing has been polled yet; show the panel rather than
// hiding something that may well populate a minute later.
txRetriesAvailable: legacy > 0 || rows.length === 0,
});
});
// GET /api/wireless/rf/tx-quality?range=6h — latest per-radio TX retry % (from CCQ)
router.get('/rf/tx-quality', async (req: Request, res: Response) => {
const deviceId = deviceScope(req);