solti_model/domain/identity/
agent.rs1use super::validate_identity;
7use crate::error::ModelError;
8
9pub const AGENT_ID_MAX_LEN: usize = 128;
11
12arc_str_newtype! {
13 #[cfg_attr(feature = "schema", schemars(schema_with = "crate::schema::agent_id"))]
14 pub struct AgentId;
31}
32
33impl AgentId {
34 pub fn validate_format(&self) -> Result<(), ModelError> {
49 validate_identity("agent_id", self.as_str(), AGENT_ID_MAX_LEN)
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use std::sync::Arc;
57
58 #[test]
59 fn exposes_string_identity_hashing_and_shared_clones() {
60 use std::collections::HashSet;
61
62 let id = AgentId::new("agent-a").unwrap();
63 assert_eq!(id.as_str(), "agent-a");
64 assert_eq!(format!("{id}"), "agent-a");
65 assert_eq!(id, *"agent-a");
66
67 let mut set = HashSet::new();
68 set.insert(id.clone());
69 set.insert(AgentId::new("agent-b").unwrap());
70 set.insert(AgentId::new("agent-a").unwrap());
71 assert_eq!(set.len(), 2);
72
73 let cloned = id.clone();
74 let a: Arc<str> = id.into_inner();
75 let b: Arc<str> = cloned.into_inner();
76 assert!(Arc::ptr_eq(&a, &b));
77 }
78
79 #[test]
80 fn serde_is_transparent() {
81 let id = AgentId::new("550e8400-e29b-41d4-a716-446655440000").unwrap();
82 let json = serde_json::to_string(&id).unwrap();
83 assert_eq!(json, r#""550e8400-e29b-41d4-a716-446655440000""#);
84 assert_eq!(serde_json::from_str::<AgentId>(&json).unwrap(), id);
85 }
86
87 #[test]
88 fn validation_accepts_safe_values_and_rejects_unsafe_values() {
89 for valid in [
90 "550e8400-e29b-41d4-a716-446655440000",
91 "worker-pod-7b9f4",
92 "agent.eu-west-1.01",
93 ] {
94 AgentId::new(valid).unwrap();
95 }
96 for invalid in ["", "agent with space", "agent/path"] {
97 assert!(AgentId::new(invalid).is_err(), "must reject {invalid:?}");
98 }
99 }
100}