1use super::engine::{GateProfile, QualityGate, QualityMetric};
6
7pub fn strict_profile() -> GateProfile {
18 GateProfile::new(
19 "strict",
20 vec![
21 QualityGate::lte("benford_compliance", QualityMetric::BenfordMad, 0.01),
22 QualityGate::gte("balance_coherence", QualityMetric::BalanceCoherence, 0.999),
23 QualityGate::gte(
24 "document_chain_integrity",
25 QualityMetric::DocumentChainIntegrity,
26 0.95,
27 ),
28 QualityGate::gte(
29 "temporal_consistency",
30 QualityMetric::TemporalConsistency,
31 0.90,
32 ),
33 QualityGate::gte("completion_rate", QualityMetric::CompletionRate, 0.99),
34 QualityGate::lte("duplicate_rate", QualityMetric::DuplicateRate, 0.001),
35 QualityGate::gte(
36 "referential_integrity",
37 QualityMetric::ReferentialIntegrity,
38 0.999,
39 ),
40 QualityGate::gte("ic_match_rate", QualityMetric::IcMatchRate, 0.99),
41 QualityGate::lte("privacy_mia_auc", QualityMetric::PrivacyMiaAuc, 0.55),
42 ],
43 )
44}
45
46pub fn default_profile() -> GateProfile {
57 GateProfile::new(
58 "default",
59 vec![
60 QualityGate::lte("benford_compliance", QualityMetric::BenfordMad, 0.015),
61 QualityGate::gte("balance_coherence", QualityMetric::BalanceCoherence, 0.99),
62 QualityGate::gte(
63 "document_chain_integrity",
64 QualityMetric::DocumentChainIntegrity,
65 0.90,
66 ),
67 QualityGate::gte(
68 "temporal_consistency",
69 QualityMetric::TemporalConsistency,
70 0.80,
71 ),
72 QualityGate::gte("completion_rate", QualityMetric::CompletionRate, 0.95),
73 QualityGate::lte("duplicate_rate", QualityMetric::DuplicateRate, 0.01),
74 QualityGate::gte(
75 "referential_integrity",
76 QualityMetric::ReferentialIntegrity,
77 0.99,
78 ),
79 QualityGate::gte("ic_match_rate", QualityMetric::IcMatchRate, 0.95),
80 QualityGate::lte("privacy_mia_auc", QualityMetric::PrivacyMiaAuc, 0.60),
81 ],
82 )
83}
84
85pub fn lenient_profile() -> GateProfile {
96 GateProfile::new(
97 "lenient",
98 vec![
99 QualityGate::lte("benford_compliance", QualityMetric::BenfordMad, 0.03),
100 QualityGate::gte("balance_coherence", QualityMetric::BalanceCoherence, 0.95),
101 QualityGate::gte(
102 "document_chain_integrity",
103 QualityMetric::DocumentChainIntegrity,
104 0.80,
105 ),
106 QualityGate::gte(
107 "temporal_consistency",
108 QualityMetric::TemporalConsistency,
109 0.60,
110 ),
111 QualityGate::gte("completion_rate", QualityMetric::CompletionRate, 0.90),
112 QualityGate::lte("duplicate_rate", QualityMetric::DuplicateRate, 0.05),
113 QualityGate::gte(
114 "referential_integrity",
115 QualityMetric::ReferentialIntegrity,
116 0.95,
117 ),
118 QualityGate::gte("ic_match_rate", QualityMetric::IcMatchRate, 0.85),
119 QualityGate::lte("privacy_mia_auc", QualityMetric::PrivacyMiaAuc, 0.70),
120 ],
121 )
122}
123
124pub fn get_profile(name: &str) -> Option<GateProfile> {
128 match name {
129 "strict" => Some(strict_profile()),
130 "default" => Some(default_profile()),
131 "lenient" => Some(lenient_profile()),
132 _ => None,
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn test_strict_profile_has_gates() {
142 let profile = strict_profile();
143 assert_eq!(profile.name, "strict");
144 assert!(!profile.gates.is_empty());
145 assert!(profile.gates.len() >= 5);
146 }
147
148 #[test]
149 fn test_default_profile_has_gates() {
150 let profile = default_profile();
151 assert_eq!(profile.name, "default");
152 assert!(!profile.gates.is_empty());
153 }
154
155 #[test]
156 fn test_lenient_profile_has_gates() {
157 let profile = lenient_profile();
158 assert_eq!(profile.name, "lenient");
159 assert!(!profile.gates.is_empty());
160 }
161
162 #[test]
163 fn test_strict_thresholds_tighter_than_lenient() {
164 let strict = strict_profile();
165 let lenient = lenient_profile();
166
167 let strict_benford = strict
169 .gates
170 .iter()
171 .find(|g| g.metric == QualityMetric::BenfordMad);
172 let lenient_benford = lenient
173 .gates
174 .iter()
175 .find(|g| g.metric == QualityMetric::BenfordMad);
176
177 if let (Some(s), Some(l)) = (strict_benford, lenient_benford) {
178 assert!(
180 s.threshold < l.threshold,
181 "strict MAD ({}) should be < lenient MAD ({})",
182 s.threshold,
183 l.threshold
184 );
185 }
186 }
187
188 #[test]
189 fn test_get_profile_by_name() {
190 assert!(get_profile("strict").is_some());
191 assert!(get_profile("default").is_some());
192 assert!(get_profile("lenient").is_some());
193 assert!(get_profile("nonexistent").is_none());
194 }
195
196 #[test]
197 fn test_profile_serialization_roundtrip() {
198 for name in &["strict", "default", "lenient"] {
199 let profile = get_profile(name).expect("profile should exist");
200 let json = serde_json::to_string(&profile).expect("should serialize");
201 let deser: GateProfile = serde_json::from_str(&json).expect("should deserialize");
202 assert_eq!(deser.name, *name);
203 assert_eq!(deser.gates.len(), profile.gates.len());
204 }
205 }
206}