"""Custom application exceptions, mapped to HTTP responses in main.py.""" class AppError(Exception): """Base class for application errors.""" status_code: int = 500 detail: str = "Internal server error" def __init__(self, detail: str | None = None) -> None: super().__init__(detail or self.detail) if detail: self.detail = detail class NotFoundError(AppError): status_code = 404 detail = "Resource not found" class ConflictError(AppError): status_code = 409 detail = "Resource conflict" class UnauthorizedError(AppError): status_code = 401 detail = "Authentication required" class ForbiddenError(AppError): status_code = 403 detail = "Permission denied" class InvalidTokenError(UnauthorizedError): detail = "Token is invalid or expired" class CredentialDecryptionError(AppError): status_code = 500 detail = "Stored credential cannot be decrypted" class ConnectionTestError(AppError): status_code = 502 detail = "Connection test failed" class WinRMError(AppError): status_code = 502 detail = "WinRM operation failed" class SSHError(AppError): status_code = 502 detail = "SSH operation failed" class CAUError(AppError): status_code = 502 detail = "Cluster-Aware Updating operation failed" class ValidationError(AppError): status_code = 422 detail = "Validation failed" class JobNotCancellableError(ConflictError): detail = "Job cannot be cancelled in its current state"