use std::cmp::Reverse;
use std::time::{Duration, Instant};
use dashmap::DashMap;
pub type InstallId = String;
pub const SESSION_QUIET_WINDOW: Duration = Duration::from_secs(300);
const MAX_TRACKED_INSTALLS: usize = 1024;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Assurance {
Attested,
Inferred,
Unknown,
}
impl Assurance {
pub fn as_str(&self) -> &'static str {
match self {
Assurance::Attested => "attested",
Assurance::Inferred => "inferred",
Assurance::Unknown => "unknown",
}
}
}
#[derive(Clone, Debug)]
pub struct SessionActivity {
pub agent_id: String,
pub source: String,
pub session_id: String,
pub last_seen: Instant,
}
#[derive(Default)]
pub struct SessionRegistry {
active: DashMap<InstallId, Vec<SessionActivity>>,
}
impl SessionRegistry {
pub fn upsert(&self, install_id: &str, agent_id: &str, source: &str, session_id: &str) {
if !self.active.contains_key(install_id) && self.active.len() >= MAX_TRACKED_INSTALLS {
self.evict_empty();
if self.active.len() >= MAX_TRACKED_INSTALLS {
return;
}
}
let now = Instant::now();
let mut entry = self.active.entry(install_id.to_string()).or_default();
entry.retain(|a| now.duration_since(a.last_seen) < SESSION_QUIET_WINDOW);
if let Some(existing) = entry.iter_mut().find(|a| a.session_id == session_id) {
existing.last_seen = now;
existing.agent_id = agent_id.to_string();
existing.source = source.to_string();
} else {
entry.push(SessionActivity {
agent_id: agent_id.to_string(),
source: source.to_string(),
session_id: session_id.to_string(),
last_seen: now,
});
}
}
fn evict_empty(&self) {
let now = Instant::now();
self.active.retain(|_, v| {
v.retain(|a| now.duration_since(a.last_seen) < SESSION_QUIET_WINDOW);
!v.is_empty()
});
}
fn fresh(&self, install_id: &str) -> Vec<SessionActivity> {
let now = Instant::now();
match self.active.get(install_id) {
Some(v) => v
.iter()
.filter(|a| now.duration_since(a.last_seen) < SESSION_QUIET_WINDOW)
.cloned()
.collect(),
None => Vec::new(),
}
}
}
#[derive(Clone, Debug)]
pub struct Resolved {
pub agent_id: Option<String>,
pub source: Option<String>,
pub session_id: Option<String>,
pub assurance: Assurance,
}
impl Resolved {
pub fn unknown() -> Self {
Resolved {
agent_id: None,
source: None,
session_id: None,
assurance: Assurance::Unknown,
}
}
}
pub fn resolve_session(reg: &SessionRegistry, install: &str) -> Resolved {
let mut active = reg.fresh(install);
match active.len() {
1 => {
let a = active.remove(0);
Resolved {
agent_id: Some(a.agent_id),
source: Some(a.source),
session_id: Some(a.session_id),
assurance: Assurance::Attested,
}
}
0 => Resolved::unknown(),
_ => {
active.sort_by_key(|a| Reverse(a.last_seen));
let a = active.remove(0);
Resolved {
agent_id: Some(a.agent_id),
source: Some(a.source),
session_id: Some(a.session_id),
assurance: Assurance::Inferred,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zero_active_resolves_unknown() {
let reg = SessionRegistry::default();
let r = resolve_session(®, "agt_absent");
assert_eq!(r.assurance, Assurance::Unknown);
assert!(r.agent_id.is_none() && r.session_id.is_none() && r.source.is_none());
}
#[test]
fn one_active_resolves_attested_with_identifiers() {
let reg = SessionRegistry::default();
reg.upsert("agt_1", "agt_1", "claude-code", "sess_a");
let r = resolve_session(®, "agt_1");
assert_eq!(r.assurance, Assurance::Attested);
assert_eq!(r.session_id.as_deref(), Some("sess_a"));
assert_eq!(r.agent_id.as_deref(), Some("agt_1"));
assert_eq!(r.source.as_deref(), Some("claude-code"));
}
#[test]
fn two_concurrent_resolve_inferred_most_recent() {
let reg = SessionRegistry::default();
reg.upsert("agt_1", "agt_1", "claude-code", "sess_old");
std::thread::sleep(Duration::from_millis(5));
reg.upsert("agt_1", "agt_1", "claude-code", "sess_new");
let r = resolve_session(®, "agt_1");
assert_eq!(r.assurance, Assurance::Inferred);
assert_eq!(r.session_id.as_deref(), Some("sess_new"));
}
#[test]
fn refresh_updates_last_seen_not_count() {
let reg = SessionRegistry::default();
reg.upsert("agt_1", "agt_1", "claude-code", "sess_a");
reg.upsert("agt_1", "agt_1", "claude-code", "sess_a");
let r = resolve_session(®, "agt_1");
assert_eq!(r.assurance, Assurance::Attested);
}
#[test]
fn assurance_wire_strings_are_the_frozen_three() {
assert_eq!(Assurance::Attested.as_str(), "attested");
assert_eq!(Assurance::Inferred.as_str(), "inferred");
assert_eq!(Assurance::Unknown.as_str(), "unknown");
}
}