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 #[serde(default)]
136 pub anomaly_realism_enabled: bool,
137}
138
139impl Default for StatisticalConfig {
140 fn default() -> Self {
141 Self {
142 benford_enabled: true,
143 amount_distribution_enabled: true,
144 line_item_enabled: true,
145 temporal_enabled: true,
146 drift_detection_enabled: true,
147 significance_level: 0.05,
148 min_sample_size: 100,
149 drift_window_size: 10,
150 anomaly_realism_enabled: false,
151 }
152 }
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct CoherenceConfig {
158 pub balance_enabled: bool,
160 pub subledger_enabled: bool,
162 pub document_chain_enabled: bool,
164 pub intercompany_enabled: bool,
166 pub referential_enabled: bool,
168 pub balance_tolerance: Decimal,
170 #[serde(default)]
172 pub financial_reporting_enabled: bool,
173 #[serde(default)]
175 pub hr_payroll_enabled: bool,
176 #[serde(default)]
178 pub manufacturing_enabled: bool,
179 #[serde(default)]
181 pub bank_reconciliation_enabled: bool,
182 #[serde(default)]
184 pub sourcing_enabled: bool,
185 #[serde(default)]
187 pub cross_process_enabled: bool,
188 #[serde(default)]
190 pub audit_enabled: bool,
191}
192
193impl Default for CoherenceConfig {
194 fn default() -> Self {
195 Self {
196 balance_enabled: true,
197 subledger_enabled: true,
198 document_chain_enabled: true,
199 intercompany_enabled: true,
200 referential_enabled: true,
201 balance_tolerance: Decimal::new(1, 2), financial_reporting_enabled: false,
203 hr_payroll_enabled: false,
204 manufacturing_enabled: false,
205 bank_reconciliation_enabled: false,
206 sourcing_enabled: false,
207 cross_process_enabled: false,
208 audit_enabled: false,
209 }
210 }
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct QualityConfig {
216 pub uniqueness_enabled: bool,
218 pub completeness_enabled: bool,
220 pub format_enabled: bool,
222 pub consistency_enabled: bool,
224 pub near_duplicate_threshold: f64,
226}
227
228impl Default for QualityConfig {
229 fn default() -> Self {
230 Self {
231 uniqueness_enabled: true,
232 completeness_enabled: true,
233 format_enabled: true,
234 consistency_enabled: true,
235 near_duplicate_threshold: 0.95,
236 }
237 }
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct MlConfig {
243 pub features_enabled: bool,
245 pub labels_enabled: bool,
247 pub splits_enabled: bool,
249 pub graph_enabled: bool,
251 #[serde(default)]
253 pub anomaly_scoring_enabled: bool,
254 #[serde(default)]
256 pub feature_quality_enabled: bool,
257 #[serde(default)]
259 pub gnn_readiness_enabled: bool,
260 #[serde(default)]
262 pub domain_gap_enabled: bool,
263 #[serde(default)]
265 pub temporal_fidelity_enabled: bool,
266 #[serde(default)]
268 pub scheme_detectability_enabled: bool,
269 #[serde(default)]
271 pub cross_modal_enabled: bool,
272 #[serde(default)]
274 pub embedding_readiness_enabled: bool,
275}
276
277impl Default for MlConfig {
278 fn default() -> Self {
279 Self {
280 features_enabled: true,
281 labels_enabled: true,
282 splits_enabled: true,
283 graph_enabled: true,
284 anomaly_scoring_enabled: false,
285 feature_quality_enabled: false,
286 gnn_readiness_enabled: false,
287 domain_gap_enabled: false,
288 temporal_fidelity_enabled: false,
289 scheme_detectability_enabled: false,
290 cross_modal_enabled: false,
291 embedding_readiness_enabled: false,
292 }
293 }
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct ReportConfig {
299 pub html_enabled: bool,
301 pub json_enabled: bool,
303 pub charts_enabled: bool,
305 pub baseline_path: Option<String>,
307}
308
309impl Default for ReportConfig {
310 fn default() -> Self {
311 Self {
312 html_enabled: true,
313 json_enabled: true,
314 charts_enabled: true,
315 baseline_path: None,
316 }
317 }
318}
319
320#[derive(Debug, Clone, Default, Serialize, Deserialize)]
322pub struct BankingEvalConfig {
323 #[serde(default)]
325 pub kyc_enabled: bool,
326 #[serde(default)]
328 pub aml_enabled: bool,
329}
330
331#[derive(Debug, Clone, Default, Serialize, Deserialize)]
333pub struct ProcessMiningEvalConfig {
334 #[serde(default)]
336 pub event_sequence_enabled: bool,
337 #[serde(default)]
339 pub variant_analysis_enabled: bool,
340}
341
342#[derive(Debug, Clone, Default, Serialize, Deserialize)]
344pub struct CausalEvalConfig {
345 #[serde(default)]
347 pub enabled: bool,
348}
349
350#[derive(Debug, Clone, Default, Serialize, Deserialize)]
352pub struct EnrichmentEvalConfig {
353 #[serde(default)]
355 pub enabled: bool,
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct EvaluationThresholds {
361 pub benford_p_value_min: f64,
364 pub benford_mad_max: f64,
366 pub amount_ks_p_value_min: f64,
368 pub temporal_correlation_min: f64,
370
371 pub drift_magnitude_min: f64,
374 pub drift_hellinger_max: f64,
376 pub drift_psi_max: f64,
378 pub drift_f1_score_min: f64,
380
381 pub balance_tolerance: Decimal,
384 pub subledger_reconciliation_rate_min: f64,
386 pub document_chain_completion_min: f64,
388 pub ic_match_rate_min: f64,
390 pub referential_integrity_min: f64,
392
393 pub duplicate_rate_max: f64,
396 pub completeness_rate_min: f64,
398 pub format_consistency_min: f64,
400
401 #[serde(default = "default_anomaly_separability")]
404 pub min_anomaly_separability: f64,
405 #[serde(default = "default_feature_quality")]
407 pub min_feature_quality: f64,
408 #[serde(default = "default_gnn_readiness")]
410 pub min_gnn_readiness: f64,
411 #[serde(default = "default_domain_gap")]
413 pub max_domain_gap: f64,
414 #[serde(default = "default_temporal_fidelity")]
416 pub min_temporal_fidelity: f64,
417 #[serde(default = "default_scheme_detectability")]
419 pub min_scheme_detectability: f64,
420 #[serde(default = "default_cross_modal")]
422 pub min_cross_modal_consistency: f64,
423 #[serde(default = "default_embedding_readiness")]
425 pub min_embedding_readiness: f64,
426
427 pub anomaly_rate_min: f64,
430 pub anomaly_rate_max: f64,
432 pub label_coverage_min: f64,
434 pub train_ratio_min: f64,
436 pub graph_connectivity_min: f64,
438}
439
440fn default_anomaly_separability() -> f64 {
441 0.70
442}
443fn default_feature_quality() -> f64 {
444 0.60
445}
446fn default_gnn_readiness() -> f64 {
447 0.65
448}
449fn default_domain_gap() -> f64 {
450 0.25
451}
452fn default_temporal_fidelity() -> f64 {
453 0.70
454}
455fn default_scheme_detectability() -> f64 {
456 0.60
457}
458fn default_cross_modal() -> f64 {
459 0.60
460}
461fn default_embedding_readiness() -> f64 {
462 0.50
463}
464
465impl Default for EvaluationThresholds {
466 fn default() -> Self {
467 Self {
468 benford_p_value_min: 0.05,
470 benford_mad_max: 0.015,
471 amount_ks_p_value_min: 0.05,
472 temporal_correlation_min: 0.80,
473
474 min_anomaly_separability: 0.70,
476 min_feature_quality: 0.60,
477 min_gnn_readiness: 0.65,
478 max_domain_gap: 0.25,
479 min_temporal_fidelity: 0.70,
480 min_scheme_detectability: 0.60,
481 min_cross_modal_consistency: 0.60,
482 min_embedding_readiness: 0.50,
483
484 drift_magnitude_min: 0.05,
486 drift_hellinger_max: 0.30,
487 drift_psi_max: 0.25,
488 drift_f1_score_min: 0.50,
489
490 balance_tolerance: Decimal::new(1, 2), subledger_reconciliation_rate_min: 0.99,
493 document_chain_completion_min: 0.90,
494 ic_match_rate_min: 0.95,
495 referential_integrity_min: 0.99,
496
497 duplicate_rate_max: 0.01,
499 completeness_rate_min: 0.95,
500 format_consistency_min: 0.99,
501
502 anomaly_rate_min: 0.01,
504 anomaly_rate_max: 0.20,
505 label_coverage_min: 0.99,
506 train_ratio_min: 0.60,
507 graph_connectivity_min: 0.95,
508 }
509 }
510}
511
512impl EvaluationThresholds {
513 pub fn strict() -> Self {
515 Self {
516 min_anomaly_separability: 0.80,
517 min_feature_quality: 0.70,
518 min_gnn_readiness: 0.75,
519 max_domain_gap: 0.15,
520 min_temporal_fidelity: 0.80,
521 min_scheme_detectability: 0.70,
522 min_cross_modal_consistency: 0.70,
523 min_embedding_readiness: 0.60,
524 benford_p_value_min: 0.10,
525 benford_mad_max: 0.010,
526 amount_ks_p_value_min: 0.10,
527 temporal_correlation_min: 0.90,
528 drift_magnitude_min: 0.03,
529 drift_hellinger_max: 0.20,
530 drift_psi_max: 0.15,
531 drift_f1_score_min: 0.70,
532 balance_tolerance: Decimal::new(1, 4), subledger_reconciliation_rate_min: 0.999,
534 document_chain_completion_min: 0.95,
535 ic_match_rate_min: 0.99,
536 referential_integrity_min: 0.999,
537 duplicate_rate_max: 0.001,
538 completeness_rate_min: 0.99,
539 format_consistency_min: 0.999,
540 anomaly_rate_min: 0.01,
541 anomaly_rate_max: 0.10,
542 label_coverage_min: 0.999,
543 train_ratio_min: 0.70,
544 graph_connectivity_min: 0.99,
545 }
546 }
547
548 pub fn lenient() -> Self {
550 Self {
551 min_anomaly_separability: 0.55,
552 min_feature_quality: 0.45,
553 min_gnn_readiness: 0.50,
554 max_domain_gap: 0.40,
555 min_temporal_fidelity: 0.55,
556 min_scheme_detectability: 0.45,
557 min_cross_modal_consistency: 0.45,
558 min_embedding_readiness: 0.35,
559 benford_p_value_min: 0.01,
560 benford_mad_max: 0.025,
561 amount_ks_p_value_min: 0.01,
562 temporal_correlation_min: 0.60,
563 drift_magnitude_min: 0.10,
564 drift_hellinger_max: 0.50,
565 drift_psi_max: 0.40,
566 drift_f1_score_min: 0.30,
567 balance_tolerance: Decimal::new(1, 1), subledger_reconciliation_rate_min: 0.90,
569 document_chain_completion_min: 0.80,
570 ic_match_rate_min: 0.85,
571 referential_integrity_min: 0.95,
572 duplicate_rate_max: 0.05,
573 completeness_rate_min: 0.90,
574 format_consistency_min: 0.95,
575 anomaly_rate_min: 0.005,
576 anomaly_rate_max: 0.30,
577 label_coverage_min: 0.95,
578 train_ratio_min: 0.50,
579 graph_connectivity_min: 0.90,
580 }
581 }
582}