"""Domain error → HTTP response mapping. This module provides a single exception handler that converts domain-layer errors into structured JSON responses, keeping the service layer free from FastAPI's ``HTTPException``. """ from fastapi import Request from fastapi.responses import JSONResponse from app.domain.errors import ( BusinessRuleViolation, DomainError, DuplicateEntityError, EntityNotFoundError, InvalidOperationError, InvalidStateTransition, PermissionViolation, ) EXCEPTION_STATUS_MAP: dict[type[DomainError], int] = { EntityNotFoundError: 404, DuplicateEntityError: 409, InvalidStateTransition: 400, InvalidOperationError: 400, BusinessRuleViolation: 400, PermissionViolation: 403, } async def domain_exception_handler( request: Request, exc: DomainError, ) -> JSONResponse: """Convert a :class:`DomainError` into a JSON error response.""" status_code = EXCEPTION_STATUS_MAP.get(type(exc), 400) content: dict = {"detail": exc.message, "code": exc.code} if isinstance(exc, InvalidStateTransition): content["current_state"] = exc.current_state content["target_state"] = exc.target_state content["valid_transitions"] = exc.valid_transitions return JSONResponse(status_code=status_code, content=content)