Skip to main content

crue_engine/
lib.rs

1//! CRUE Engine - Deterministic Rule Execution Engine
2//! 
3//! This is the core of the Zero-Trust access control system.
4//! Rules are immutable, versioned, signed, and cannot be bypassed.
5
6pub mod engine;
7pub mod context;
8pub mod decision;
9pub mod rules;
10pub mod error;
11
12use serde::{Deserialize, Serialize};
13
14/// Rule evaluation request
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct EvaluationRequest {
17    /// Request ID for tracing
18    pub request_id: String,
19    /// Agent information
20    pub agent_id: String,
21    pub agent_org: String,
22    pub agent_level: String,
23    /// Mission context
24    pub mission_id: Option<String>,
25    pub mission_type: Option<String>,
26    /// Request details
27    pub query_type: Option<String>,
28    pub justification: Option<String>,
29    pub export_format: Option<String>,
30    pub result_limit: Option<u32>,
31    /// Real-time metrics
32    pub requests_last_hour: u32,
33    pub requests_last_24h: u32,
34    pub results_last_query: u32,
35    /// Geographic context
36    pub account_department: Option<String>,
37    pub allowed_departments: Vec<u32>,
38    /// Time context
39    pub request_hour: u32,
40    pub is_within_mission_hours: bool,
41}
42
43/// Rule evaluation result
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct EvaluationResult {
46    /// Request ID
47    pub request_id: String,
48    /// Decision
49    pub decision: decision::Decision,
50    /// Error code (if blocked)
51    pub error_code: Option<String>,
52    /// Error message
53    pub message: Option<String>,
54    /// Rule ID that triggered
55    pub rule_id: Option<String>,
56    /// Rule version
57    pub rule_version: Option<String>,
58    /// Timestamp
59    pub evaluated_at: String,
60    /// Evaluation time in ms
61    pub evaluation_time_ms: u64,
62}
63
64impl Default for EvaluationResult {
65    fn default() -> Self {
66        EvaluationResult {
67            request_id: String::new(),
68            decision: decision::Decision::Allow,
69            error_code: None,
70            message: None,
71            rule_id: None,
72            rule_version: None,
73            evaluated_at: chrono::Utc::now().to_rfc3339(),
74            evaluation_time_ms: 0,
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82    
83    #[test]
84    fn test_default_result() {
85        let result = EvaluationResult::default();
86        assert_eq!(result.decision, decision::Decision::Allow);
87    }
88    
89    #[test]
90    fn test_evaluation_request_serialization() {
91        let request = EvaluationRequest {
92            request_id: "req_001".to_string(),
93            agent_id: "AGENT_001".to_string(),
94            agent_org: "DGFiP".to_string(),
95            agent_level: "standard".to_string(),
96            mission_id: Some("MIS_001".to_string()),
97            mission_type: Some("FISCAL".to_string()),
98            query_type: Some("SEARCH_BY_NAME".to_string()),
99            justification: Some("EnquĂȘte".to_string()),
100            export_format: None,
101            result_limit: Some(50),
102            requests_last_hour: 10,
103            requests_last_24h: 100,
104            results_last_query: 5,
105            account_department: Some("75".to_string()),
106            allowed_departments: vec![75, 92, 93],
107            request_hour: 14,
108            is_within_mission_hours: true,
109        };
110        
111        let json = serde_json::to_string(&request).unwrap();
112        assert!(json.contains("AGENT_001"));
113    }
114}