use auths_core::error::AuthsErrorInfo;
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SetupError {
#[error("identity already exists: {did}")]
IdentityAlreadyExists {
did: String,
},
#[error("keychain unavailable ({backend}): {reason}")]
KeychainUnavailable {
backend: String,
reason: String,
},
#[error("crypto error: {0}")]
CryptoError(#[source] auths_core::AgentError),
#[error("storage error: {0}")]
StorageError(#[source] crate::error::SdkStorageError),
#[error("git config error: {0}")]
GitConfigError(#[source] crate::ports::git_config::GitConfigError),
#[error("invalid setup config: {0}")]
InvalidSetupConfig(String),
#[error("registration failed: {0}")]
RegistrationFailed(#[source] RegistrationError),
#[error("platform verification failed: {0}")]
PlatformVerificationFailed(String),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum RotationError {
#[error("identity not found at {path}")]
IdentityNotFound {
path: std::path::PathBuf,
},
#[error("key not found: {0}")]
KeyNotFound(String),
#[error("key decryption failed: {0}")]
KeyDecryptionFailed(String),
#[error("KEL history error: {0}")]
KelHistoryFailed(String),
#[error("rotation failed: {0}")]
RotationFailed(String),
#[error(
"rotation event committed to KEL but keychain write failed — manual recovery required: {0}"
)]
PartialRotation(String),
#[error(
"rotation requires a software-backed key; alias '{alias}' is hardware-backed (Secure Enclave) and cannot export the raw key material rotation needs"
)]
HardwareKeyNotRotatable {
alias: String,
},
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum RegistrationError {
#[error("identity already registered at this registry")]
AlreadyRegistered,
#[error("registration quota exceeded — try again later")]
QuotaExceeded,
#[error("network error: {0}")]
NetworkError(#[source] auths_core::ports::network::NetworkError),
#[error("invalid DID format: {did}")]
InvalidDidFormat {
did: String,
},
#[error("identity load error: {0}")]
IdentityLoadError(#[source] auths_id::error::StorageError),
#[error("registry read error: {0}")]
RegistryReadError(#[source] auths_id::storage::registry::backend::RegistryError),
#[error("serialization error: {0}")]
SerializationError(#[source] serde_json::Error),
}
impl From<auths_core::AgentError> for SetupError {
fn from(err: auths_core::AgentError) -> Self {
SetupError::CryptoError(err)
}
}
impl From<RegistrationError> for SetupError {
fn from(err: RegistrationError) -> Self {
SetupError::RegistrationFailed(err)
}
}
impl From<auths_core::ports::network::NetworkError> for RegistrationError {
fn from(err: auths_core::ports::network::NetworkError) -> Self {
RegistrationError::NetworkError(err)
}
}
impl AuthsErrorInfo for SetupError {
fn error_code(&self) -> &'static str {
match self {
Self::IdentityAlreadyExists { .. } => "AUTHS-E5001",
Self::KeychainUnavailable { .. } => "AUTHS-E5002",
Self::CryptoError(e) => e.error_code(),
Self::StorageError(e) => e.error_code(),
Self::GitConfigError(_) => "AUTHS-E5004",
Self::InvalidSetupConfig(_) => "AUTHS-E5007",
Self::RegistrationFailed(e) => e.error_code(),
Self::PlatformVerificationFailed(_) => "AUTHS-E5006",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::IdentityAlreadyExists { .. } => {
Some("Use `auths id show` to inspect the existing identity")
}
Self::KeychainUnavailable { .. } => {
Some("Run `auths doctor` to diagnose keychain issues")
}
Self::CryptoError(e) => e.suggestion(),
Self::StorageError(e) => e.suggestion(),
Self::GitConfigError(_) => {
Some("Ensure Git is configured: git config --global user.name/email")
}
Self::InvalidSetupConfig(_) => Some("Check identity setup configuration parameters"),
Self::RegistrationFailed(e) => e.suggestion(),
Self::PlatformVerificationFailed(_) => Some(
"Platform identity verification failed; check your platform credentials and network connectivity",
),
}
}
}
impl AuthsErrorInfo for RotationError {
fn error_code(&self) -> &'static str {
match self {
Self::IdentityNotFound { .. } => "AUTHS-E5301",
Self::KeyNotFound(_) => "AUTHS-E5302",
Self::KeyDecryptionFailed(_) => "AUTHS-E5303",
Self::KelHistoryFailed(_) => "AUTHS-E5304",
Self::RotationFailed(_) => "AUTHS-E5305",
Self::PartialRotation(_) => "AUTHS-E5306",
Self::HardwareKeyNotRotatable { .. } => "AUTHS-E5307",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::IdentityNotFound { .. } => Some("Run `auths init` to create an identity first"),
Self::KeyNotFound(_) => Some("Run `auths key list` to see available keys"),
Self::KeyDecryptionFailed(_) => Some("Check your passphrase and try again"),
Self::KelHistoryFailed(_) => Some("Run `auths doctor` to check KEL integrity"),
Self::RotationFailed(_) => Some(
"Key rotation failed; verify your current key is accessible with `auths key list`",
),
Self::PartialRotation(_) => {
Some("Re-run the rotation with the same new key to complete the keychain write")
}
Self::HardwareKeyNotRotatable { .. } => Some(
"Hardware-backed keys (Secure Enclave / HSM) cannot be rotated in-place; provision a software-backed identity or rotate by creating a new identity",
),
}
}
}
impl AuthsErrorInfo for RegistrationError {
fn error_code(&self) -> &'static str {
match self {
Self::AlreadyRegistered => "AUTHS-E5401",
Self::QuotaExceeded => "AUTHS-E5402",
Self::NetworkError(e) => e.error_code(),
Self::InvalidDidFormat { .. } => "AUTHS-E5403",
Self::IdentityLoadError(_) => "AUTHS-E5404",
Self::RegistryReadError(_) => "AUTHS-E5405",
Self::SerializationError(_) => "AUTHS-E5406",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::AlreadyRegistered => Some(
"This identity is already registered; use `auths id show` to see registration details",
),
Self::QuotaExceeded => Some("Wait a few minutes and try again"),
Self::NetworkError(e) => e.suggestion(),
Self::InvalidDidFormat { .. } => {
Some("Run `auths doctor` to check local identity data")
}
Self::IdentityLoadError(_) => Some("Run `auths doctor` to check local identity data"),
Self::RegistryReadError(_) => Some("Run `auths doctor` to check local identity data"),
Self::SerializationError(_) => Some("Run `auths doctor` to check local identity data"),
}
}
}