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