Skip to main content

datasynth_eval/
config.rs

1//! Configuration for the evaluation framework.
2
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6/// Main configuration for running an evaluation.
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct EvaluationConfig {
9    /// Statistical evaluation settings.
10    pub statistical: StatisticalConfig,
11    /// Coherence evaluation settings.
12    pub coherence: CoherenceConfig,
13    /// Data quality evaluation settings.
14    pub quality: QualityConfig,
15    /// ML-readiness evaluation settings.
16    pub ml: MlConfig,
17    /// Privacy evaluation settings.
18    #[serde(default)]
19    pub privacy: PrivacyEvaluationConfig,
20    /// Report generation settings.
21    pub report: ReportConfig,
22    /// Pass/fail thresholds.
23    pub thresholds: EvaluationThresholds,
24    /// Quality gate configuration.
25    #[serde(default)]
26    pub quality_gates: QualityGateConfig,
27}
28
29/// Configuration for quality gates.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct QualityGateConfig {
32    /// Whether quality gate evaluation is enabled.
33    #[serde(default)]
34    pub enabled: bool,
35    /// Profile name: "strict", "default", "lenient", or "custom".
36    #[serde(default = "default_gate_profile")]
37    pub profile: String,
38    /// Custom gate definitions (used when profile = "custom").
39    #[serde(default)]
40    pub custom_gates: Vec<CustomGateConfig>,
41    /// Whether to fail the generation run on gate violations.
42    #[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/// Configuration for a custom quality gate.
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct CustomGateConfig {
64    /// Gate name.
65    pub name: String,
66    /// Metric to check (e.g., "benford_mad", "completion_rate", "duplicate_rate").
67    pub metric: String,
68    /// Threshold value.
69    pub threshold: f64,
70    /// Upper threshold for "between" comparison.
71    #[serde(default)]
72    pub upper_threshold: Option<f64>,
73    /// Comparison: "gte", "lte", "eq", "between".
74    #[serde(default = "default_comparison")]
75    pub comparison: String,
76}
77
78fn default_comparison() -> String {
79    "gte".to_string()
80}
81
82/// Privacy evaluation configuration.
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct PrivacyEvaluationConfig {
85    /// Enable membership inference attack testing.
86    pub mia_enabled: bool,
87    /// Enable linkage attack assessment.
88    pub linkage_enabled: bool,
89    /// Enable NIST SP 800-226 alignment report.
90    pub nist_alignment_enabled: bool,
91    /// Enable SynQP quality-privacy matrix.
92    pub synqp_enabled: bool,
93    /// Maximum AUC-ROC threshold for MIA (default: 0.6).
94    pub mia_auc_threshold: f64,
95    /// Maximum re-identification rate for linkage (default: 0.05).
96    pub max_reidentification_rate: f64,
97    /// Minimum k-anonymity for linkage (default: 5).
98    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/// Statistical evaluation configuration.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct StatisticalConfig {
118    /// Enable Benford's Law analysis.
119    pub benford_enabled: bool,
120    /// Enable amount distribution analysis.
121    pub amount_distribution_enabled: bool,
122    /// Enable line item distribution analysis.
123    pub line_item_enabled: bool,
124    /// Enable temporal pattern analysis.
125    pub temporal_enabled: bool,
126    /// Enable drift detection analysis.
127    pub drift_detection_enabled: bool,
128    /// Significance level for statistical tests (default: 0.05).
129    pub significance_level: f64,
130    /// Minimum sample size for statistical tests.
131    pub min_sample_size: usize,
132    /// Window size for drift detection rolling statistics.
133    pub drift_window_size: usize,
134    /// Enable anomaly realism evaluation.
135    #[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/// Coherence evaluation configuration.
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct CoherenceConfig {
158    /// Enable balance sheet validation.
159    pub balance_enabled: bool,
160    /// Enable subledger reconciliation.
161    pub subledger_enabled: bool,
162    /// Enable document chain validation.
163    pub document_chain_enabled: bool,
164    /// Enable intercompany matching validation.
165    pub intercompany_enabled: bool,
166    /// Enable referential integrity validation.
167    pub referential_enabled: bool,
168    /// Tolerance for balance differences.
169    pub balance_tolerance: Decimal,
170    /// Enable financial reporting evaluation.
171    #[serde(default)]
172    pub financial_reporting_enabled: bool,
173    /// Enable HR/payroll evaluation.
174    #[serde(default)]
175    pub hr_payroll_enabled: bool,
176    /// Enable manufacturing evaluation.
177    #[serde(default)]
178    pub manufacturing_enabled: bool,
179    /// Enable bank reconciliation evaluation.
180    #[serde(default)]
181    pub bank_reconciliation_enabled: bool,
182    /// Enable sourcing (S2C) evaluation.
183    #[serde(default)]
184    pub sourcing_enabled: bool,
185    /// Enable cross-process link evaluation.
186    #[serde(default)]
187    pub cross_process_enabled: bool,
188    /// Enable audit evaluation.
189    #[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), // 0.01
202            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/// Data quality evaluation configuration.
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct QualityConfig {
216    /// Enable uniqueness validation.
217    pub uniqueness_enabled: bool,
218    /// Enable completeness validation.
219    pub completeness_enabled: bool,
220    /// Enable format consistency validation.
221    pub format_enabled: bool,
222    /// Enable cross-field consistency validation.
223    pub consistency_enabled: bool,
224    /// Similarity threshold for near-duplicate detection (0.0-1.0).
225    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/// ML-readiness evaluation configuration.
241#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct MlConfig {
243    /// Enable feature distribution analysis.
244    pub features_enabled: bool,
245    /// Enable label quality analysis.
246    pub labels_enabled: bool,
247    /// Enable train/test split validation.
248    pub splits_enabled: bool,
249    /// Enable graph structure analysis.
250    pub graph_enabled: bool,
251    /// Enable anomaly scoring analysis.
252    #[serde(default)]
253    pub anomaly_scoring_enabled: bool,
254    /// Enable feature quality analysis.
255    #[serde(default)]
256    pub feature_quality_enabled: bool,
257    /// Enable GNN readiness analysis.
258    #[serde(default)]
259    pub gnn_readiness_enabled: bool,
260    /// Enable domain gap analysis.
261    #[serde(default)]
262    pub domain_gap_enabled: bool,
263    /// Enable temporal fidelity analysis.
264    #[serde(default)]
265    pub temporal_fidelity_enabled: bool,
266    /// Enable scheme detectability analysis.
267    #[serde(default)]
268    pub scheme_detectability_enabled: bool,
269    /// Enable cross-modal consistency analysis.
270    #[serde(default)]
271    pub cross_modal_enabled: bool,
272    /// Enable embedding readiness analysis.
273    #[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/// Report generation configuration.
297#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct ReportConfig {
299    /// Generate HTML report.
300    pub html_enabled: bool,
301    /// Generate JSON report.
302    pub json_enabled: bool,
303    /// Include charts in HTML report.
304    pub charts_enabled: bool,
305    /// Path to baseline report for comparison.
306    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/// Banking/KYC/AML evaluation configuration.
321#[derive(Debug, Clone, Default, Serialize, Deserialize)]
322pub struct BankingEvalConfig {
323    /// Enable KYC completeness evaluation.
324    #[serde(default)]
325    pub kyc_enabled: bool,
326    /// Enable AML detectability evaluation.
327    #[serde(default)]
328    pub aml_enabled: bool,
329}
330
331/// Process mining evaluation configuration.
332#[derive(Debug, Clone, Default, Serialize, Deserialize)]
333pub struct ProcessMiningEvalConfig {
334    /// Enable event sequence validation.
335    #[serde(default)]
336    pub event_sequence_enabled: bool,
337    /// Enable variant analysis.
338    #[serde(default)]
339    pub variant_analysis_enabled: bool,
340}
341
342/// Causal model evaluation configuration.
343#[derive(Debug, Clone, Default, Serialize, Deserialize)]
344pub struct CausalEvalConfig {
345    /// Enable causal model evaluation.
346    #[serde(default)]
347    pub enabled: bool,
348}
349
350/// LLM enrichment quality evaluation configuration.
351#[derive(Debug, Clone, Default, Serialize, Deserialize)]
352pub struct EnrichmentEvalConfig {
353    /// Enable enrichment quality evaluation.
354    #[serde(default)]
355    pub enabled: bool,
356}
357
358/// Pass/fail thresholds for evaluation metrics.
359#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct EvaluationThresholds {
361    // Statistical thresholds
362    /// Minimum p-value for Benford's Law chi-squared test.
363    pub benford_p_value_min: f64,
364    /// Maximum Mean Absolute Deviation for Benford's Law.
365    pub benford_mad_max: f64,
366    /// Minimum p-value for amount distribution KS test.
367    pub amount_ks_p_value_min: f64,
368    /// Minimum correlation for temporal patterns.
369    pub temporal_correlation_min: f64,
370
371    // Drift detection thresholds
372    /// Minimum drift magnitude to consider significant.
373    pub drift_magnitude_min: f64,
374    /// Maximum Hellinger distance threshold.
375    pub drift_hellinger_max: f64,
376    /// Maximum Population Stability Index (PSI) threshold.
377    pub drift_psi_max: f64,
378    /// Minimum F1 score for drift detection quality.
379    pub drift_f1_score_min: f64,
380
381    // Coherence thresholds
382    /// Maximum balance sheet imbalance.
383    pub balance_tolerance: Decimal,
384    /// Minimum subledger reconciliation rate.
385    pub subledger_reconciliation_rate_min: f64,
386    /// Minimum document chain completion rate.
387    pub document_chain_completion_min: f64,
388    /// Minimum intercompany match rate.
389    pub ic_match_rate_min: f64,
390    /// Minimum referential integrity rate.
391    pub referential_integrity_min: f64,
392
393    // Quality thresholds
394    /// Maximum duplicate rate.
395    pub duplicate_rate_max: f64,
396    /// Minimum completeness rate.
397    pub completeness_rate_min: f64,
398    /// Minimum format consistency rate.
399    pub format_consistency_min: f64,
400
401    // New evaluator thresholds
402    /// Minimum anomaly separability (AUC-ROC).
403    #[serde(default = "default_anomaly_separability")]
404    pub min_anomaly_separability: f64,
405    /// Minimum feature quality score.
406    #[serde(default = "default_feature_quality")]
407    pub min_feature_quality: f64,
408    /// Minimum GNN readiness score.
409    #[serde(default = "default_gnn_readiness")]
410    pub min_gnn_readiness: f64,
411    /// Maximum domain gap score.
412    #[serde(default = "default_domain_gap")]
413    pub max_domain_gap: f64,
414    /// Minimum temporal fidelity score.
415    #[serde(default = "default_temporal_fidelity")]
416    pub min_temporal_fidelity: f64,
417    /// Minimum scheme detectability score.
418    #[serde(default = "default_scheme_detectability")]
419    pub min_scheme_detectability: f64,
420    /// Minimum cross-modal consistency.
421    #[serde(default = "default_cross_modal")]
422    pub min_cross_modal_consistency: f64,
423    /// Minimum embedding readiness score.
424    #[serde(default = "default_embedding_readiness")]
425    pub min_embedding_readiness: f64,
426
427    // ML thresholds
428    /// Minimum anomaly rate.
429    pub anomaly_rate_min: f64,
430    /// Maximum anomaly rate.
431    pub anomaly_rate_max: f64,
432    /// Minimum label coverage.
433    pub label_coverage_min: f64,
434    /// Minimum train ratio.
435    pub train_ratio_min: f64,
436    /// Minimum graph connectivity.
437    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            // Statistical
469            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            // New evaluator thresholds
475            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 detection
485            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            // Coherence
491            balance_tolerance: Decimal::new(1, 2), // 0.01
492            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            // Quality
498            duplicate_rate_max: 0.01,
499            completeness_rate_min: 0.95,
500            format_consistency_min: 0.99,
501
502            // ML
503            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    /// Create strict thresholds for rigorous validation.
514    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), // 0.0001
533            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    /// Create lenient thresholds for exploratory validation.
549    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), // 0.1
568            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}