Background
Follow-up from #21, which wired talonctl health to actually fetch alert volumes.
DetectionHealthReport._classify() looks up alert volumes keyed by the detection's template display name (det.display_name or det.name) and matches it against the trigger query's rule.name (from the rule-trigger events repo).
This works only when the deployed rule's name in the console is identical to the current template name: field. When a rule's name has drifted between the two, the detection is silently misreported as zero-hit even though it fired.
Reproduction (observed during #21 validation)
Over a 7-day window, the set of rules that triggered did not fully reconcile with the template inventory: one rule fired in the console under a display name that differed from the name: field in its IaC template. Because the two strings weren't equal, the volume didn't join and the detection showed as zero-hit despite having fired.
Generalized shape of the mismatch:
- Console trigger:
rule.name = "<display name as deployed>"
- IaC template:
name: "<different display name on disk>"
Why it matters
The whole point of health is to surface genuinely silent detections. A name-drift false "zero-hit" undermines that signal and could lead someone to retune or retire a rule that is actually firing.
Proposed direction
Match on stable deployed identity rather than display-name string equality. Options to evaluate:
- Use deployed state. Map
resource_id -> deployed rule name (and/or composite id) from the deployment state file, and key volumes off the deployed name. Most robust, since it reflects what's actually in the console.
- Group the trigger query by a stable rule identifier (e.g. rule id) if the events carry one, and join on that instead of
rule.name.
- At minimum, when a triggered
rule.name matches no template, surface it in the report as an "unmatched / possible drift" bucket instead of dropping it silently — so name drift becomes visible rather than masquerading as a zero-hit.
Option 3 is cheap and could ship independently as a safety net; 1 or 2 are the real fix.
Note
A display-name divergence like this is also genuine config drift (talonctl drift would flag it) and should be reconciled at the source — but health should be resilient to it regardless.
Background
Follow-up from #21, which wired
talonctl healthto actually fetch alert volumes.DetectionHealthReport._classify()looks up alert volumes keyed by the detection's template display name (det.display_name or det.name) and matches it against the trigger query'srule.name(from the rule-trigger events repo).This works only when the deployed rule's name in the console is identical to the current template
name:field. When a rule's name has drifted between the two, the detection is silently misreported as zero-hit even though it fired.Reproduction (observed during #21 validation)
Over a 7-day window, the set of rules that triggered did not fully reconcile with the template inventory: one rule fired in the console under a display name that differed from the
name:field in its IaC template. Because the two strings weren't equal, the volume didn't join and the detection showed as zero-hit despite having fired.Generalized shape of the mismatch:
rule.name = "<display name as deployed>"name: "<different display name on disk>"Why it matters
The whole point of
healthis to surface genuinely silent detections. A name-drift false "zero-hit" undermines that signal and could lead someone to retune or retire a rule that is actually firing.Proposed direction
Match on stable deployed identity rather than display-name string equality. Options to evaluate:
resource_id-> deployed rule name (and/or composite id) from the deployment state file, and key volumes off the deployed name. Most robust, since it reflects what's actually in the console.rule.name.rule.namematches no template, surface it in the report as an "unmatched / possible drift" bucket instead of dropping it silently — so name drift becomes visible rather than masquerading as a zero-hit.Option 3 is cheap and could ship independently as a safety net; 1 or 2 are the real fix.
Note
A display-name divergence like this is also genuine config drift (
talonctl driftwould flag it) and should be reconciled at the source — buthealthshould be resilient to it regardless.