Skip to main content

xbp_analysis/domain/
rule.rs

1//! Rule metadata and evaluation interface (domain-facing).
2
3use super::capabilities::CapabilitySet;
4use super::model::LanguageModel;
5use super::types::{Finding, Severity};
6use serde::{Deserialize, Serialize};
7
8/// Static rule descriptor (language-independent catalog entry).
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct RuleMeta {
11    pub id: String,
12    pub name: String,
13    pub description: String,
14    pub default_severity: Severity,
15    /// Capabilities required; if missing, the rule is skipped (graceful degrade).
16    pub required_capabilities: CapabilitySet,
17    /// Whether an autofix may ever be offered (still subject to safety policy).
18    pub autofix_safe: bool,
19}
20
21/// A rule that evaluates a language-independent model.
22pub trait Rule: Send + Sync {
23    fn meta(&self) -> &RuleMeta;
24    fn evaluate(&self, model: &LanguageModel) -> Vec<Finding>;
25}
26
27/// Selection / filter for rules.
28#[derive(Debug, Clone, Default, Serialize, Deserialize)]
29pub struct RuleSelection {
30    pub enabled: Vec<String>,
31    pub disabled: Vec<String>,
32    pub min_severity: Option<Severity>,
33}
34
35impl RuleSelection {
36    pub fn allows(&self, rule_id: &str) -> bool {
37        if self.disabled.iter().any(|d| d == rule_id || d == "*") {
38            return false;
39        }
40        if self.enabled.is_empty() {
41            return true;
42        }
43        self.enabled.iter().any(|e| e == rule_id || e == "*")
44    }
45}