Skip to main content

tirith_core/
session.rs

1use std::sync::OnceLock;
2
3/// Global session ID for the current tirith process lifetime.
4static SESSION_ID: OnceLock<String> = OnceLock::new();
5
6/// Get or generate the session ID.
7///
8/// Priority:
9/// 1. `TIRITH_SESSION_ID` env var (set by shell hooks for cross-command sessions)
10/// 2. Auto-generated UUID for this process
11pub fn session_id() -> &'static str {
12    SESSION_ID.get_or_init(|| {
13        std::env::var("TIRITH_SESSION_ID").unwrap_or_else(|_| generate_session_id())
14    })
15}
16
17/// Generate a new session ID using UUID v4.
18fn generate_session_id() -> String {
19    uuid::Uuid::new_v4().to_string()
20}
21
22/// Generate a fresh session ID suitable for `tirith init` to export.
23pub fn new_session_id() -> String {
24    generate_session_id()
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn test_session_id_stable_within_process() {
33        let id1 = session_id();
34        let id2 = session_id();
35        assert_eq!(id1, id2);
36    }
37
38    #[test]
39    fn test_generate_session_id_unique() {
40        let a = generate_session_id();
41        // Small sleep to ensure different timestamp
42        std::thread::sleep(std::time::Duration::from_millis(1));
43        let b = generate_session_id();
44        assert_ne!(a, b);
45    }
46
47    #[test]
48    fn test_generate_session_id_format() {
49        let id = generate_session_id();
50        // UUID v4 format: 8-4-4-4-12 hex chars = 36 chars
51        assert_eq!(id.len(), 36);
52        assert!(uuid::Uuid::parse_str(&id).is_ok());
53    }
54}