agentic_reality/security/
mod.rs1use crate::types::error::{RealityError, RealityResult};
4use std::collections::HashMap;
5
6pub struct AuthManager {
8 token: Option<String>,
9 sessions: HashMap<String, SessionBinding>,
10 failed_attempts: u32,
11 rate_limit: u32,
12}
13
14impl AuthManager {
15 pub fn new() -> Self {
16 let token = std::env::var("AGENTIC_AUTH_TOKEN").ok();
17 Self {
18 token,
19 sessions: HashMap::new(),
20 failed_attempts: 0,
21 rate_limit: 100,
22 }
23 }
24
25 pub fn authenticate(&mut self, provided_token: &str) -> RealityResult<String> {
26 if self.failed_attempts >= self.rate_limit {
27 return Err(RealityError::Authentication("rate limited".into()));
28 }
29 match &self.token {
30 Some(expected) => {
31 if constant_time_eq::constant_time_eq(
32 expected.as_bytes(),
33 provided_token.as_bytes(),
34 ) {
35 self.failed_attempts = 0;
36 let session_id = uuid::Uuid::new_v4().to_string();
37 self.sessions.insert(
38 session_id.clone(),
39 SessionBinding {
40 session_id: session_id.clone(),
41 created_at: chrono::Utc::now().timestamp(),
42 last_activity: chrono::Utc::now().timestamp(),
43 permissions: Permissions::default(),
44 },
45 );
46 Ok(session_id)
47 } else {
48 self.failed_attempts += 1;
49 Err(RealityError::Authentication("invalid token".into()))
50 }
51 }
52 None => {
53 Ok("anonymous".to_string())
55 }
56 }
57 }
58
59 pub fn is_auth_required(&self) -> bool {
60 self.token.is_some()
61 }
62}
63
64impl Default for AuthManager {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct SessionBinding {
73 pub session_id: String,
74 pub created_at: i64,
75 pub last_activity: i64,
76 pub permissions: Permissions,
77}
78
79#[derive(Debug, Clone)]
81pub struct Permissions {
82 pub deployment_read: bool,
83 pub deployment_write: bool,
84 pub environment_read: bool,
85 pub environment_write: bool,
86 pub resource_read: bool,
87 pub resource_write: bool,
88 pub reality_read: bool,
89 pub reality_write: bool,
90 pub topology_read: bool,
91 pub topology_write: bool,
92 pub temporal_read: bool,
93 pub temporal_write: bool,
94 pub stakes_read: bool,
95 pub stakes_write: bool,
96 pub admin: bool,
97}
98
99impl Default for Permissions {
100 fn default() -> Self {
101 Self {
102 deployment_read: true,
103 deployment_write: true,
104 environment_read: true,
105 environment_write: true,
106 resource_read: true,
107 resource_write: true,
108 reality_read: true,
109 reality_write: true,
110 topology_read: true,
111 topology_write: true,
112 temporal_read: true,
113 temporal_write: true,
114 stakes_read: true,
115 stakes_write: true,
116 admin: false,
117 }
118 }
119}
120
121pub struct AuditLogger {
123 log_path: Option<String>,
124}
125
126impl AuditLogger {
127 pub fn new() -> Self {
128 Self {
129 log_path: std::env::var("AGENTIC_AUDIT_LOG").ok(),
130 }
131 }
132
133 pub fn log_operation(&self, operation: &str, session: &str, success: bool) {
134 if let Some(path) = &self.log_path {
135 let entry = serde_json::json!({
136 "timestamp": chrono::Utc::now().to_rfc3339(),
137 "operation": operation,
138 "session": session,
139 "success": success,
140 });
141 if let Ok(mut file) = std::fs::OpenOptions::new()
142 .create(true)
143 .append(true)
144 .open(path)
145 {
146 use std::io::Write;
147 let _ = writeln!(file, "{}", entry);
148 }
149 }
150 }
151}
152
153impl Default for AuditLogger {
154 fn default() -> Self {
155 Self::new()
156 }
157}