Skip to main content

stateset_embedded/
fraud.rs

1//! Fraud detection operations for order risk assessment and rule management
2//!
3//! # Example
4//!
5//! ```rust,ignore
6//! use stateset_embedded::{Commerce, CreateFraudAssessment, OrderId};
7//!
8//! let commerce = Commerce::new("./store.db")?;
9//!
10//! let assessment = commerce.fraud().create_assessment(CreateFraudAssessment {
11//!     order_id: OrderId::new(),
12//!     signals: vec![],
13//!     ..Default::default()
14//! })?;
15//!
16//! println!("Risk score: {}", assessment.risk_score);
17//! # Ok::<(), stateset_embedded::CommerceError>(())
18//! ```
19
20use stateset_core::{
21    CreateFraudAssessment, CreateFraudRule, FraudAssessment, FraudAssessmentFilter, FraudDecision,
22    FraudRule, FraudRuleFilter, FraudRuleId, OrderId, Result, UpdateFraudRule,
23};
24use stateset_db::{Database, DatabaseCapability};
25use std::sync::Arc;
26
27/// Fraud detection operations for risk assessment and rules.
28pub struct Fraud {
29    db: Arc<dyn Database>,
30}
31
32impl std::fmt::Debug for Fraud {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        f.debug_struct("Fraud").finish_non_exhaustive()
35    }
36}
37
38impl Fraud {
39    pub(crate) fn new(db: Arc<dyn Database>) -> Self {
40        Self { db }
41    }
42
43    /// Whether fraud management is supported by the active backend.
44    #[must_use]
45    pub fn is_supported(&self) -> bool {
46        self.db.supports_capability(DatabaseCapability::Fraud)
47    }
48
49    fn ensure_supported(&self) -> Result<()> {
50        self.db.ensure_capability(DatabaseCapability::Fraud)
51    }
52
53    // ========================================================================
54    // Assessment Operations
55    // ========================================================================
56
57    /// Create a fraud assessment for an order.
58    ///
59    /// # Example
60    ///
61    /// ```rust,ignore
62    /// use stateset_embedded::{Commerce, CreateFraudAssessment, OrderId};
63    ///
64    /// let commerce = Commerce::new("./store.db")?;
65    ///
66    /// let assessment = commerce.fraud().create_assessment(CreateFraudAssessment {
67    ///     order_id: OrderId::new(),
68    ///     signals: vec![],
69    ///     ..Default::default()
70    /// })?;
71    /// # Ok::<(), stateset_embedded::CommerceError>(())
72    /// ```
73    pub fn create_assessment(&self, input: CreateFraudAssessment) -> Result<FraudAssessment> {
74        self.ensure_supported()?;
75        self.db.fraud().create_assessment(input)
76    }
77
78    /// Get a fraud assessment for an order.
79    pub fn get_assessment(&self, order_id: OrderId) -> Result<Option<FraudAssessment>> {
80        self.ensure_supported()?;
81        self.db.fraud().get_assessment(order_id)
82    }
83
84    /// List fraud assessments with optional filtering.
85    pub fn list_assessments(&self, filter: FraudAssessmentFilter) -> Result<Vec<FraudAssessment>> {
86        self.ensure_supported()?;
87        self.db.fraud().list_assessments(filter)
88    }
89
90    /// Update an assessment after manual review.
91    pub fn review_assessment(
92        &self,
93        order_id: OrderId,
94        decision: FraudDecision,
95        reviewer: String,
96        notes: Option<String>,
97    ) -> Result<FraudAssessment> {
98        self.ensure_supported()?;
99        self.db.fraud().review_assessment(order_id, decision, reviewer, notes)
100    }
101
102    // ========================================================================
103    // Rule Operations
104    // ========================================================================
105
106    /// Create a fraud detection rule.
107    pub fn create_rule(&self, input: CreateFraudRule) -> Result<FraudRule> {
108        self.ensure_supported()?;
109        self.db.fraud().create_rule(input)
110    }
111
112    /// Get a fraud rule by ID.
113    pub fn get_rule(&self, id: FraudRuleId) -> Result<Option<FraudRule>> {
114        self.ensure_supported()?;
115        self.db.fraud().get_rule(id)
116    }
117
118    /// Update a fraud rule.
119    pub fn update_rule(&self, id: FraudRuleId, input: UpdateFraudRule) -> Result<FraudRule> {
120        self.ensure_supported()?;
121        self.db.fraud().update_rule(id, input)
122    }
123
124    /// List fraud rules with optional filtering.
125    pub fn list_rules(&self, filter: FraudRuleFilter) -> Result<Vec<FraudRule>> {
126        self.ensure_supported()?;
127        self.db.fraud().list_rules(filter)
128    }
129
130    /// Delete a fraud rule.
131    pub fn delete_rule(&self, id: FraudRuleId) -> Result<()> {
132        self.ensure_supported()?;
133        self.db.fraud().delete_rule(id)
134    }
135
136    /// Get all enabled (active) fraud rules.
137    pub fn get_active_rules(&self) -> Result<Vec<FraudRule>> {
138        self.ensure_supported()?;
139        self.db.fraud().get_active_rules()
140    }
141}