Description
Session IDs are raw String or uuid::Uuid with no newtype wrapper:
- ACP session IDs:
session_id: uuid::Uuid::new_v4().to_string() in zeph-acp
- Experiment session IDs in
zeph-experiments
- Agent session context in
zeph-core
ConversationId(i64) is a proper newtype, but session IDs — a distinct concept — have no equivalent protection.
Problem
It is easy to pass a ConversationId where a session ID (or vice versa) is expected. Currently only the field name provides disambiguation, not the type system. A debug log search for a session ID can accidentally match conversation IDs.
Proposed Solution
/// Identifies a single agent session (one binary invocation or one ACP connection).
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SessionId(pub uuid::Uuid);
impl SessionId {
pub fn new() -> Self { Self(Uuid::new_v4()) }
}
Affected Crates
zeph-common (define newtype)
zeph-acp (ACP session tracking)
zeph-core (agent session context)
zeph-experiments (experiment session correlation)
Acceptance Criteria
Audit Reference
Architecture Audit 2026-04-11, finding TS-2 (P2)
Description
Session IDs are raw
Stringoruuid::Uuidwith no newtype wrapper:session_id: uuid::Uuid::new_v4().to_string()inzeph-acpzeph-experimentszeph-coreConversationId(i64)is a proper newtype, but session IDs — a distinct concept — have no equivalent protection.Problem
It is easy to pass a
ConversationIdwhere a session ID (or vice versa) is expected. Currently only the field name provides disambiguation, not the type system. A debug log search for a session ID can accidentally match conversation IDs.Proposed Solution
Affected Crates
zeph-common(define newtype)zeph-acp(ACP session tracking)zeph-core(agent session context)zeph-experiments(experiment session correlation)Acceptance Criteria
SessionIdnewtype inzeph-commonSessionIdinstead of rawUuid/StringSessionIdandConversationIdat call sitesAudit Reference
Architecture Audit 2026-04-11, finding TS-2 (P2)