use auths_core::error::AuthsErrorInfo;
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum TrustError {
#[error("Unknown identity '{did}' and trust policy is '{policy}'")]
UnknownIdentity {
did: String,
policy: String,
},
#[error("Failed to resolve public key for identity {did}")]
KeyResolutionFailed {
did: String,
},
#[error("Invalid trust store: {0}")]
InvalidTrustStore(String),
#[error("TOFU trust decision required but running in non-interactive mode")]
TofuRequiresInteraction,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum McpAuthError {
#[error("bridge unreachable: {0}")]
BridgeUnreachable(String),
#[error("token exchange failed (HTTP {status}): {body}")]
TokenExchangeFailed {
status: u16,
body: String,
},
#[error("invalid response: {0}")]
InvalidResponse(String),
#[error("insufficient capabilities: requested {requested:?}")]
InsufficientCapabilities {
requested: Vec<String>,
detail: String,
},
}
impl AuthsErrorInfo for TrustError {
fn error_code(&self) -> &'static str {
match self {
Self::UnknownIdentity { .. } => "AUTHS-E5551",
Self::KeyResolutionFailed { .. } => "AUTHS-E5552",
Self::InvalidTrustStore(_) => "AUTHS-E5553",
Self::TofuRequiresInteraction => "AUTHS-E5554",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::UnknownIdentity { .. } => {
Some("Run `auths trust pin --did <did>` or add the identity to .auths/roots.json")
}
Self::KeyResolutionFailed { .. } => {
Some("Verify the identity exists and has a valid public key registered")
}
Self::InvalidTrustStore(_) => Some(
"Check the format of your trust store (roots.json or ~/.auths/known_identities.json)",
),
Self::TofuRequiresInteraction => {
Some("Run interactively (on a TTY) or use `auths verify --trust explicit`")
}
}
}
}
impl AuthsErrorInfo for McpAuthError {
fn error_code(&self) -> &'static str {
match self {
Self::BridgeUnreachable(_) => "AUTHS-E5501",
Self::TokenExchangeFailed { .. } => "AUTHS-E5502",
Self::InvalidResponse(_) => "AUTHS-E5503",
Self::InsufficientCapabilities { .. } => "AUTHS-E5504",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::BridgeUnreachable(_) => Some("Check network connectivity to the OIDC bridge"),
Self::TokenExchangeFailed { .. } => Some("Verify your credentials and try again"),
Self::InvalidResponse(_) => Some(
"The OIDC bridge returned an unexpected response; verify the bridge URL and try again",
),
Self::InsufficientCapabilities { .. } => {
Some("Request fewer capabilities or contact your administrator")
}
}
}
}