Skip to content

refactor(common): introduce SessionId newtype to distinguish session from conversation IDs #2902

@bug-ops

Description

@bug-ops

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

  • SessionId newtype in zeph-common
  • ACP, core, and experiments use SessionId instead of raw Uuid/String
  • No confusion between SessionId and ConversationId at call sites

Audit Reference

Architecture Audit 2026-04-11, finding TS-2 (P2)

Metadata

Metadata

Assignees

Labels

P2High value, medium complexityarchitectureArchitecture improvementscorezeph-core craterefactorCode refactoring without functional changes

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions