Skip to content

domain.events.session_events

src.domain.events.session_events

Session domain events for event-driven architecture.

This module contains two types of events:

  1. Workflow Events (3-state pattern):
  2. SessionCreatedEvent, SessionRevokedEvent, AllSessionsRevokedEvent
  3. Emitted during critical workflows (login creates session, logout revokes)
  4. Trigger audit, logging, cache updates
  5. Note: These integrate with existing auth workflow events (UserLoginSucceeded creates session, UserPasswordChangeSucceeded revokes all)

  6. Operational Events (single state, NOT 3-state):

  7. SessionActivityUpdatedEvent, SessionProviderAccessEvent
  8. SuspiciousSessionActivityEvent, SessionLimitExceededEvent
  9. Used for telemetry, monitoring, security tracking
  10. Handlers must be lightweight (<10ms)
  11. Do NOT require audit unless security-relevant

See Decision 6 in docs/architecture/domain-events-architecture.md for operational event guidelines.

Reference
  • docs/architecture/session-management-architecture.md
  • docs/architecture/domain-events-architecture.md (Decision 6)

Classes

SessionCreatedEvent dataclass

Bases: DomainEvent

Emitted when a new session is created.

Triggered during successful login. Handlers may: - Cache session in Redis - Log session creation for audit - Send notification (if configured)

Attributes:

Name Type Description
session_id UUID

The new session's ID.

user_id UUID

User who logged in.

device_info str | None

Parsed device info ("Chrome on macOS").

ip_address str | None

Client IP address.

location str | None

Geographic location.

user_agent str | None

Full user agent string.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionCreatedEvent(DomainEvent):
    """Emitted when a new session is created.

    Triggered during successful login. Handlers may:
    - Cache session in Redis
    - Log session creation for audit
    - Send notification (if configured)

    Attributes:
        session_id: The new session's ID.
        user_id: User who logged in.
        device_info: Parsed device info ("Chrome on macOS").
        ip_address: Client IP address.
        location: Geographic location.
        user_agent: Full user agent string.
    """

    session_id: UUID
    user_id: UUID
    device_info: str | None = None
    ip_address: str | None = None
    location: str | None = None
    user_agent: str | None = None

SessionRevocationAttempted dataclass

Bases: DomainEvent

Session revocation attempt initiated (3-state pattern).

Triggers: - LoggingEventHandler: Log attempt - AuditEventHandler: Record SESSION_REVOCATION_ATTEMPTED

Attributes:

Name Type Description
session_id UUID

Session being revoked.

user_id UUID

User initiating revocation.

reason str

Why session is being revoked.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionRevocationAttempted(DomainEvent):
    """Session revocation attempt initiated (3-state pattern).

    Triggers:
    - LoggingEventHandler: Log attempt
    - AuditEventHandler: Record SESSION_REVOCATION_ATTEMPTED

    Attributes:
        session_id: Session being revoked.
        user_id: User initiating revocation.
        reason: Why session is being revoked.
    """

    session_id: UUID
    user_id: UUID
    reason: str

SessionRevokedEvent dataclass

Bases: DomainEvent

Emitted when a single session is revoked (SUCCEEDED).

Triggered during logout or session deletion. Handlers may: - Remove from cache - Log revocation for audit - Clean up associated resources

Attributes:

Name Type Description
session_id UUID

The revoked session's ID.

user_id UUID

User who owned the session.

reason str

Why session was revoked.

device_info str | None

Device info of revoked session (for notifications).

revoked_by_user bool

Whether user initiated (vs admin/system).

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionRevokedEvent(DomainEvent):
    """Emitted when a single session is revoked (SUCCEEDED).

    Triggered during logout or session deletion. Handlers may:
    - Remove from cache
    - Log revocation for audit
    - Clean up associated resources

    Attributes:
        session_id: The revoked session's ID.
        user_id: User who owned the session.
        reason: Why session was revoked.
        device_info: Device info of revoked session (for notifications).
        revoked_by_user: Whether user initiated (vs admin/system).
    """

    session_id: UUID
    user_id: UUID
    reason: str
    device_info: str | None = None
    revoked_by_user: bool = True

SessionRevocationFailed dataclass

Bases: DomainEvent

Session revocation failed (3-state pattern).

Triggers: - LoggingEventHandler: Log failure - AuditEventHandler: Record SESSION_REVOCATION_FAILED

Attributes:

Name Type Description
session_id UUID

Session that failed to revoke.

user_id UUID

User who attempted revocation.

reason str

Original reason for revocation.

failure_reason str

Why revocation failed.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionRevocationFailed(DomainEvent):
    """Session revocation failed (3-state pattern).

    Triggers:
    - LoggingEventHandler: Log failure
    - AuditEventHandler: Record SESSION_REVOCATION_FAILED

    Attributes:
        session_id: Session that failed to revoke.
        user_id: User who attempted revocation.
        reason: Original reason for revocation.
        failure_reason: Why revocation failed.
    """

    session_id: UUID
    user_id: UUID
    reason: str
    failure_reason: str

SessionEvictedEvent dataclass

Bases: DomainEvent

Emitted when a session is evicted due to limit enforcement.

Triggered when a new session causes the oldest to be automatically revoked (FIFO eviction). Handlers may: - Log eviction for audit - Send notification to user

Attributes:

Name Type Description
session_id UUID

The evicted session's ID.

user_id UUID

User who owns the session.

reason str

Why session was evicted (e.g., "session_limit_exceeded").

device_info str | None

Device info of evicted session.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionEvictedEvent(DomainEvent):
    """Emitted when a session is evicted due to limit enforcement.

    Triggered when a new session causes the oldest to be automatically
    revoked (FIFO eviction). Handlers may:
    - Log eviction for audit
    - Send notification to user

    Attributes:
        session_id: The evicted session's ID.
        user_id: User who owns the session.
        reason: Why session was evicted (e.g., "session_limit_exceeded").
        device_info: Device info of evicted session.
    """

    session_id: UUID
    user_id: UUID
    reason: str
    device_info: str | None = None

AllSessionsRevocationAttempted dataclass

Bases: DomainEvent

All sessions revocation attempt initiated (3-state pattern).

Triggers: - LoggingEventHandler: Log attempt - AuditEventHandler: Record ALL_SESSIONS_REVOCATION_ATTEMPTED

Attributes:

Name Type Description
user_id UUID

User whose sessions are being revoked.

reason str

Why sessions are being revoked.

except_session_id UUID | None

Session to exclude from revocation.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class AllSessionsRevocationAttempted(DomainEvent):
    """All sessions revocation attempt initiated (3-state pattern).

    Triggers:
    - LoggingEventHandler: Log attempt
    - AuditEventHandler: Record ALL_SESSIONS_REVOCATION_ATTEMPTED

    Attributes:
        user_id: User whose sessions are being revoked.
        reason: Why sessions are being revoked.
        except_session_id: Session to exclude from revocation.
    """

    user_id: UUID
    reason: str
    except_session_id: UUID | None = None

AllSessionsRevokedEvent dataclass

Bases: DomainEvent

Emitted when all sessions for a user are revoked (SUCCEEDED).

Triggered during password change or security event. Handlers may: - Clear all cached sessions - Log bulk revocation for audit - Send security notification

Attributes:

Name Type Description
user_id UUID

User whose sessions were revoked.

reason str

Why sessions were revoked.

session_count int

Number of sessions revoked.

except_session_id UUID | None

Session that was NOT revoked (current session).

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class AllSessionsRevokedEvent(DomainEvent):
    """Emitted when all sessions for a user are revoked (SUCCEEDED).

    Triggered during password change or security event. Handlers may:
    - Clear all cached sessions
    - Log bulk revocation for audit
    - Send security notification

    Attributes:
        user_id: User whose sessions were revoked.
        reason: Why sessions were revoked.
        session_count: Number of sessions revoked.
        except_session_id: Session that was NOT revoked (current session).
    """

    user_id: UUID
    reason: str
    session_count: int
    except_session_id: UUID | None = None

AllSessionsRevocationFailed dataclass

Bases: DomainEvent

All sessions revocation failed (3-state pattern).

Triggers: - LoggingEventHandler: Log failure - AuditEventHandler: Record ALL_SESSIONS_REVOCATION_FAILED

Attributes:

Name Type Description
user_id UUID

User whose sessions failed to revoke.

reason str

Original reason for revocation.

failure_reason str

Why revocation failed.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class AllSessionsRevocationFailed(DomainEvent):
    """All sessions revocation failed (3-state pattern).

    Triggers:
    - LoggingEventHandler: Log failure
    - AuditEventHandler: Record ALL_SESSIONS_REVOCATION_FAILED

    Attributes:
        user_id: User whose sessions failed to revoke.
        reason: Original reason for revocation.
        failure_reason: Why revocation failed.
    """

    user_id: UUID
    reason: str
    failure_reason: str

SessionActivityUpdatedEvent dataclass

Bases: DomainEvent

Emitted when session activity is updated.

Operational Event (single state, NOT 3-state pattern). Used for telemetry/monitoring, not a business workflow.

Triggered when user performs actions. Handlers may: - Update cache with new activity timestamp - Track for security monitoring

Handler Requirements: - Lightweight (<10ms) - Fail-silent (never block business flow) - No audit record (unless security threshold exceeded)

Attributes:

Name Type Description
session_id UUID

The session's ID.

user_id UUID

User who owns the session.

ip_address str | None

Current client IP.

ip_changed bool

Whether IP changed from session creation.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionActivityUpdatedEvent(DomainEvent):
    """Emitted when session activity is updated.

    **Operational Event** (single state, NOT 3-state pattern).
    Used for telemetry/monitoring, not a business workflow.

    Triggered when user performs actions. Handlers may:
    - Update cache with new activity timestamp
    - Track for security monitoring

    Handler Requirements:
    - Lightweight (<10ms)
    - Fail-silent (never block business flow)
    - No audit record (unless security threshold exceeded)

    Attributes:
        session_id: The session's ID.
        user_id: User who owns the session.
        ip_address: Current client IP.
        ip_changed: Whether IP changed from session creation.
    """

    session_id: UUID
    user_id: UUID
    ip_address: str | None = None
    ip_changed: bool = False

SessionProviderAccessEvent dataclass

Bases: DomainEvent

Emitted when a session accesses a financial provider.

Operational Event (single state, NOT 3-state pattern). Security-relevant: triggers audit record for compliance.

Dashtam-specific event for tracking provider access per session. Used for audit trail when investigating compromised sessions.

Handler Requirements: - May write audit record (security-relevant) - Should be lightweight otherwise

Attributes:

Name Type Description
session_id UUID

The session's ID.

user_id UUID

User who owns the session.

provider_name str

Provider that was accessed.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionProviderAccessEvent(DomainEvent):
    """Emitted when a session accesses a financial provider.

    **Operational Event** (single state, NOT 3-state pattern).
    Security-relevant: triggers audit record for compliance.

    Dashtam-specific event for tracking provider access per session.
    Used for audit trail when investigating compromised sessions.

    Handler Requirements:
    - May write audit record (security-relevant)
    - Should be lightweight otherwise

    Attributes:
        session_id: The session's ID.
        user_id: User who owns the session.
        provider_name: Provider that was accessed.
    """

    session_id: UUID
    user_id: UUID
    provider_name: str

SuspiciousSessionActivityEvent dataclass

Bases: DomainEvent

Emitted when suspicious activity is detected in a session.

Operational Event (single state, NOT 3-state pattern). Security-relevant: triggers audit record and may trigger alerts.

Triggered by anomaly detection. Handlers may: - Alert user via email (if threshold exceeded) - Log for security review (audit record) - Auto-revoke if threshold exceeded

Handler Requirements: - Security audit record required - May trigger alerts (async, non-blocking)

Attributes:

Name Type Description
session_id UUID

The session's ID.

user_id UUID

User who owns the session.

activity_type str

Type of suspicious activity.

details dict[str, str]

Additional context about the activity.

suspicious_count int

Total suspicious events for this session.

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SuspiciousSessionActivityEvent(DomainEvent):
    """Emitted when suspicious activity is detected in a session.

    **Operational Event** (single state, NOT 3-state pattern).
    Security-relevant: triggers audit record and may trigger alerts.

    Triggered by anomaly detection. Handlers may:
    - Alert user via email (if threshold exceeded)
    - Log for security review (audit record)
    - Auto-revoke if threshold exceeded

    Handler Requirements:
    - Security audit record required
    - May trigger alerts (async, non-blocking)

    Attributes:
        session_id: The session's ID.
        user_id: User who owns the session.
        activity_type: Type of suspicious activity.
        details: Additional context about the activity.
        suspicious_count: Total suspicious events for this session.
    """

    session_id: UUID
    user_id: UUID
    activity_type: str
    details: dict[str, str] = field(default_factory=dict)
    suspicious_count: int = 0

SessionLimitExceededEvent dataclass

Bases: DomainEvent

Emitted when user's session limit is exceeded.

Operational Event (single state, NOT 3-state pattern). Informational event for monitoring session limit enforcement.

Triggered during login when new session would exceed limit. Handlers may: - Log for metrics/monitoring - Alert admin (if configured)

Handler Requirements: - Lightweight (<10ms) - Fail-silent (never block login flow) - No audit record required (informational only)

Attributes:

Name Type Description
user_id UUID

User who exceeded limit.

current_count int

Current number of active sessions.

max_sessions int

User's session limit.

evicted_session_id UUID | None

Session that was evicted (FIFO).

Source code in src/domain/events/session_events.py
@dataclass(frozen=True, kw_only=True, slots=True)
class SessionLimitExceededEvent(DomainEvent):
    """Emitted when user's session limit is exceeded.

    **Operational Event** (single state, NOT 3-state pattern).
    Informational event for monitoring session limit enforcement.

    Triggered during login when new session would exceed limit.
    Handlers may:
    - Log for metrics/monitoring
    - Alert admin (if configured)

    Handler Requirements:
    - Lightweight (<10ms)
    - Fail-silent (never block login flow)
    - No audit record required (informational only)

    Attributes:
        user_id: User who exceeded limit.
        current_count: Current number of active sessions.
        max_sessions: User's session limit.
        evicted_session_id: Session that was evicted (FIFO).
    """

    user_id: UUID
    current_count: int
    max_sessions: int
    evicted_session_id: UUID | None = None