Skip to content

fix(hosts): Avg compliance KPI now matches /dashboard (shared fleet/score)#676

Merged
remyluslosius merged 2 commits into
mainfrom
fix/hosts-avg-compliance-parity
Jun 25, 2026
Merged

fix(hosts): Avg compliance KPI now matches /dashboard (shared fleet/score)#676
remyluslosius merged 2 commits into
mainfrom
fix/hosts-avg-compliance-parity

Conversation

@remyluslosius

Copy link
Copy Markdown
Contributor

Problem

/dashboard and /hosts both show an "Avg compliance" tile, but the numbers differed. Both read host_rule_state, with different denominators:

Numerator Denominator
/dashboard (GET /api/v1/fleet/score) passing passing + failing
/hosts (kpisFromHosts) passing total = COUNT(*) incl. skipped + error

Kensa marks a large share of the corpus not-applicable (skipped) per host, so the /hosts figure read materially lower. passing/(passing+failing) is the canonical metric — it's also what drift.ComplianceScore uses to drive the scheduler bands.

Fix

Source the /hosts headline KPI from the same /api/v1/fleet/score endpoint the dashboard uses (shared queryKey ['fleet','score'], same Math.round(passing_fraction*100)). The two tiles are now literally the same number and can't drift. The client-side kpisFromHosts aggregate stays as a fallback until the fleet score resolves.

  • Spec frontend-hosts-list v1.8.0: new C-13 + AC-26 + source-inspection test.
  • tsc + eslint clean; full suite 338 green; specter check 113 specs, coverage 100%.

Related (not in this PR)

The per-host card compliance % (the donut on each host card) still uses passing/total (skipped-inclusive), which differs from the canonical band metric. That's internally consistent on the card but means the cards won't visually average to the headline tile, and a host's card color can differ from its scheduler band. Worth a follow-up to align per-host display to passing/(passing+failing) (touches AC-16 + card wording + sort/tier). Also: fleet/score has no deleted_at filter, so residual host_rule_state rows for soft-deleted hosts count toward the fleet number — a small backend correctness fix. Happy to file/do both.

… /dashboard

The /dashboard and /hosts 'Avg compliance' tiles showed different numbers
because they used different denominators over the same host_rule_state data:
  - /dashboard (GET /api/v1/fleet/score): passing / (passing + failing)
  - /hosts (kpisFromHosts): passing / total, where total = COUNT(*) including
    skipped + error rows.
Kensa marks many rules not-applicable (skipped) per host, so the /hosts figure
read materially lower. passing/(passing+failing) is the canonical metric (it
also drives the scheduler bands via drift.ComplianceScore).

Source the /hosts headline KPI from the same /api/v1/fleet/score endpoint the
dashboard uses (shared queryKey ['fleet','score'], same round(passing_fraction
*100)) so the two surfaces are literally the same number and cannot drift. The
client-side kpisFromHosts aggregate remains a fallback until the score loads.

Spec frontend-hosts-list v1.8.0: new C-13 + AC-26 + source-inspection test.
@remyluslosius remyluslosius merged commit 5645bde into main Jun 25, 2026
13 of 14 checks passed
@remyluslosius remyluslosius deleted the fix/hosts-avg-compliance-parity branch June 25, 2026 14:05
remyluslosius added a commit that referenced this pull request Jun 25, 2026
… flake

It hard-asserts 2s and gated #676's CI under -race (passed on rerun); it missed
the 2026-06-21 perftest.Budgetf() migration the other perf tests got.
remyluslosius added a commit that referenced this pull request Jun 25, 2026
* docs: session meta — CHANGELOG, SESSION_LOG (2026-06-25), STATUS.md

Document the 2026-06-25 session's in-flight work (PKG-3 #673, AUTH-1 #675/#678,
notifications Slice 1 #679, avg-compliance #676): CHANGELOG [Unreleased]
entries, a SESSION_LOG handoff entry, and a new STATUS.md one-page snapshot.
BACKLOG findings from the security review land in a follow-up commit.

* docs(guides): truthfulness fixes from the 2026-06-25 audit + BACKLOG DOC-3

High-impact, verified guide defects fixed:
- UPGRADE/QUICKSTART/ENVIRONMENT/MONITORING: --config is a GLOBAL flag (Go flag
  parsing stops at the first non-flag arg), so 'openwatch migrate --config X'
  silently ignored --config. Moved --config before the subcommand everywhere.
- COMPLIANCE_CONTROLS: removed the invented 'analyst' role + 'three-tier role
  model' (real: 5 roles — viewer/auditor/ops_lead/security_admin/admin) and the
  fabricated '100/min per user, 1000/min per IP' rate-limit (real: per-IP
  sliding window on the auth endpoints).
- API_GUIDE: the 'not yet in the API' section was almost entirely false (scans,
  remediation, exceptions, posture/drift, audit export, rule browser all ship);
  rewrote it to list the live surface + only the genuinely-absent /metrics and
  /security-info. Added the missing ops_lead role to the role table.
- Version sweep rc.13 -> rc.14; bumped Last Updated to 2026-06-25 on edited guides.

BACKLOG DOC-3 captures the remaining audit items (SCANNING dead-endpoint
appendix, USER_ROLES matrix, INSTALLATION PG-dep, DATABASE_MIGRATIONS fake
output, style sweep) and flags the audit's '538->539' suggestion as a FALSE
POSITIVE — rc.14 bundles Kensa v0.6.0 = 538 (the guides correctly say 538).

* docs(backlog): note the gating TestApply_1000Rules_Under2Seconds perf flake

It hard-asserts 2s and gated #676's CI under -race (passed on rerun); it missed
the 2026-06-21 perftest.Budgetf() migration the other perf tests got.
remyluslosius added a commit that referenced this pull request Jun 25, 2026
Bump version.env to 0.2.0-rc.15 and cut the CHANGELOG [Unreleased] accumulator
into a dated [0.2.0-rc.15] section covering everything landed since rc.14:
- PKG-3 remediation store-path fix (production-breaking) (#673)
- AUTH-1: client idle timer (#675) + absolute-timeout ceiling +
  slide-on-user-activity (#678)
- Notifications Slice 1: durable change-driven bell (#679)
- Avg-compliance parity /hosts <-> /dashboard (#676)

Local: changelog + version-consistency + fips + package-build tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant