anya_core/web5/
protocols.rs

1// use std::error::Error; // Commented out as it's not being used
2// Web5 Protocols Implementation
3// Provides protocol handlers for Web5 interactions
4// [AIR-012] Operational Reliability and [AIP-002] Modular Architecture
5
6use crate::web5::identity::{Web5Error, Web5Result};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10/// Protocol Handler trait
11///
12/// Defines the interface for protocol handlers in the Web5 system,
13/// following the Hexagonal Architecture principles.
14pub trait ProtocolHandler: Send + Sync {
15    /// Get the protocol ID
16    fn protocol_id(&self) -> &str;
17
18    /// Handle a protocol message
19    fn handle_message(&self, message: &[u8]) -> Web5Result<Vec<u8>>;
20
21    /// Get protocol definition
22    fn get_definition(&self) -> ProtocolDefinition;
23}
24
25/// Protocol Definition
26///
27/// Describes a protocol's capabilities and structure.
28#[derive(Clone, Serialize, Deserialize)]
29pub struct ProtocolDefinition {
30    /// Protocol ID (URI)
31    pub protocol: String,
32    /// Protocol version
33    pub version: String,
34    /// Protocol types
35    pub types: HashMap<String, TypeDefinition>,
36    /// Protocol actions
37    pub actions: Vec<ActionDefinition>,
38}
39
40/// Type Definition
41///
42/// Describes a data type within a protocol.
43#[derive(Clone, Serialize, Deserialize)]
44pub struct TypeDefinition {
45    /// Type schema
46    pub schema: String,
47    /// Type description
48    pub description: String,
49}
50
51/// Action Definition
52///
53/// Describes an action within a protocol.
54#[derive(Clone, Serialize, Deserialize)]
55pub struct ActionDefinition {
56    /// Action name
57    pub name: String,
58    /// Action description
59    pub description: String,
60    /// Action input type
61    pub input: Option<String>,
62    /// Action output type
63    pub output: Option<String>,
64}
65
66/// Protocol Manager
67///
68/// Manages protocol handlers and facilitates protocol-based interactions.
69pub struct ProtocolManager {
70    /// Registered protocols
71    protocols: HashMap<String, ProtocolDefinition>,
72    /// Protocol handlers
73    handlers: HashMap<String, Box<dyn ProtocolHandler>>,
74}
75
76impl Default for ProtocolManager {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82impl ProtocolManager {
83    /// Create a new protocol manager
84    pub fn new() -> Self {
85        Self {
86            protocols: HashMap::new(),
87            handlers: HashMap::new(),
88        }
89    }
90
91    /// Register a protocol handler
92    pub fn register_protocol(&mut self, handler: Box<dyn ProtocolHandler>) -> Web5Result<()> {
93        let protocol_id = handler.protocol_id().to_string();
94        let definition = handler.get_definition();
95
96        self.protocols.insert(protocol_id.clone(), definition);
97        self.handlers.insert(protocol_id, handler);
98
99        Ok(())
100    }
101
102    /// Get a protocol definition by ID
103    pub fn get_protocol(&self, protocol_id: &str) -> Web5Result<&ProtocolDefinition> {
104        self.protocols
105            .get(protocol_id)
106            .ok_or_else(|| Web5Error::Protocol(format!("Protocol not found: {protocol_id}")))
107    }
108
109    /// Handle a message for a specific protocol
110    pub fn handle_message(&self, protocol_id: &str, message: &[u8]) -> Web5Result<Vec<u8>> {
111        let handler = self.handlers.get(protocol_id).ok_or_else(|| {
112            Web5Error::Protocol(format!("No handler found for protocol: {protocol_id}"))
113        })?;
114
115        handler.handle_message(message)
116    }
117
118    /// Check if a protocol is registered
119    pub fn has_protocol(&self, protocol_id: &str) -> bool {
120        self.protocols.contains_key(protocol_id)
121    }
122
123    /// Get all registered protocol definitions
124    pub fn get_all_protocols(&self) -> Vec<&ProtocolDefinition> {
125        self.protocols.values().collect()
126    }
127}
128
129/// Profile Protocol Handler
130///
131/// Handles the standard profile protocol for Web5.
132pub struct ProfileProtocolHandler;
133
134impl Default for ProfileProtocolHandler {
135    fn default() -> Self {
136        Self::new()
137    }
138}
139
140impl ProfileProtocolHandler {
141    /// Create a new profile protocol handler
142    pub fn new() -> Self {
143        Self {}
144    }
145}
146
147impl ProtocolHandler for ProfileProtocolHandler {
148    fn protocol_id(&self) -> &str {
149        "https://identity.foundation/schemas/profile"
150    }
151
152    fn handle_message(&self, message: &[u8]) -> Web5Result<Vec<u8>> {
153        // Simple echo implementation for demonstration
154        Ok(message.to_vec())
155    }
156
157    fn get_definition(&self) -> ProtocolDefinition {
158        let mut types = HashMap::new();
159        types.insert(
160            "profile".to_string(),
161            TypeDefinition {
162                schema: r#"{
163                    "type": "object",
164                    "properties": {
165                        "name": { "type": "string" },
166                        "image": { "type": "string", "format": "uri" },
167                        "description": { "type": "string" }
168                    }
169                }"#
170                .to_string(),
171                description: "A user profile".to_string(),
172            },
173        );
174
175        let actions = vec![
176            ActionDefinition {
177                name: "get".to_string(),
178                description: "Get a profile".to_string(),
179                input: None,
180                output: Some("profile".to_string()),
181            },
182            ActionDefinition {
183                name: "update".to_string(),
184                description: "Update a profile".to_string(),
185                input: Some("profile".to_string()),
186                output: Some("profile".to_string()),
187            },
188        ];
189
190        ProtocolDefinition {
191            protocol: self.protocol_id().to_string(),
192            version: "1.0".to_string(),
193            types,
194            actions,
195        }
196    }
197}
198
199/// Credentials Protocol Handler
200///
201/// Handles the standard credentials protocol for Web5.
202pub struct CredentialProtocolHandler;
203
204impl Default for CredentialProtocolHandler {
205    fn default() -> Self {
206        Self::new()
207    }
208}
209
210impl CredentialProtocolHandler {
211    /// Create a new credentials protocol handler
212    pub fn new() -> Self {
213        Self {}
214    }
215}
216
217impl ProtocolHandler for CredentialProtocolHandler {
218    fn protocol_id(&self) -> &str {
219        "https://identity.foundation/schemas/credentials"
220    }
221
222    fn handle_message(&self, message: &[u8]) -> Web5Result<Vec<u8>> {
223        // Simple echo implementation for demonstration
224        Ok(message.to_vec())
225    }
226
227    fn get_definition(&self) -> ProtocolDefinition {
228        let mut types = HashMap::new();
229        types.insert(
230            "credential".to_string(),
231            TypeDefinition {
232                schema: r#"{
233                    "type": "object",
234                    "properties": {
235                        "id": { "type": "string" },
236                        "type": { "type": "array", "items": { "type": "string" } },
237                        "issuer": { "type": "string" },
238                        "issuanceDate": { "type": "string", "format": "date-time" },
239                        "credentialSubject": { "type": "object" }
240                    }
241                }"#
242                .to_string(),
243                description: "A verifiable credential".to_string(),
244            },
245        );
246
247        let actions = vec![
248            ActionDefinition {
249                name: "issue".to_string(),
250                description: "Issue a credential".to_string(),
251                input: Some("credential".to_string()),
252                output: Some("credential".to_string()),
253            },
254            ActionDefinition {
255                name: "verify".to_string(),
256                description: "Verify a credential".to_string(),
257                input: Some("credential".to_string()),
258                output: None,
259            },
260        ];
261
262        ProtocolDefinition {
263            protocol: self.protocol_id().to_string(),
264            version: "1.0".to_string(),
265            types,
266            actions,
267        }
268    }
269}
270
271#[cfg(test)]
272mod tests {
273    use super::*;
274    use std::error::Error;
275
276    #[tokio::test]
277    async fn test_protocol_manager() -> Result<(), Box<dyn Error>> {
278        let mut manager = ProtocolManager::new();
279
280        // Test registering a protocol
281        let profile_handler = Box::new(ProfileProtocolHandler::new());
282        manager.register_protocol(profile_handler)?;
283
284        // Test protocol lookup
285        assert!(manager.has_protocol("https://identity.foundation/schemas/profile"));
286
287        // Test getting all protocols
288        let protocols = manager.get_all_protocols();
289        assert_eq!(protocols.len(), 1);
290
291        // Test getting protocol definition
292        let _def = manager.get_protocol("https://identity.foundation/schemas/profile")?;
293
294        Ok(())
295    }
296
297    #[tokio::test]
298    async fn test_profile_protocol_handler() -> Result<(), Box<dyn Error>> {
299        let handler = ProfileProtocolHandler::new();
300
301        // Test protocol ID
302        assert_eq!(
303            handler.protocol_id(),
304            "https://identity.foundation/schemas/profile"
305        );
306
307        // Test message handling
308        let response = handler.handle_message(b"test")?;
309        assert_eq!(response, b"test");
310
311        Ok(())
312    }
313
314    #[tokio::test]
315    async fn test_credential_protocol_handler() -> Result<(), Box<dyn Error>> {
316        let handler = CredentialProtocolHandler::new();
317
318        // Test protocol ID
319        assert_eq!(
320            handler.protocol_id(),
321            "https://identity.foundation/schemas/credentials"
322        );
323
324        // Test message handling
325        let response = handler.handle_message(b"test")?;
326        assert_eq!(response, b"test");
327
328        Ok(())
329    }
330}