use auths_core::error::AuthsErrorInfo;
use auths_verifier::types::CanonicalDid;
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DeviceError {
#[error("identity not found: {did}")]
IdentityNotFound {
did: String,
},
#[error("device not found: {did}")]
DeviceNotFound {
did: String,
},
#[error("attestation error: {0}")]
AttestationError(#[source] auths_verifier::error::AttestationError),
#[error("device DID mismatch: expected {expected}, got {actual}")]
DeviceDidMismatch {
expected: String,
actual: String,
},
#[error("crypto error: {0}")]
CryptoError(#[source] auths_core::AgentError),
#[error("storage error: {0}")]
StorageError(#[source] crate::error::SdkStorageError),
#[error("anchor error: {0}")]
AnchorError(#[from] auths_id::keri::AnchorError),
#[error("device delegation failed: {0}")]
DelegationError(#[source] auths_id::error::InitError),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum DeviceExtensionError {
#[error("identity not found")]
IdentityNotFound,
#[error("no attestation found for device {device_did}")]
NoAttestationFound {
device_did: CanonicalDid,
},
#[error("device {device_did} is already revoked")]
AlreadyRevoked {
device_did: CanonicalDid,
},
#[error("attestation creation failed: {0}")]
AttestationFailed(#[source] auths_verifier::error::AttestationError),
#[error("storage error: {0}")]
StorageError(#[source] crate::error::SdkStorageError),
#[error("anchor error: {0}")]
AnchorError(#[from] auths_id::keri::AnchorError),
}
impl From<auths_core::AgentError> for DeviceError {
fn from(err: auths_core::AgentError) -> Self {
DeviceError::CryptoError(err)
}
}
impl AuthsErrorInfo for DeviceError {
fn error_code(&self) -> &'static str {
match self {
Self::IdentityNotFound { .. } => "AUTHS-E5101",
Self::DeviceNotFound { .. } => "AUTHS-E5102",
Self::AttestationError(_) => "AUTHS-E5103",
Self::DeviceDidMismatch { .. } => "AUTHS-E5105",
Self::CryptoError(e) => e.error_code(),
Self::StorageError(e) => e.error_code(),
Self::AnchorError(e) => e.error_code(),
Self::DelegationError(_) => "AUTHS-E5106",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::IdentityNotFound { .. } => Some("Run `auths init` to create an identity first"),
Self::DeviceNotFound { .. } => Some("Run `auths device list` to see linked devices"),
Self::AttestationError(_) => Some(
"The attestation operation failed; run `auths device list` to check device status",
),
Self::DeviceDidMismatch { .. } => Some("Check that --device matches the key name"),
Self::CryptoError(e) => e.suggestion(),
Self::StorageError(e) => e.suggestion(),
Self::AnchorError(e) => e.suggestion(),
Self::DelegationError(_) => Some(
"The device delegation could not be authored or anchored; check the root identity",
),
}
}
}
impl AuthsErrorInfo for DeviceExtensionError {
fn error_code(&self) -> &'static str {
match self {
Self::IdentityNotFound => "AUTHS-E5201",
Self::NoAttestationFound { .. } => "AUTHS-E5202",
Self::AlreadyRevoked { .. } => "AUTHS-E5203",
Self::AttestationFailed(_) => "AUTHS-E5204",
Self::StorageError(e) => e.error_code(),
Self::AnchorError(e) => e.error_code(),
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::IdentityNotFound => Some("Run `auths init` to create an identity first"),
Self::NoAttestationFound { .. } => {
Some("Run `auths device link` to create an attestation for this device")
}
Self::AlreadyRevoked { .. } => Some(
"This device has been revoked and cannot be extended; link a new device with `auths device link`",
),
Self::AttestationFailed(_) => {
Some("Failed to create the extension attestation; check key access and try again")
}
Self::StorageError(e) => e.suggestion(),
Self::AnchorError(e) => e.suggestion(),
}
}
}