use thiserror::Error;
use crate::error::AppError;
use crate::operations::did_webvh::UpdateDidWebvhError;
use super::multikey::MultikeyError;
#[derive(Debug, Error)]
pub enum PasskeyVmError {
#[error("passkey enrolment not available: {0}")]
NotAvailable(String),
#[error("unknown or expired ceremony id")]
UnknownCeremony,
#[error("ceremony/DID mismatch")]
CeremonyDidMismatch,
#[error("invalid attestation: {0}")]
InvalidAttestation(String),
#[error("webauthn ceremony failed: {0}")]
WebauthnFinishFailed(String),
#[error("public-key mismatch — browser tampered with the multikey")]
PublicKeyMismatch,
#[error("multikey conversion failed: {0}")]
Multikey(#[from] MultikeyError),
#[error("DID not found or not VTA-managed")]
DidNotFound,
#[error("admin role required")]
PermissionDenied(String),
#[error("passkey verification-method fragment not found")]
FragmentNotFound,
#[error("passkey already enrolled on this DID")]
AlreadyEnrolled,
#[error("verification-method fragment collision: {0}")]
FragmentCollision(String),
#[error(transparent)]
Update(#[from] UpdateDidWebvhError),
#[error("persistence: {0}")]
Persistence(String),
#[error("{0}")]
Internal(String),
}
impl From<PasskeyVmError> for AppError {
fn from(e: PasskeyVmError) -> Self {
match e {
PasskeyVmError::NotAvailable(msg) => AppError::ServiceError {
status: axum::http::StatusCode::SERVICE_UNAVAILABLE,
message: msg,
},
PasskeyVmError::UnknownCeremony => AppError::NotFound("unknown ceremony".into()),
PasskeyVmError::CeremonyDidMismatch => {
AppError::Authentication("ceremony/DID mismatch".into())
}
PasskeyVmError::InvalidAttestation(msg) => AppError::Validation(msg),
PasskeyVmError::WebauthnFinishFailed(msg) => AppError::Authentication(msg),
PasskeyVmError::PublicKeyMismatch => {
AppError::Validation("publicKeyMultibase mismatch".into())
}
PasskeyVmError::Multikey(e) => AppError::Validation(format!("multikey: {e}")),
PasskeyVmError::DidNotFound => AppError::NotFound("DID not managed by this VTA".into()),
PasskeyVmError::PermissionDenied(msg) => AppError::Forbidden(msg),
PasskeyVmError::FragmentNotFound => {
AppError::NotFound("passkey verification-method fragment not found".into())
}
PasskeyVmError::AlreadyEnrolled => {
AppError::Conflict("passkey already enrolled".into())
}
PasskeyVmError::FragmentCollision(msg) => AppError::Conflict(msg),
PasskeyVmError::Update(e) => AppError::from(e),
PasskeyVmError::Persistence(msg) => AppError::Internal(msg),
PasskeyVmError::Internal(msg) => AppError::Internal(msg),
}
}
}