//! Domain error types for the IAM (auth) module. //! //! Typed error enums replace `anyhow::Result` in domain traits and //! application services, enabling callers to match on specific error //! variants (e.g. `NotFound` vs `Conflict`) rather than string-checking. //! //! # Components //! //! - [`RepositoryError`] — persistence-layer errors (not found, conflict, I/O) //! - [`ServiceError`] — use-case / orchestration errors (config, state //! mismatch, provider failures) use std::fmt; use crate::error::DomainError; /// Shared repository error type for IAM persistence operations. pub type RepositoryError = DomainError; /// Errors from service / use-case operations in the IAM domain. #[derive(Debug)] pub enum ServiceError { /// A repository operation failed. Repository(DomainError), /// The provided configuration is invalid. InvalidConfig(String), /// OAuth state mismatch — possible CSRF attack. StateMismatch, /// The OAuth provider returned an error. OAuthProvider(String), /// A generic error with a message. Other(String), } impl From for ServiceError { fn from(err: DomainError) -> Self { ServiceError::Repository(err) } } impl fmt::Display for ServiceError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ServiceError::Repository(err) => write!(f, "repository error: {err}"), ServiceError::InvalidConfig(msg) => write!(f, "invalid configuration: {msg}"), ServiceError::StateMismatch => { write!(f, "OAuth state mismatch — possible CSRF attack") } ServiceError::OAuthProvider(msg) => write!(f, "OAuth provider error: {msg}"), ServiceError::Other(msg) => write!(f, "{msg}"), } } } impl std::error::Error for ServiceError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { ServiceError::Repository(err) => Some(err), _ => None, } } }