Skip to main content

aa_core/
identity.rs

1//! Stable identity types for agents and execution sessions.
2//!
3//! [`AgentId`] identifies a long-lived agent across sessions.
4//! [`SessionId`] identifies a single execution run within that agent.
5//! Both are 16-byte opaque wrappers over UUID v4 raw bytes.
6
7/// Stable identifier for an agent — UUID v4 encoded as raw bytes.
8///
9/// The inner `[u8; 16]` is private. Use [`AgentId::from_bytes`] to construct
10/// and [`AgentId::as_bytes`] to inspect.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct AgentId([u8; 16]);
14
15impl AgentId {
16    /// Construct an [`AgentId`] from raw UUID bytes.
17    #[inline]
18    pub const fn from_bytes(bytes: [u8; 16]) -> Self {
19        Self(bytes)
20    }
21
22    /// Return the raw UUID bytes.
23    #[inline]
24    pub const fn as_bytes(&self) -> &[u8; 16] {
25        &self.0
26    }
27}
28
29/// Per-execution session identifier — UUID v4 encoded as raw bytes.
30///
31/// A new [`SessionId`] is generated for each agent execution. It ties together
32/// all governance events within a single run.
33///
34/// The inner `[u8; 16]` is private. Use [`SessionId::from_bytes`] to construct
35/// and [`SessionId::as_bytes`] to inspect.
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38pub struct SessionId([u8; 16]);
39
40impl SessionId {
41    /// Construct a [`SessionId`] from raw UUID bytes.
42    #[inline]
43    pub const fn from_bytes(bytes: [u8; 16]) -> Self {
44        Self(bytes)
45    }
46
47    /// Return the raw UUID bytes.
48    #[inline]
49    pub const fn as_bytes(&self) -> &[u8; 16] {
50        &self.0
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    const BYTES: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
59
60    #[test]
61    fn agent_id_round_trip() {
62        let id = AgentId::from_bytes(BYTES);
63        assert_eq!(id.as_bytes(), &BYTES);
64    }
65
66    #[test]
67    fn session_id_round_trip() {
68        let id = SessionId::from_bytes(BYTES);
69        assert_eq!(id.as_bytes(), &BYTES);
70    }
71
72    #[test]
73    fn agent_id_equality() {
74        let a = AgentId::from_bytes(BYTES);
75        let b = AgentId::from_bytes(BYTES);
76        assert_eq!(a, b);
77    }
78
79    #[test]
80    fn session_id_equality() {
81        let a = SessionId::from_bytes(BYTES);
82        let b = SessionId::from_bytes(BYTES);
83        assert_eq!(a, b);
84    }
85
86    #[test]
87    fn agent_id_copy_semantics() {
88        let a = AgentId::from_bytes(BYTES);
89        let b = a; // Copy, not move
90        assert_eq!(a, b);
91    }
92
93    #[test]
94    fn session_id_copy_semantics() {
95        let a = SessionId::from_bytes(BYTES);
96        let b = a; // Copy, not move
97        assert_eq!(a, b);
98    }
99
100    #[test]
101    fn agent_id_and_session_id_are_distinct_types() {
102        // Compile-time check: AgentId and SessionId are different types.
103        // If they were the same type, the following would be ambiguous or fail.
104        let _agent: AgentId = AgentId::from_bytes(BYTES);
105        let _session: SessionId = SessionId::from_bytes(BYTES);
106    }
107}