1use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct EvaluationConfig {
9 pub statistical: StatisticalConfig,
11 pub coherence: CoherenceConfig,
13 pub quality: QualityConfig,
15 pub ml: MlConfig,
17 #[serde(default)]
19 pub privacy: PrivacyEvaluationConfig,
20 pub report: ReportConfig,
22 pub thresholds: EvaluationThresholds,
24 #[serde(default)]
26 pub quality_gates: QualityGateConfig,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct QualityGateConfig {
32 #[serde(default)]
34 pub enabled: bool,
35 #[serde(default = "default_gate_profile")]
37 pub profile: String,
38 #[serde(default)]
40 pub custom_gates: Vec<CustomGateConfig>,
41 #[serde(default)]
43 pub fail_on_violation: bool,
44}
45
46fn default_gate_profile() -> String {
47 "default".to_string()
48}
49
50impl Default for QualityGateConfig {
51 fn default() -> Self {
52 Self {
53 enabled: false,
54 profile: default_gate_profile(),
55 custom_gates: Vec::new(),
56 fail_on_violation: false,
57 }
58 }
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct CustomGateConfig {
64 pub name: String,
66 pub metric: String,
68 pub threshold: f64,
70 #[serde(default)]
72 pub upper_threshold: Option<f64>,
73 #[serde(default = "default_comparison")]
75 pub comparison: String,
76}
77
78fn default_comparison() -> String {
79 "gte".to_string()
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct PrivacyEvaluationConfig {
85 pub mia_enabled: bool,
87 pub linkage_enabled: bool,
89 pub nist_alignment_enabled: bool,
91 pub synqp_enabled: bool,
93 pub mia_auc_threshold: f64,
95 pub max_reidentification_rate: f64,
97 pub min_k_anonymity: usize,
99}
100
101impl Default for PrivacyEvaluationConfig {
102 fn default() -> Self {
103 Self {
104 mia_enabled: false,
105 linkage_enabled: false,
106 nist_alignment_enabled: false,
107 synqp_enabled: false,
108 mia_auc_threshold: 0.6,
109 max_reidentification_rate: 0.05,
110 min_k_anonymity: 5,
111 }
112 }
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct StatisticalConfig {
118 pub benford_enabled: bool,
120 pub amount_distribution_enabled: bool,
122 pub line_item_enabled: bool,
124 pub temporal_enabled: bool,
126 pub drift_detection_enabled: bool,
128 pub significance_level: f64,
130 pub min_sample_size: usize,
132 pub drift_window_size: usize,
134}
135
136impl Default for StatisticalConfig {
137 fn default() -> Self {
138 Self {
139 benford_enabled: true,
140 amount_distribution_enabled: true,
141 line_item_enabled: true,
142 temporal_enabled: true,
143 drift_detection_enabled: true,
144 significance_level: 0.05,
145 min_sample_size: 100,
146 drift_window_size: 10,
147 }
148 }
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct CoherenceConfig {
154 pub balance_enabled: bool,
156 pub subledger_enabled: bool,
158 pub document_chain_enabled: bool,
160 pub intercompany_enabled: bool,
162 pub referential_enabled: bool,
164 pub balance_tolerance: Decimal,
166}
167
168impl Default for CoherenceConfig {
169 fn default() -> Self {
170 Self {
171 balance_enabled: true,
172 subledger_enabled: true,
173 document_chain_enabled: true,
174 intercompany_enabled: true,
175 referential_enabled: true,
176 balance_tolerance: Decimal::new(1, 2), }
178 }
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct QualityConfig {
184 pub uniqueness_enabled: bool,
186 pub completeness_enabled: bool,
188 pub format_enabled: bool,
190 pub consistency_enabled: bool,
192 pub near_duplicate_threshold: f64,
194}
195
196impl Default for QualityConfig {
197 fn default() -> Self {
198 Self {
199 uniqueness_enabled: true,
200 completeness_enabled: true,
201 format_enabled: true,
202 consistency_enabled: true,
203 near_duplicate_threshold: 0.95,
204 }
205 }
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct MlConfig {
211 pub features_enabled: bool,
213 pub labels_enabled: bool,
215 pub splits_enabled: bool,
217 pub graph_enabled: bool,
219}
220
221impl Default for MlConfig {
222 fn default() -> Self {
223 Self {
224 features_enabled: true,
225 labels_enabled: true,
226 splits_enabled: true,
227 graph_enabled: true,
228 }
229 }
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct ReportConfig {
235 pub html_enabled: bool,
237 pub json_enabled: bool,
239 pub charts_enabled: bool,
241 pub baseline_path: Option<String>,
243}
244
245impl Default for ReportConfig {
246 fn default() -> Self {
247 Self {
248 html_enabled: true,
249 json_enabled: true,
250 charts_enabled: true,
251 baseline_path: None,
252 }
253 }
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct EvaluationThresholds {
259 pub benford_p_value_min: f64,
262 pub benford_mad_max: f64,
264 pub amount_ks_p_value_min: f64,
266 pub temporal_correlation_min: f64,
268
269 pub drift_magnitude_min: f64,
272 pub drift_hellinger_max: f64,
274 pub drift_psi_max: f64,
276 pub drift_f1_score_min: f64,
278
279 pub balance_tolerance: Decimal,
282 pub subledger_reconciliation_rate_min: f64,
284 pub document_chain_completion_min: f64,
286 pub ic_match_rate_min: f64,
288 pub referential_integrity_min: f64,
290
291 pub duplicate_rate_max: f64,
294 pub completeness_rate_min: f64,
296 pub format_consistency_min: f64,
298
299 pub anomaly_rate_min: f64,
302 pub anomaly_rate_max: f64,
304 pub label_coverage_min: f64,
306 pub train_ratio_min: f64,
308 pub graph_connectivity_min: f64,
310}
311
312impl Default for EvaluationThresholds {
313 fn default() -> Self {
314 Self {
315 benford_p_value_min: 0.05,
317 benford_mad_max: 0.015,
318 amount_ks_p_value_min: 0.05,
319 temporal_correlation_min: 0.80,
320
321 drift_magnitude_min: 0.05,
323 drift_hellinger_max: 0.30,
324 drift_psi_max: 0.25,
325 drift_f1_score_min: 0.50,
326
327 balance_tolerance: Decimal::new(1, 2), subledger_reconciliation_rate_min: 0.99,
330 document_chain_completion_min: 0.90,
331 ic_match_rate_min: 0.95,
332 referential_integrity_min: 0.99,
333
334 duplicate_rate_max: 0.01,
336 completeness_rate_min: 0.95,
337 format_consistency_min: 0.99,
338
339 anomaly_rate_min: 0.01,
341 anomaly_rate_max: 0.20,
342 label_coverage_min: 0.99,
343 train_ratio_min: 0.60,
344 graph_connectivity_min: 0.95,
345 }
346 }
347}
348
349impl EvaluationThresholds {
350 pub fn strict() -> Self {
352 Self {
353 benford_p_value_min: 0.10,
354 benford_mad_max: 0.010,
355 amount_ks_p_value_min: 0.10,
356 temporal_correlation_min: 0.90,
357 drift_magnitude_min: 0.03,
358 drift_hellinger_max: 0.20,
359 drift_psi_max: 0.15,
360 drift_f1_score_min: 0.70,
361 balance_tolerance: Decimal::new(1, 4), subledger_reconciliation_rate_min: 0.999,
363 document_chain_completion_min: 0.95,
364 ic_match_rate_min: 0.99,
365 referential_integrity_min: 0.999,
366 duplicate_rate_max: 0.001,
367 completeness_rate_min: 0.99,
368 format_consistency_min: 0.999,
369 anomaly_rate_min: 0.01,
370 anomaly_rate_max: 0.10,
371 label_coverage_min: 0.999,
372 train_ratio_min: 0.70,
373 graph_connectivity_min: 0.99,
374 }
375 }
376
377 pub fn lenient() -> Self {
379 Self {
380 benford_p_value_min: 0.01,
381 benford_mad_max: 0.025,
382 amount_ks_p_value_min: 0.01,
383 temporal_correlation_min: 0.60,
384 drift_magnitude_min: 0.10,
385 drift_hellinger_max: 0.50,
386 drift_psi_max: 0.40,
387 drift_f1_score_min: 0.30,
388 balance_tolerance: Decimal::new(1, 1), subledger_reconciliation_rate_min: 0.90,
390 document_chain_completion_min: 0.80,
391 ic_match_rate_min: 0.85,
392 referential_integrity_min: 0.95,
393 duplicate_rate_max: 0.05,
394 completeness_rate_min: 0.90,
395 format_consistency_min: 0.95,
396 anomaly_rate_min: 0.005,
397 anomaly_rate_max: 0.30,
398 label_coverage_min: 0.95,
399 train_ratio_min: 0.50,
400 graph_connectivity_min: 0.90,
401 }
402 }
403}