GitHub
09/03/2026, 7:27 AMš 3 alert rules Ā· 1 this node Ā· 1 env Ā· 1 globalIt links to the Alerts page, and its tooltip names every covering rule and why it applies ā
node-errors ā this node, env-wide ā environment prod,
everywhere ā global ā so all three scopes are accounted for, not just the
node-specific ones created from "Alert on this node".
How coverage is decided
frontend/src/features/nodes/alertCoverage.ts (new) mirrors pkg/alerts rather
than reinventing the predicate. It is the same test the ingest matcher
(matcher.go, ruleApplies + nodeScope) and the inactive sweep (inactive.go)
already apply, which is what makes the marker trustworthy:
⢠enabled rules only ā the rule snapshot loads only enabled rows, so a
switched-off rule marks nothing.
⢠env 0 is global, any other value must equal the node's environment.
⢠*empty node scope covers every node*; a set scope must equal this UUID,
compared case-sensitively and trimmed, exactly as the server does. A
lowercased scope on an uppercase node truly never fires, and claiming coverage
that will not happen is worse than showing none.
⢠most specific first ā a rule written for this node ranks above the blanket
ones.
Wiring notes
⢠One unfiltered listAlertRules() serves all three scopes. It is keyed under the
existing ['alert-rules'] prefix, so creating a rule from the node modal
refreshes the marker with no extra plumbing.
⢠The query is gated on global admin, not `canAdminNode`: listing rules is
global-admin-only, so gating on the looser check would fire a request the
server refuses. Consequence to be aware of ā the marker is invisible to
env-admins until the requireAlertsAdmin gate is revisited.
⢠Also hoisted the page's environment lookup into one envRow (it was resolved
twice, once inline for the alert modal).
Tests
⢠alertCoverage.test.ts (new) ā scope attribution and ordering; exclusion of
other environments, other nodes and disabled rules; the case-sensitivity and
trim contract; global-only attribution before the environment resolves.
⢠NodeDetailPage.test.tsx ā a mixed five-rule set (node / env / global /
other-node / disabled) renders the right count, summary and tooltip; and no
marker at all when nothing covers the node.
74 node-feature tests pass (322 frontend total), tsc --noEmit clean. Frontend
only ā no API or schema changes.
jmpsec/osctrlGitHub
09/03/2026, 7:31 AM