//! Core error types for the Acudo application. //! //! This module provides the main error hierarchy and shared error types used //! throughout the application. All error strings follow the standardized format: //! //! ```text //! error-acudo-- :
//! ``` //! //! ## Error Domain Allocation //! //! To ensure globally unique error identifiers, domains are allocated as follows: //! - `config`: 1-99 - Configuration and environment variable errors //! - `http`: 100-199 - HTTP layer and web server errors //! - `storage`: 200-299 - Database and storage errors //! - `auth`: 300-399 - Authentication and authorization errors //! - `event`: 400-499 - Event management and AT Protocol errors //! - `identity`: 500-599 - DID resolution and identity errors //! - `oauth`: 600-699 - OAuth flow and session errors use std::net::AddrParseError; use thiserror::Error; /// Core application errors that can occur across multiple domains. /// /// This enum serves as the main error type for the application, aggregating /// all domain-specific errors into a single hierarchy. #[derive(Debug, Error)] pub enum AcudoError { /// Configuration-related errors (domain: config, range: 1-99) #[error(transparent)] Config(#[from] ConfigError), /// HTTP layer errors (domain: http, range: 100-199) #[error(transparent)] Http(#[from] HttpError), /// Storage and database errors (domain: storage, range: 200-299) #[error(transparent)] Storage(#[from] StorageError), /// Event management errors (domain: event, range: 400-499) #[error(transparent)] Event(#[from] EventError), /// Identity resolution errors (domain: identity, range: 500-599) #[error(transparent)] Identity(#[from] IdentityError), /// OAuth and authentication errors (domain: oauth, range: 600-699) #[error(transparent)] OAuth(#[from] OAuthError), } /// Configuration validation and environment variable errors. /// /// Error domain: `config` (numbers 1-99) #[derive(Error, Debug)] pub enum ConfigError { #[error("error-acudo-config-1 Required environment variable not set: {var_name}")] EnvVarRequired { var_name: String }, #[error("error-acudo-config-2 Failed to parse port: {source}")] PortParsingFailed { #[source] source: std::num::ParseIntError, }, #[error("error-acudo-config-3 Failed to parse nameserver '{nameserver}': {source}")] NameserverParsingFailed { nameserver: String, #[source] source: AddrParseError, }, #[error("error-acudo-config-4 No signing keys provided")] EmptySigningKeys, #[error("error-acudo-config-5 Missing event AT-URI")] MissingEventAturi, #[error("error-acudo-config-6 Invalid event AT-URI format: {aturi}")] InvalidEventAturi { aturi: String }, #[error("error-acudo-config-7 Missing issuer DID")] MissingIssuerDid, #[error("error-acudo-config-8 Invalid issuer DID format: {did}")] InvalidIssuerDid { did: String }, #[error("error-acudo-config-9 Version not set")] VersionNotSet, #[error("error-acudo-config-10 Invalid HTTP configuration: {details}")] InvalidHttpConfig { details: String }, #[error("error-acudo-config-11 Invalid key format: {details}")] InvalidKeyFormat { details: String }, #[error("error-acudo-config-12 Version not available")] VersionNotAvailable, #[error("error-acudo-config-13 Invalid port number: {port}")] InvalidPortNumber { port: String }, #[error("error-acudo-config-14 Invalid IP address: {address}")] InvalidIpAddress { address: String }, #[error("error-acudo-config-15 Invalid timeout value: {value}")] InvalidTimeout { value: String }, #[error("error-acudo-config-16 Invalid AT URI: {uri}")] InvalidAtUri { uri: String }, #[error("error-acudo-config-17 Invalid OAuth backend: {backend}")] InvalidOAuthBackend { backend: String }, #[error("error-acudo-config-18 Invalid DID: {did}")] InvalidDid { did: String }, } /// HTTP layer and web server errors. /// /// Error domain: `http` (numbers 100-199) #[derive(Debug, Error)] pub enum HttpError { #[error("error-acudo-http-100 Unhandled web error: {source}")] Unhandled { #[source] source: anyhow::Error, }, #[error("error-acudo-http-101 Request validation failed: {details}")] RequestValidation { details: String }, #[error("error-acudo-http-102 Authentication required")] AuthenticationRequired, #[error("error-acudo-http-103 Forbidden access to resource")] Forbidden, #[error("error-acudo-http-104 Resource not found")] NotFound, } /// Storage and database operation errors. /// /// Error domain: `storage` (numbers 200-299) #[derive(Debug, Error)] pub enum StorageError { #[error("error-acudo-storage-200 Database connection failed: {source}")] ConnectionFailed { #[source] source: sqlx::Error, }, #[error("error-acudo-storage-201 Transaction failed: {source}")] TransactionFailed { #[source] source: sqlx::Error, }, #[error("error-acudo-storage-202 Query execution failed: {source}")] QueryFailed { #[source] source: sqlx::Error, }, #[error("error-acudo-storage-203 Record not found: {record_type}")] RecordNotFound { record_type: String }, #[error("error-acudo-storage-204 Invalid input data: {details}")] InvalidInput { details: String }, #[error("error-acudo-storage-205 Serialization failed: {source}")] SerializationFailed { #[source] source: anyhow::Error, }, } /// Event management and AT Protocol record errors. /// /// Error domain: `event` (numbers 400-499) #[derive(Debug, Error)] pub enum EventError { #[error("error-acudo-event-400 Invalid AT URI format: {uri}")] InvalidAtUri { uri: String }, #[error("error-acudo-event-401 AT URI must have 3 parts (repo/collection/rkey): {uri}")] MalformedAtUri { uri: String }, #[error("error-acudo-event-402 Failed to fetch AT Protocol record: {source}")] RecordFetchFailed { #[source] source: anyhow::Error, }, #[error("error-acudo-event-403 Failed to parse event record: {source}")] RecordParseFailed { #[source] source: serde_json::Error, }, #[error("error-acudo-event-404 No PDS service endpoint found in DID document: {did}")] NoPdsEndpoint { did: String }, #[error("error-acudo-event-405 Identity resolution failed for DID {did}: {source}")] IdentityResolution { did: String, #[source] source: anyhow::Error, }, #[error("error-acudo-event-406 Failed to fetch record from {uri}: {source}")] RecordFetch { uri: String, #[source] source: anyhow::Error, }, #[error("error-acudo-event-407 Failed to parse event record from {uri}: {source}")] EventParsing { uri: String, #[source] source: anyhow::Error, }, #[error("error-acudo-event-408 Record not found at {uri}: {details}")] RecordNotFound { uri: String, details: String }, } /// Identity resolution and DID processing errors. /// /// Error domain: `identity` (numbers 500-599) #[derive(Debug, Error)] pub enum IdentityError { #[error("error-acudo-identity-500 Failed to resolve DID: {did}")] ResolutionFailed { did: String, #[source] source: anyhow::Error, }, #[error("error-acudo-identity-501 Invalid DID format: {did}")] InvalidDidFormat { did: String }, #[error("error-acudo-identity-502 DID document missing required service: {service_type}")] MissingService { service_type: String }, } /// OAuth flow and session management errors. /// /// Error domain: `oauth` (numbers 600-699) #[derive(Debug, Error)] pub enum OAuthError { #[error("error-acudo-oauth-600 OAuth state cannot be empty")] EmptyState, #[error("error-acudo-oauth-601 Issuer cannot be empty")] EmptyIssuer, #[error("error-acudo-oauth-602 DID cannot be empty")] EmptyDid, #[error("error-acudo-oauth-603 Session chain cannot be empty")] EmptySessionChain, #[error("error-acudo-oauth-604 Access token cannot be empty")] EmptyAccessToken, #[error("error-acudo-oauth-605 OAuth request not found: {state}")] RequestNotFound { state: String }, #[error("error-acudo-oauth-606 OAuth session not found: {session_chain}")] SessionNotFound { session_chain: String }, }