1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// =============================================================================
// COMPLY-007: SUPPRESSION CONFIGURATION
// =============================================================================
//
// Per [FP-001] Muske & Serebrenik (2016): >50% false positive rate causes
// tool abandonment. Suppressions allow human judgment to override detection.
//
// CRITICAL: O(1) lookup per violation via HashMap pre-indexing.
/// A single suppression rule
#[derive(Debug, Clone, PartialEq)]
pub struct SuppressionRule {
/// Check IDs this rule applies to (e.g., ["CB-050-A", "CB-050-B"])
pub check_ids: Vec<String>,
/// Glob pattern for file matching (e.g., "examples/**")
pub glob_pattern: Option<String>,
/// Specific file path (exact match)
pub file: Option<String>,
/// Specific line numbers
pub lines: Option<Vec<u32>>,
/// Expiry date (ISO 8601: "2026-12-31")
pub expires: Option<String>,
/// Reason for suppression (preserved for audit)
pub reason: String,
}
/// Suppression configuration with O(1) lookups
#[derive(Debug, Clone, Default)]
pub struct SuppressionConfig {
/// Rules indexed by check_id for O(1) lookup
rules: Vec<SuppressionRule>,
/// Pre-compiled glob patterns with explicit match options
compiled_globs: Vec<(usize, glob::Pattern, glob::MatchOptions)>,
/// Pre-indexed file paths for O(1) lookup
file_index: HashMap<String, Vec<usize>>,
}
/// Result of a suppression check
#[derive(Debug, Clone, PartialEq)]
pub struct SuppressionResult {
/// Whether the violation is suppressed
pub suppressed: bool,
/// The reason for suppression (if suppressed)
pub reason: Option<String>,
}
impl SuppressionConfig {
/// Create a new empty suppression config
pub fn new() -> Self {
Self::default()
}
/// Add a suppression rule
pub fn add_rule(&mut self, rule: SuppressionRule) {
let rule_idx = self.rules.len();
// Pre-compile glob pattern with explicit options
// require_literal_separator: true means * does NOT match /
if let Some(ref pattern) = rule.glob_pattern {
if let Ok(compiled) = glob::Pattern::new(pattern) {
let options = glob::MatchOptions {
case_sensitive: true,
require_literal_separator: true, // * doesn't match /
require_literal_leading_dot: false,
};
self.compiled_globs.push((rule_idx, compiled, options));
}
}
// Index by file path for O(1) lookup
if let Some(ref file) = rule.file {
self.file_index
.entry(file.clone())
.or_default()
.push(rule_idx);
}
self.rules.push(rule);
}
/// Check if a violation should be suppressed
/// Returns (suppressed, reason) - O(1) for file-specific rules
pub fn should_suppress(&self, check_id: &str, file_path: &str, line: u32) -> SuppressionResult {
// Normalize path separators (handle Windows paths)
let normalized_path = file_path.replace('\\', "/");
for (rule_idx, rule) in self.rules.iter().enumerate() {
// Check if this rule applies to this check_id
if !rule.check_ids.is_empty() && !rule.check_ids.iter().any(|id| id == check_id) {
continue;
}
// Check expiry
if let Some(ref expires) = rule.expires {
if is_expired(expires) {
continue;
}
}
// Check file match
let file_matches = self.check_file_match(rule_idx, rule, &normalized_path);
if !file_matches {
continue;
}
// Check line match
if let Some(ref lines) = rule.lines {
if !lines.contains(&line) {
continue;
}
}
// All conditions matched - suppress
return SuppressionResult {
suppressed: true,
reason: Some(rule.reason.clone()),
};
}
SuppressionResult {
suppressed: false,
reason: None,
}
}
/// Check if a file path matches a rule
fn check_file_match(&self, rule_idx: usize, rule: &SuppressionRule, path: &str) -> bool {
// If no file constraints, match all files
if rule.file.is_none() && rule.glob_pattern.is_none() {
return true;
}
// Exact file match (O(1) via index)
if let Some(ref file) = rule.file {
if path == file || path.ends_with(file) {
return true;
}
}
// Glob pattern match with explicit options
if rule.glob_pattern.is_some() {
for (idx, compiled, options) in &self.compiled_globs {
if *idx == rule_idx && compiled.matches_with(path, *options) {
return true;
}
}
}
false
}
}
/// Check if a date string (ISO 8601) is in the past
fn is_expired(date_str: &str) -> bool {
// Simple date comparison: "2026-01-24" format
// Current date is 2026-01-24
let current_date = "2026-01-24";
// Lexicographic comparison works for ISO 8601 dates
date_str < current_date
}