Skip to main content

aura_core/effects/
agent.rs

1//! Agent-Specific Effect Traits
2//!
3//! **Layer 1 (aura-core)**: Foundational effect trait definitions for agent operations.
4//!
5//! These effect traits define capabilities specific to device-side agent operations.
6//! They compose core system effects into higher-level device workflows.
7//!
8//! These are foundational capability trait definitions, similar to CryptoEffects,
9//! NetworkEffects, etc., and belong in the interface layer.
10//!
11//! # Effect Classification
12//!
13//! - **Category**: Application Effect
14//! - **Implementation**: `aura-agent` (Layer 6)
15//! - **Usage**: Agent coordination, device sessions, authentication flows
16//!
17//! This is an application effect with heavy Aura-specific semantics for device
18//! enrollment, session management, and authentication flows. Handlers implement
19//! the agent runtime in `aura-agent` by composing infrastructure effects with
20//! domain-specific logic.
21
22/// Maximum size for encrypted credential data in bytes.
23/// Supports typical encrypted key material with padding.
24pub const MAX_ENCRYPTED_CREDENTIALS_BYTES: usize = 4096;
25
26/// Maximum size for agent message/session payloads in bytes.
27/// Prevents unbounded memory allocation from malformed inputs.
28pub const MAX_AGENT_PAYLOAD_BYTES: usize = 65536;
29
30use crate::{
31    types::identifiers::{AccountId, DeviceId, SessionId},
32    AuraResult as Result, CapabilityName,
33};
34use async_trait::async_trait;
35use serde::{Deserialize, Serialize};
36use std::collections::HashMap;
37
38/// Device information structure
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct DeviceInfo {
41    /// Device identifier
42    pub device_id: DeviceId,
43    /// Account this device belongs to
44    pub account_id: Option<AccountId>,
45    /// Human-readable device name
46    pub device_name: String,
47    /// Whether hardware security is available
48    pub hardware_security: bool,
49    /// Whether device attestation is available
50    pub attestation_available: bool,
51    /// Last sync timestamp
52    pub last_sync: Option<u64>,
53    /// Storage usage in bytes
54    pub storage_usage: u64,
55    /// Maximum storage in bytes
56    pub storage_limit: u64,
57}
58
59/// High-level agent effects that compose core system capabilities
60/// into device-specific workflows
61#[async_trait]
62pub trait AgentEffects: Send + Sync {
63    /// Initialize the agent runtime
64    async fn initialize(&self) -> Result<()>;
65
66    /// Get comprehensive device information
67    async fn get_device_info(&self) -> Result<DeviceInfo>;
68
69    /// Perform agent shutdown procedures
70    async fn shutdown(&self) -> Result<()>;
71
72    /// Sync with distributed systems
73    async fn sync_distributed_state(&self) -> Result<()>;
74
75    /// Get agent health status
76    async fn health_check(&self) -> Result<AgentHealthStatus>;
77}
78
79/// Agent health status information
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct AgentHealthStatus {
82    pub overall_status: HealthStatus,
83    pub storage_status: HealthStatus,
84    pub network_status: HealthStatus,
85    pub authentication_status: HealthStatus,
86    pub session_status: HealthStatus,
87    pub last_check: u64,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub enum HealthStatus {
92    Healthy,
93    Degraded { reason: String },
94    Unhealthy { error: String },
95}
96
97/// Device-specific secure storage effects that enhance core storage
98/// with biometric protection and device-specific security features
99#[async_trait]
100pub trait DeviceStorageEffects: Send + Sync {
101    /// Store credential with biometric protection
102    async fn store_credential(&self, key: &str, credential: &[u8]) -> Result<()>;
103
104    /// Retrieve credential with biometric authentication
105    async fn retrieve_credential(&self, key: &str) -> Result<Option<Vec<u8>>>;
106
107    /// Delete credential securely
108    async fn delete_credential(&self, key: &str) -> Result<()>;
109
110    /// List all stored credential keys (metadata only)
111    async fn list_credentials(&self) -> Result<Vec<String>>;
112
113    /// Store device-specific configuration
114    async fn store_device_config(&self, config: &[u8]) -> Result<()>;
115
116    /// Retrieve device configuration
117    async fn retrieve_device_config(&self) -> Result<Option<Vec<u8>>>;
118
119    /// Backup credentials to secure backup location
120    async fn backup_credentials(&self) -> Result<CredentialBackup>;
121
122    /// Restore credentials from backup with verification
123    async fn restore_credentials(&self, backup: &CredentialBackup) -> Result<()>;
124
125    /// Securely wipe all stored credentials
126    async fn secure_wipe(&self) -> Result<()>;
127}
128
129/// Credential backup structure
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct CredentialBackup {
132    pub device_id: DeviceId,
133    pub timestamp: u64,
134    pub encrypted_credentials: Vec<u8>,
135    pub backup_hash: [u8; 32],
136    pub metadata: HashMap<String, String>,
137}
138
139/// Authentication effects for device unlock and biometric operations
140#[async_trait]
141pub trait AuthenticationEffects: Send + Sync {
142    /// Authenticate device using available methods (biometric, PIN, etc.)
143    async fn authenticate_device(&self) -> Result<AuthenticationResult>;
144
145    /// Check if device is currently authenticated
146    async fn is_authenticated(&self) -> Result<bool>;
147
148    /// Lock the device (clear authentication state)
149    async fn lock_device(&self) -> Result<()>;
150
151    /// Get available authentication methods
152    async fn get_auth_methods(&self) -> Result<Vec<AuthMethod>>;
153
154    /// Enroll new biometric data
155    async fn enroll_biometric(&self, biometric_type: BiometricType) -> Result<()>;
156
157    /// Remove enrolled biometric data
158    async fn remove_biometric(&self, biometric_type: BiometricType) -> Result<()>;
159
160    /// Verify capability token for operations
161    async fn verify_capability(&self, capability: &[u8]) -> Result<bool>;
162
163    /// Generate device attestation
164    async fn generate_attestation(&self) -> Result<Vec<u8>>;
165}
166
167/// Authentication result from device unlock
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct AuthenticationResult {
170    pub success: bool,
171    pub method_used: Option<AuthMethod>,
172    pub session_token: Option<Vec<u8>>,
173    pub expires_at: Option<u64>,
174    pub error: Option<String>,
175}
176
177/// Available authentication methods
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub enum AuthMethod {
180    Biometric(BiometricType),
181    Pin,
182    Password,
183    HardwareKey,
184    DeviceCredential,
185}
186
187/// Supported biometric types
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub enum BiometricType {
190    Fingerprint,
191    FaceId,
192    TouchId,
193    VoiceId,
194}
195
196/// Session management effects for device-side session coordination
197///
198/// Enhanced to support choreographic patterns and consistent protocol implementation.
199#[async_trait]
200pub trait SessionManagementEffects: Send + Sync {
201    /// Create new device session for distributed protocols
202    async fn create_session(&self, session_type: SessionType) -> Result<SessionId>;
203
204    /// Create choreographic session with participants and roles
205    async fn create_choreographic_session(
206        &self,
207        session_type: SessionType,
208        participants: Vec<DeviceId>,
209        choreography_config: ChoreographyConfig,
210    ) -> Result<SessionId>;
211
212    /// Join existing session as participant
213    async fn join_session(&self, session_id: SessionId) -> Result<SessionHandle>;
214
215    /// Join choreographic session with specific role
216    async fn join_choreographic_session(
217        &self,
218        session_id: SessionId,
219        role: ChoreographicRole,
220    ) -> Result<SessionHandle>;
221
222    /// Leave session gracefully
223    async fn leave_session(&self, session_id: SessionId) -> Result<()>;
224
225    /// End session (if session owner)
226    async fn end_session(&self, session_id: SessionId) -> Result<()>;
227
228    /// List active sessions for this device
229    async fn list_active_sessions(&self) -> Result<Vec<SessionInfo>>;
230
231    /// Get session status and metadata
232    async fn get_session_status(&self, session_id: SessionId) -> Result<SessionStatus>;
233
234    /// Send choreographic message within session context
235    async fn send_choreographic_message(
236        &self,
237        session_id: SessionId,
238        message_type: &str,
239        payload: &[u8],
240        target_role: Option<ChoreographicRole>,
241    ) -> Result<()>;
242
243    /// Receive choreographic messages for session with role filtering
244    async fn receive_choreographic_messages(
245        &self,
246        session_id: SessionId,
247        role_filter: Option<ChoreographicRole>,
248    ) -> Result<Vec<ChoreographicMessage>>;
249
250    /// Get choreography phase for session
251    async fn get_choreography_phase(&self, session_id: SessionId) -> Result<Option<String>>;
252
253    /// Update choreography state
254    async fn update_choreography_state(
255        &self,
256        session_id: SessionId,
257        phase: &str,
258        state_data: &[u8],
259    ) -> Result<()>;
260
261    /// Validate choreography message against current phase
262    async fn validate_choreographic_message(
263        &self,
264        session_id: SessionId,
265        message: &ChoreographicMessage,
266    ) -> Result<bool>;
267}
268
269/// Types of sessions the agent can participate in
270#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
271pub enum SessionType {
272    Recovery,
273    KeyRotation,
274    ThresholdOperation,
275    Coordination,
276    Backup,
277    Invitation,
278    Rendezvous,
279    Sync,
280    Custom(String),
281}
282
283/// Session handle for ongoing operations
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct SessionHandle {
286    pub session_id: SessionId,
287    pub role: SessionRole,
288    pub participants: Vec<DeviceId>,
289    pub created_at: u64,
290}
291
292/// Role in a session
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub enum SessionRole {
295    Coordinator,
296    Initiator,
297    Participant,
298    Approver,
299    Observer,
300}
301
302/// Session information
303#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct SessionInfo {
305    pub session_id: SessionId,
306    pub session_type: SessionType,
307    pub role: SessionRole,
308    pub participants: Vec<DeviceId>,
309    pub status: SessionStatus,
310    pub created_at: u64,
311    pub updated_at: u64,
312    pub timeout_at: Option<u64>,
313    pub operation: Option<String>,
314    pub metadata: std::collections::HashMap<String, String>,
315}
316
317/// Session status
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub enum SessionStatus {
320    Created,
321    Active,
322    Paused,
323    WaitingForApprovals,
324    Completed,
325    Failed { error: String },
326    Expired,
327    Cancelled,
328    TimedOut,
329}
330
331/// Message within a session
332#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct SessionMessage {
334    pub from: DeviceId,
335    pub to: Option<DeviceId>, // None for broadcast
336    pub timestamp: u64,
337    pub message_type: String,
338    pub payload: Vec<u8>,
339}
340
341/// Choreographic role in a session
342#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
343pub struct ChoreographicRole {
344    pub device_id: uuid::Uuid,
345    pub role_index: u32,
346}
347
348impl ChoreographicRole {
349    #[must_use]
350    pub fn new(device_id: uuid::Uuid, role_index: u32) -> Self {
351        Self {
352            device_id,
353            role_index,
354        }
355    }
356}
357
358/// Configuration for choreographic sessions
359#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct ChoreographyConfig {
361    /// Protocol namespace
362    pub namespace: String,
363    /// Guard capabilities required
364    pub guard_capabilities: Vec<CapabilityName>,
365    /// Flow budget limits
366    pub flow_budget: Option<u64>,
367    /// Journal facts to record
368    pub journal_facts: Vec<String>,
369    /// Timeout for the choreography in seconds
370    pub timeout_seconds: u64,
371    /// Maximum number of retries
372    pub max_retries: u32,
373}
374
375/// Choreographic message with role and phase information
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct ChoreographicMessage {
378    pub from: DeviceId,
379    pub to: Option<DeviceId>,
380    pub source_role: ChoreographicRole,
381    pub target_role: Option<ChoreographicRole>,
382    pub protocol_namespace: String,
383    pub phase: String,
384    pub message_type: String,
385    pub payload: Vec<u8>,
386    pub timestamp: u64,
387    pub sequence_number: u64,
388    pub guard_capabilities: Vec<CapabilityName>,
389}
390
391/// Configuration management effects for device settings
392#[async_trait]
393pub trait ConfigurationEffects: Send + Sync {
394    /// Get device configuration
395    async fn get_device_config(&self) -> Result<DeviceConfig>;
396
397    /// Update device configuration
398    async fn update_device_config(&self, config: &DeviceConfig) -> Result<()>;
399
400    /// Reset configuration to defaults
401    async fn reset_to_defaults(&self) -> Result<()>;
402
403    /// Export configuration for backup
404    async fn export_config(&self) -> Result<Vec<u8>>;
405
406    /// Import configuration from backup
407    async fn import_config(&self, config_data: &[u8]) -> Result<()>;
408
409    /// Validate configuration settings
410    async fn validate_config(&self, config: &DeviceConfig) -> Result<Vec<ConfigValidationError>>;
411
412    /// Get configuration value as JSON
413    async fn get_config_json(&self, key: &str) -> Result<Option<serde_json::Value>>;
414
415    /// Set configuration value as JSON
416    async fn set_config_json(&self, key: &str, value: &serde_json::Value) -> Result<()>;
417
418    /// Get all configuration as key-value pairs
419    async fn get_all_config(&self) -> Result<std::collections::HashMap<String, serde_json::Value>>;
420}
421
422/// Device configuration structure
423#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct DeviceConfig {
425    pub device_name: String,
426    pub auto_lock_timeout: u32, // seconds
427    pub biometric_enabled: bool,
428    pub backup_enabled: bool,
429    pub sync_interval: u32,    // seconds
430    pub max_storage_size: u64, // bytes
431    pub network_timeout: u32,  // milliseconds
432    pub log_level: String,
433    pub custom_settings: HashMap<String, serde_json::Value>,
434}
435
436impl Default for DeviceConfig {
437    fn default() -> Self {
438        Self {
439            device_name: "Aura Device".to_string(),
440            auto_lock_timeout: 300, // 5 minutes
441            biometric_enabled: false,
442            backup_enabled: true,
443            sync_interval: 3600,                 // 1 hour
444            max_storage_size: 100 * 1024 * 1024, // 100 MB
445            network_timeout: 5000,               // 5 seconds
446            log_level: "info".to_string(),
447            custom_settings: HashMap::new(),
448        }
449    }
450}
451
452/// Configuration validation error
453#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct ConfigValidationError {
455    pub field: String,
456    pub error: String,
457    pub suggested_value: Option<serde_json::Value>,
458}
459
460/// Configuration operation error
461#[derive(Debug, Clone, Serialize, Deserialize)]
462pub enum ConfigError {
463    /// Configuration key not found
464    NotFound(String),
465    /// Invalid JSON value
466    InvalidJson(String),
467    /// Serialization/deserialization error
468    SerializationError(String),
469    /// Storage error
470    StorageError(String),
471    /// Permission denied
472    PermissionDenied(String),
473}
474
475impl std::fmt::Display for ConfigError {
476    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
477        match self {
478            ConfigError::NotFound(key) => write!(f, "Configuration key not found: {key}"),
479            ConfigError::InvalidJson(msg) => write!(f, "Invalid JSON value: {msg}"),
480            ConfigError::SerializationError(msg) => write!(f, "Serialization error: {msg}"),
481            ConfigError::StorageError(msg) => write!(f, "Storage error: {msg}"),
482            ConfigError::PermissionDenied(msg) => write!(f, "Permission denied: {msg}"),
483        }
484    }
485}
486
487impl std::error::Error for ConfigError {}