Project started 🍾
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
"""Pure business core — entities, value objects, errors, and ports (Protocols).
|
||||
|
||||
This package MUST NOT import frameworks (FastAPI, SQLAlchemy, redis, …).
|
||||
Adapters depend on the domain; the domain depends on nothing but stdlib.
|
||||
"""
|
||||
@@ -0,0 +1,63 @@
|
||||
"""Domain exception hierarchy — framework-agnostic.
|
||||
|
||||
Services raise these; the API layer maps them to HTTP responses
|
||||
(see ``app.api.errors``). The domain never references HTTP status codes.
|
||||
"""
|
||||
|
||||
|
||||
class DomainError(Exception):
|
||||
"""Base for all expected, business-meaningful failures.
|
||||
|
||||
``code`` is a stable, machine-readable identifier returned to clients.
|
||||
"""
|
||||
|
||||
code: str = "domain_error"
|
||||
|
||||
def __init__(self, message: str | None = None) -> None:
|
||||
super().__init__(message or self.__class__.__doc__ or self.code)
|
||||
self.message = str(self)
|
||||
|
||||
|
||||
class NotFoundError(DomainError):
|
||||
"""Requested resource does not exist."""
|
||||
|
||||
code = "not_found"
|
||||
|
||||
|
||||
class AlreadyExistsError(DomainError):
|
||||
"""Resource conflicts with an existing one (e.g. duplicate)."""
|
||||
|
||||
code = "already_exists"
|
||||
|
||||
|
||||
class ConflictError(DomainError):
|
||||
"""Operation conflicts with current state (e.g. stale version on write)."""
|
||||
|
||||
code = "conflict"
|
||||
|
||||
|
||||
class ValidationError(DomainError):
|
||||
"""Input is well-formed but violates a business rule."""
|
||||
|
||||
code = "validation_error"
|
||||
|
||||
|
||||
class AuthenticationError(DomainError):
|
||||
"""Caller could not be authenticated."""
|
||||
|
||||
code = "authentication_error"
|
||||
|
||||
|
||||
class PermissionDeniedError(DomainError):
|
||||
"""Caller authenticated but not authorized for this action."""
|
||||
|
||||
code = "permission_denied"
|
||||
|
||||
|
||||
class DependencyUnavailableError(DomainError):
|
||||
"""An external dependency (source, ML, MusicBrainz) is unavailable.
|
||||
|
||||
Callers should degrade gracefully rather than propagate as a hard 500.
|
||||
"""
|
||||
|
||||
code = "dependency_unavailable"
|
||||
Reference in New Issue
Block a user