Skip to main content

rustkernel_core/
domain.rs

1//! Domain definitions for kernel categorization.
2//!
3//! Kernels are organized into domains representing different business/analytical areas.
4//! Domains are used for:
5//! - License enforcement (licensing per domain)
6//! - Kernel discovery and organization
7//! - Feature gating
8
9use serde::{Deserialize, Serialize};
10use std::fmt;
11
12/// Business/analytical domain for kernel categorization.
13///
14/// Each domain represents a distinct area of functionality:
15/// - Financial services (banking, compliance, risk, treasury)
16/// - Analytics (graph, ML, temporal, behavioral)
17/// - Operations (clearing, payments, order matching)
18#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
19#[non_exhaustive]
20pub enum Domain {
21    /// Graph analytics: centrality, community detection, motifs, similarity
22    GraphAnalytics,
23
24    /// Statistical machine learning: clustering, anomaly detection, regression
25    StatisticalML,
26
27    /// Compliance: AML, KYC, sanctions screening, transaction monitoring
28    Compliance,
29
30    /// Temporal analysis: forecasting, change detection, decomposition
31    TemporalAnalysis,
32
33    /// Risk analytics: credit risk, VaR, portfolio risk, stress testing
34    RiskAnalytics,
35
36    /// Banking: fraud detection and pattern matching
37    Banking,
38
39    /// Behavioral analytics: profiling, forensics, event correlation
40    BehavioralAnalytics,
41
42    /// Order matching: high-frequency order book matching
43    OrderMatching,
44
45    /// Process intelligence: process mining, conformance checking
46    ProcessIntelligence,
47
48    /// Clearing: settlement, netting, DVP matching
49    Clearing,
50
51    /// Treasury management: cash flow, collateral, hedging, liquidity
52    TreasuryManagement,
53
54    /// Accounting: chart of accounts, journal transformation, reconciliation
55    Accounting,
56
57    /// Payment processing: transaction execution, flow analysis
58    PaymentProcessing,
59
60    /// Financial audit: feature extraction, hypergraph construction
61    FinancialAudit,
62
63    /// Core: test kernels and infrastructure validation
64    #[default]
65    Core,
66}
67
68impl Domain {
69    /// All available domains.
70    pub const ALL: &'static [Domain] = &[
71        Domain::GraphAnalytics,
72        Domain::StatisticalML,
73        Domain::Compliance,
74        Domain::TemporalAnalysis,
75        Domain::RiskAnalytics,
76        Domain::Banking,
77        Domain::BehavioralAnalytics,
78        Domain::OrderMatching,
79        Domain::ProcessIntelligence,
80        Domain::Clearing,
81        Domain::TreasuryManagement,
82        Domain::Accounting,
83        Domain::PaymentProcessing,
84        Domain::FinancialAudit,
85        Domain::Core,
86    ];
87
88    /// Priority 1 domains (high-value, implement first).
89    pub const P1: &'static [Domain] = &[
90        Domain::GraphAnalytics,
91        Domain::StatisticalML,
92        Domain::Compliance,
93        Domain::TemporalAnalysis,
94        Domain::RiskAnalytics,
95    ];
96
97    /// Priority 2 domains (medium priority).
98    pub const P2: &'static [Domain] = &[
99        Domain::Banking,
100        Domain::BehavioralAnalytics,
101        Domain::OrderMatching,
102        Domain::ProcessIntelligence,
103        Domain::Clearing,
104    ];
105
106    /// Priority 3 domains (lower priority).
107    pub const P3: &'static [Domain] = &[
108        Domain::TreasuryManagement,
109        Domain::Accounting,
110        Domain::PaymentProcessing,
111        Domain::FinancialAudit,
112    ];
113
114    /// Returns the domain name as a string slice.
115    #[must_use]
116    pub const fn as_str(&self) -> &'static str {
117        match self {
118            Domain::GraphAnalytics => "GraphAnalytics",
119            Domain::StatisticalML => "StatisticalML",
120            Domain::Compliance => "Compliance",
121            Domain::TemporalAnalysis => "TemporalAnalysis",
122            Domain::RiskAnalytics => "RiskAnalytics",
123            Domain::Banking => "Banking",
124            Domain::BehavioralAnalytics => "BehavioralAnalytics",
125            Domain::OrderMatching => "OrderMatching",
126            Domain::ProcessIntelligence => "ProcessIntelligence",
127            Domain::Clearing => "Clearing",
128            Domain::TreasuryManagement => "TreasuryManagement",
129            Domain::Accounting => "Accounting",
130            Domain::PaymentProcessing => "PaymentProcessing",
131            Domain::FinancialAudit => "FinancialAudit",
132            Domain::Core => "Core",
133        }
134    }
135
136    /// Parse a domain from a string.
137    #[must_use]
138    pub fn parse(s: &str) -> Option<Self> {
139        match s {
140            "GraphAnalytics" => Some(Domain::GraphAnalytics),
141            "StatisticalML" => Some(Domain::StatisticalML),
142            "Compliance" => Some(Domain::Compliance),
143            "TemporalAnalysis" => Some(Domain::TemporalAnalysis),
144            "RiskAnalytics" => Some(Domain::RiskAnalytics),
145            "Banking" => Some(Domain::Banking),
146            "BehavioralAnalytics" => Some(Domain::BehavioralAnalytics),
147            "OrderMatching" => Some(Domain::OrderMatching),
148            "ProcessIntelligence" => Some(Domain::ProcessIntelligence),
149            "Clearing" => Some(Domain::Clearing),
150            "TreasuryManagement" => Some(Domain::TreasuryManagement),
151            "Accounting" => Some(Domain::Accounting),
152            "PaymentProcessing" => Some(Domain::PaymentProcessing),
153            "FinancialAudit" => Some(Domain::FinancialAudit),
154            "Core" => Some(Domain::Core),
155            _ => None,
156        }
157    }
158
159    /// Returns true if this is a P1 (high priority) domain.
160    #[must_use]
161    pub const fn is_p1(&self) -> bool {
162        matches!(
163            self,
164            Domain::GraphAnalytics
165                | Domain::StatisticalML
166                | Domain::Compliance
167                | Domain::TemporalAnalysis
168                | Domain::RiskAnalytics
169        )
170    }
171
172    /// Convert to the corresponding `ringkernel_core::domain::Domain` variant.
173    ///
174    /// Mapping notes:
175    /// - `TemporalAnalysis` maps to `TimeSeries`
176    /// - `RiskAnalytics` maps to `RiskManagement`
177    /// - `Core` maps to `General`
178    /// - All other variants map by name.
179    #[must_use]
180    pub fn to_ring_domain(&self) -> ringkernel_core::domain::Domain {
181        ringkernel_core::domain::Domain::from(*self)
182    }
183
184    /// Construct a `Domain` from a `ringkernel_core::domain::Domain` variant.
185    ///
186    /// Mapping notes:
187    /// - `TimeSeries` maps to `TemporalAnalysis`
188    /// - `RiskManagement` maps to `RiskAnalytics`
189    /// - `General` maps to `Core`
190    /// - Variants without a direct counterpart (`MarketData`, `Settlement`,
191    ///   `NetworkAnalysis`, `FraudDetection`, `Simulation`, `Custom`) are
192    ///   mapped to the closest match or `Core`.
193    #[must_use]
194    pub fn from_ring_domain(ring: ringkernel_core::domain::Domain) -> Self {
195        Domain::from(ring)
196    }
197}
198
199impl fmt::Display for Domain {
200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201        write!(f, "{}", self.as_str())
202    }
203}
204
205// ---------------------------------------------------------------------------
206// Bidirectional conversion: Domain <-> ringkernel_core::domain::Domain (0.4.2)
207// ---------------------------------------------------------------------------
208
209impl From<Domain> for ringkernel_core::domain::Domain {
210    fn from(d: Domain) -> Self {
211        use ringkernel_core::domain::Domain as RD;
212        match d {
213            Domain::GraphAnalytics => RD::GraphAnalytics,
214            Domain::StatisticalML => RD::StatisticalML,
215            Domain::Compliance => RD::Compliance,
216            Domain::TemporalAnalysis => RD::TimeSeries,
217            Domain::RiskAnalytics => RD::RiskManagement,
218            Domain::Banking => RD::Banking,
219            Domain::BehavioralAnalytics => RD::BehavioralAnalytics,
220            Domain::OrderMatching => RD::OrderMatching,
221            Domain::ProcessIntelligence => RD::ProcessIntelligence,
222            Domain::Clearing => RD::Clearing,
223            Domain::TreasuryManagement => RD::TreasuryManagement,
224            Domain::Accounting => RD::Accounting,
225            Domain::PaymentProcessing => RD::PaymentProcessing,
226            Domain::FinancialAudit => RD::FinancialAudit,
227            Domain::Core => RD::General,
228        }
229    }
230}
231
232impl From<ringkernel_core::domain::Domain> for Domain {
233    fn from(rd: ringkernel_core::domain::Domain) -> Self {
234        use ringkernel_core::domain::Domain as RD;
235        match rd {
236            RD::General => Domain::Core,
237            RD::GraphAnalytics => Domain::GraphAnalytics,
238            RD::StatisticalML => Domain::StatisticalML,
239            RD::Compliance => Domain::Compliance,
240            RD::RiskManagement => Domain::RiskAnalytics,
241            RD::OrderMatching => Domain::OrderMatching,
242            RD::Accounting => Domain::Accounting,
243            RD::TimeSeries => Domain::TemporalAnalysis,
244            RD::Banking => Domain::Banking,
245            RD::BehavioralAnalytics => Domain::BehavioralAnalytics,
246            RD::ProcessIntelligence => Domain::ProcessIntelligence,
247            RD::Clearing => Domain::Clearing,
248            RD::TreasuryManagement => Domain::TreasuryManagement,
249            RD::PaymentProcessing => Domain::PaymentProcessing,
250            RD::FinancialAudit => Domain::FinancialAudit,
251            // Variants present in ringkernel_core but without a direct
252            // counterpart in this crate are mapped to the closest match.
253            RD::NetworkAnalysis => Domain::GraphAnalytics,
254            RD::FraudDetection => Domain::Banking,
255            RD::Settlement => Domain::Clearing,
256            RD::MarketData => Domain::Core,
257            RD::Simulation => Domain::Core,
258            RD::Custom => Domain::Core,
259            // Future-proofing: map unknown variants to Core.
260            _ => Domain::Core,
261        }
262    }
263}
264
265/// Feature strings for fine-grained licensing.
266///
267/// Format: `Domain.Feature` (e.g., `GraphAnalytics.PageRank`)
268pub mod features {
269    // GraphAnalytics domain
270    /// PageRank centrality calculation
271    pub const GRAPH_PAGERANK: &str = "GraphAnalytics.PageRank";
272    /// Betweenness centrality calculation
273    pub const GRAPH_BETWEENNESS: &str = "GraphAnalytics.BetweennessCentrality";
274    /// Closeness centrality calculation
275    pub const GRAPH_CLOSENESS: &str = "GraphAnalytics.ClosenessCentrality";
276    /// Degree centrality calculation
277    pub const GRAPH_DEGREE: &str = "GraphAnalytics.DegreeCentrality";
278    /// Eigenvector centrality calculation
279    pub const GRAPH_EIGENVECTOR: &str = "GraphAnalytics.EigenvectorCentrality";
280    /// Katz centrality calculation
281    pub const GRAPH_KATZ: &str = "GraphAnalytics.KatzCentrality";
282    /// Community detection algorithms
283    pub const GRAPH_COMMUNITY: &str = "GraphAnalytics.CommunityDetection";
284    /// Motif detection algorithms
285    pub const GRAPH_MOTIF: &str = "GraphAnalytics.MotifDetection";
286    /// Similarity metrics
287    pub const GRAPH_SIMILARITY: &str = "GraphAnalytics.Similarity";
288
289    // StatisticalML domain
290    /// K-Means clustering
291    pub const ML_KMEANS: &str = "StatisticalML.KMeans";
292    /// DBSCAN clustering
293    pub const ML_DBSCAN: &str = "StatisticalML.DBSCAN";
294    /// Isolation Forest anomaly detection
295    pub const ML_ISOLATION_FOREST: &str = "StatisticalML.IsolationForest";
296    /// Local Outlier Factor anomaly detection
297    pub const ML_LOF: &str = "StatisticalML.LocalOutlierFactor";
298    /// Ensemble methods
299    pub const ML_ENSEMBLE: &str = "StatisticalML.Ensemble";
300    /// Regression models
301    pub const ML_REGRESSION: &str = "StatisticalML.Regression";
302
303    // Compliance domain
304    /// Anti-Money Laundering pattern detection
305    pub const COMPLIANCE_AML: &str = "Compliance.AML";
306    /// Sanctions screening
307    pub const COMPLIANCE_SANCTIONS: &str = "Compliance.SanctionsScreening";
308    /// Know Your Customer scoring
309    pub const COMPLIANCE_KYC: &str = "Compliance.KYC";
310    /// Transaction monitoring
311    pub const COMPLIANCE_MONITORING: &str = "Compliance.TransactionMonitoring";
312
313    // RiskAnalytics domain
314    /// Credit risk scoring
315    pub const RISK_CREDIT: &str = "RiskAnalytics.CreditRisk";
316    /// Market risk / VaR
317    pub const RISK_MARKET: &str = "RiskAnalytics.MarketRisk";
318    /// Value at Risk calculation
319    pub const RISK_VAR: &str = "RiskAnalytics.VaR";
320    /// Portfolio risk aggregation
321    pub const RISK_PORTFOLIO: &str = "RiskAnalytics.PortfolioRisk";
322    /// Stress testing
323    pub const RISK_STRESS: &str = "RiskAnalytics.StressTesting";
324
325    // TemporalAnalysis domain
326    /// ARIMA forecasting
327    pub const TEMPORAL_ARIMA: &str = "TemporalAnalysis.ARIMA";
328    /// Prophet-style decomposition
329    pub const TEMPORAL_PROPHET: &str = "TemporalAnalysis.Prophet";
330    /// Change point detection
331    pub const TEMPORAL_CHANGEPOINT: &str = "TemporalAnalysis.ChangePoint";
332    /// Seasonal decomposition
333    pub const TEMPORAL_SEASONAL: &str = "TemporalAnalysis.Seasonal";
334    /// Volatility analysis
335    pub const TEMPORAL_VOLATILITY: &str = "TemporalAnalysis.Volatility";
336
337    // Banking domain
338    /// Fraud detection
339    pub const BANKING_FRAUD: &str = "Banking.FraudDetection";
340
341    // OrderMatching domain
342    /// Order book matching
343    pub const ORDERBOOK_MATCHING: &str = "OrderMatching.OrderMatching";
344
345    // ProcessIntelligence domain
346    /// Process mining
347    pub const PROCINT_MINING: &str = "ProcessIntelligence.ProcessMining";
348    /// Conformance checking
349    pub const PROCINT_CONFORMANCE: &str = "ProcessIntelligence.ConformanceChecking";
350}
351
352#[cfg(test)]
353mod tests {
354    use super::*;
355
356    #[test]
357    fn test_domain_all_count() {
358        assert_eq!(Domain::ALL.len(), 15);
359    }
360
361    #[test]
362    fn test_domain_priority_coverage() {
363        let p1_count = Domain::P1.len();
364        let p2_count = Domain::P2.len();
365        let p3_count = Domain::P3.len();
366        // Core is P0, not in P1/P2/P3
367        assert_eq!(p1_count + p2_count + p3_count + 1, Domain::ALL.len());
368    }
369
370    #[test]
371    fn test_domain_from_str() {
372        assert_eq!(
373            Domain::parse("GraphAnalytics"),
374            Some(Domain::GraphAnalytics)
375        );
376        assert_eq!(Domain::parse("Unknown"), None);
377    }
378
379    #[test]
380    fn test_domain_display() {
381        assert_eq!(Domain::GraphAnalytics.to_string(), "GraphAnalytics");
382        assert_eq!(Domain::RiskAnalytics.to_string(), "RiskAnalytics");
383    }
384
385    #[test]
386    fn test_domain_default() {
387        assert_eq!(Domain::default(), Domain::Core);
388    }
389
390    #[test]
391    fn test_to_ring_domain_renamed_variants() {
392        use ringkernel_core::domain::Domain as RD;
393
394        assert_eq!(Domain::TemporalAnalysis.to_ring_domain(), RD::TimeSeries);
395        assert_eq!(Domain::RiskAnalytics.to_ring_domain(), RD::RiskManagement);
396        assert_eq!(Domain::Core.to_ring_domain(), RD::General);
397    }
398
399    #[test]
400    fn test_to_ring_domain_identity_variants() {
401        use ringkernel_core::domain::Domain as RD;
402
403        assert_eq!(Domain::GraphAnalytics.to_ring_domain(), RD::GraphAnalytics);
404        assert_eq!(Domain::StatisticalML.to_ring_domain(), RD::StatisticalML);
405        assert_eq!(Domain::Compliance.to_ring_domain(), RD::Compliance);
406        assert_eq!(Domain::Banking.to_ring_domain(), RD::Banking);
407        assert_eq!(
408            Domain::BehavioralAnalytics.to_ring_domain(),
409            RD::BehavioralAnalytics
410        );
411        assert_eq!(Domain::OrderMatching.to_ring_domain(), RD::OrderMatching);
412        assert_eq!(
413            Domain::ProcessIntelligence.to_ring_domain(),
414            RD::ProcessIntelligence
415        );
416        assert_eq!(Domain::Clearing.to_ring_domain(), RD::Clearing);
417        assert_eq!(
418            Domain::TreasuryManagement.to_ring_domain(),
419            RD::TreasuryManagement
420        );
421        assert_eq!(Domain::Accounting.to_ring_domain(), RD::Accounting);
422        assert_eq!(
423            Domain::PaymentProcessing.to_ring_domain(),
424            RD::PaymentProcessing
425        );
426        assert_eq!(Domain::FinancialAudit.to_ring_domain(), RD::FinancialAudit);
427    }
428
429    #[test]
430    fn test_from_ring_domain_renamed_variants() {
431        use ringkernel_core::domain::Domain as RD;
432
433        assert_eq!(
434            Domain::from_ring_domain(RD::TimeSeries),
435            Domain::TemporalAnalysis
436        );
437        assert_eq!(
438            Domain::from_ring_domain(RD::RiskManagement),
439            Domain::RiskAnalytics
440        );
441        assert_eq!(Domain::from_ring_domain(RD::General), Domain::Core);
442    }
443
444    #[test]
445    fn test_from_ring_domain_closest_match() {
446        use ringkernel_core::domain::Domain as RD;
447
448        assert_eq!(
449            Domain::from_ring_domain(RD::NetworkAnalysis),
450            Domain::GraphAnalytics
451        );
452        assert_eq!(
453            Domain::from_ring_domain(RD::FraudDetection),
454            Domain::Banking
455        );
456        assert_eq!(Domain::from_ring_domain(RD::Settlement), Domain::Clearing);
457        assert_eq!(Domain::from_ring_domain(RD::MarketData), Domain::Core);
458        assert_eq!(Domain::from_ring_domain(RD::Simulation), Domain::Core);
459        assert_eq!(Domain::from_ring_domain(RD::Custom), Domain::Core);
460    }
461
462    #[test]
463    fn test_ring_domain_roundtrip() {
464        // Every rustkernel Domain should survive a roundtrip through
465        // ringkernel_core and back.
466        for &domain in Domain::ALL {
467            let ring = domain.to_ring_domain();
468            let back = Domain::from_ring_domain(ring);
469            assert_eq!(
470                back, domain,
471                "roundtrip failed for {:?} -> {:?} -> {:?}",
472                domain, ring, back
473            );
474        }
475    }
476}