Summary
Rule name uniqueness is currently enforced by convention — the 223 built-in rules live in a deterministic YAML file embedded at compile time (include_str!) with unique names. However, neither Engine::new_with_anchor_policy, load_rules_from_content, nor RuleSpec::assert_valid perform a runtime cross-rule uniqueness check.
Because RuleCold::fingerprint is derived solely from RuleSpec.name via BLAKE3 derive-key (domain "gossip/rule/v1"), two rules sharing the same name will produce identical fingerprints. If such a collision were ever introduced (e.g., via a custom rule set or a YAML edit), findings from the two distinct rules would be merged or deduplicated incorrectly downstream in the persistence layer.
Proposed fix
Add a HashSet-based duplicate-name check during rule loading/engine construction as defense-in-depth:
- Collect each
RuleSpec.name into a HashSet<&str> while iterating the rule list.
- Return an error (or panic in debug builds) if a duplicate name is detected.
- Candidate locations:
Engine::new_with_anchor_policy or load_rules_from_content.
Per-rule validation should remain in RuleSpec::assert_valid; the cross-rule uniqueness check is a separate concern.
Context
Summary
Rule name uniqueness is currently enforced by convention — the 223 built-in rules live in a deterministic YAML file embedded at compile time (
include_str!) with unique names. However, neitherEngine::new_with_anchor_policy,load_rules_from_content, norRuleSpec::assert_validperform a runtime cross-rule uniqueness check.Because
RuleCold::fingerprintis derived solely fromRuleSpec.namevia BLAKE3 derive-key (domain"gossip/rule/v1"), two rules sharing the same name will produce identical fingerprints. If such a collision were ever introduced (e.g., via a custom rule set or a YAML edit), findings from the two distinct rules would be merged or deduplicated incorrectly downstream in the persistence layer.Proposed fix
Add a
HashSet-based duplicate-name check during rule loading/engine construction as defense-in-depth:RuleSpec.nameinto aHashSet<&str>while iterating the rule list.Engine::new_with_anchor_policyorload_rules_from_content.Per-rule validation should remain in
RuleSpec::assert_valid; the cross-rule uniqueness check is a separate concern.Context