"""Domain exceptions for Aegis business logic. These exceptions are raised by service-layer code and automatically mapped to HTTP responses by the error-handler middleware registered in ``app.main``. This keeps the service layer free from any HTTP or framework coupling. """ class DomainException(Exception): """Base for all domain exceptions.""" def __init__(self, message: str, code: str = "DOMAIN_ERROR"): self.message = message self.code = code super().__init__(message) class EntityNotFoundError(DomainException): """Raised when a requested entity does not exist.""" def __init__(self, entity: str, identifier: str): super().__init__(f"{entity} not found: {identifier}", "NOT_FOUND") self.entity = entity self.identifier = identifier class DuplicateEntityError(DomainException): """Raised when creating an entity that already exists.""" def __init__(self, entity: str, field: str, value: str): super().__init__( f"{entity} with {field}='{value}' already exists", "DUPLICATE", ) class InvalidTransitionError(DomainException): """Raised when a state-machine transition is not allowed.""" def __init__( self, current_state: str, target_state: str, valid_transitions: list[str] | None = None, ): msg = f"Cannot transition from '{current_state}' to '{target_state}'" if valid_transitions: msg += f". Valid transitions: {valid_transitions}" super().__init__(msg, "INVALID_TRANSITION") self.current_state = current_state self.target_state = target_state self.valid_transitions = valid_transitions or [] class InvalidOperationError(DomainException): """Raised when an operation is invalid in the current context.""" def __init__(self, message: str): super().__init__(message, "INVALID_OPERATION") class AuthorizationError(DomainException): """Raised when the user lacks permissions for an action.""" def __init__(self, message: str = "Insufficient permissions"): super().__init__(message, "FORBIDDEN")