Skip to main content

datasynth_eval/banking/
mod.rs

1//! Banking/KYC/AML evaluation module.
2//!
3//! Validates banking data including KYC profile completeness
4//! and AML typology coherence and detectability.
5
6pub mod account_lifecycle;
7pub mod aml_detectability;
8pub mod cross_layer_coherence;
9pub mod device_fingerprint;
10pub mod false_positive_quality;
11pub mod kyc_completeness;
12pub mod network_structure;
13pub mod sanctions_screening;
14pub mod sophistication_distribution;
15pub mod velocity_quality;
16
17pub use account_lifecycle::{
18    LifecycleAnalysis, LifecycleAnalyzer, LifecycleEndState, LifecycleThresholds, TransitionRecord,
19};
20pub use aml_detectability::{
21    AmlDetectabilityAnalysis, AmlDetectabilityAnalyzer, AmlTransactionData, TypologyData,
22};
23pub use cross_layer_coherence::{
24    BankTxnLinks, CrossLayerCoherenceAnalysis, CrossLayerCoherenceAnalyzer, CrossLayerThresholds,
25    PaymentRef,
26};
27pub use device_fingerprint::{
28    DeviceFingerprintAnalysis, DeviceFingerprintAnalyzer, DeviceFingerprintThresholds,
29    DeviceObservation,
30};
31pub use false_positive_quality::{
32    FalsePositiveAnalysis, FalsePositiveAnalyzer, FalsePositiveThresholds, LabelData,
33};
34pub use kyc_completeness::{KycCompletenessAnalysis, KycCompletenessAnalyzer, KycProfileData};
35pub use network_structure::{
36    NetworkNodeObservation, NetworkStructureAnalysis, NetworkStructureAnalyzer,
37    NetworkStructureThresholds,
38};
39pub use sanctions_screening::{
40    SanctionsScreeningAnalysis, SanctionsScreeningAnalyzer, SanctionsScreeningThresholds,
41    ScreeningObservation,
42};
43pub use sophistication_distribution::{
44    SophisticationAnalysis, SophisticationAnalyzer, SophisticationObservation,
45    SophisticationThresholds,
46};
47pub use velocity_quality::{
48    VelocityFeaturesData, VelocityQualityAnalysis, VelocityQualityAnalyzer,
49    VelocityQualityThresholds,
50};
51
52use serde::{Deserialize, Serialize};
53
54/// Combined banking evaluation results.
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct BankingEvaluation {
57    /// KYC completeness analysis.
58    pub kyc: Option<KycCompletenessAnalysis>,
59    /// AML detectability analysis.
60    pub aml: Option<AmlDetectabilityAnalysis>,
61    /// Cross-layer coherence analysis (payment↔bank txn).
62    #[serde(default)]
63    pub cross_layer: Option<CrossLayerCoherenceAnalysis>,
64    /// Velocity feature quality analysis.
65    #[serde(default)]
66    pub velocity: Option<VelocityQualityAnalysis>,
67    /// False positive quality analysis.
68    #[serde(default)]
69    pub false_positive: Option<FalsePositiveAnalysis>,
70    /// Overall pass/fail.
71    pub passes: bool,
72    /// Issues found.
73    pub issues: Vec<String>,
74}
75
76impl BankingEvaluation {
77    /// Create a new empty evaluation.
78    pub fn new() -> Self {
79        Self {
80            kyc: None,
81            aml: None,
82            cross_layer: None,
83            velocity: None,
84            false_positive: None,
85            passes: true,
86            issues: Vec::new(),
87        }
88    }
89
90    /// Check thresholds and update pass status.
91    pub fn check_thresholds(&mut self) {
92        self.issues.clear();
93        if let Some(ref kyc) = self.kyc {
94            if !kyc.passes {
95                self.issues.extend(kyc.issues.clone());
96            }
97        }
98        if let Some(ref aml) = self.aml {
99            if !aml.passes {
100                self.issues.extend(aml.issues.clone());
101            }
102        }
103        if let Some(ref cl) = self.cross_layer {
104            if !cl.passes {
105                self.issues.extend(cl.issues.clone());
106            }
107        }
108        if let Some(ref v) = self.velocity {
109            if !v.passes {
110                self.issues.extend(v.issues.clone());
111            }
112        }
113        if let Some(ref fp) = self.false_positive {
114            if !fp.passes {
115                self.issues.extend(fp.issues.clone());
116            }
117        }
118        self.passes = self.issues.is_empty();
119    }
120}
121
122impl Default for BankingEvaluation {
123    fn default() -> Self {
124        Self::new()
125    }
126}