/** * Stable IPC error codes. The renderer maps `errors:native.*` (and other * `errors:` keys that match these dotted paths). Command envelopes may also * still carry a human `error` string for logs. */ pub mod codes { pub const TASK_JOIN: &str = "native.taskJoin"; pub const INVALID_BASE64: &str = "native.invalidBase64"; pub const KNOWN_HOSTS_PATH: &str = "native.knownHostsPath"; pub const INVALID_HOST_KEY_DECISION: &str = "native.invalidHostKeyDecision"; } /// Domain failures retain their cause while exposing stable IPC codes where available. #[derive(Debug, thiserror::Error)] pub enum AppError { #[error(transparent)] Io(#[from] std::io::Error), #[error(transparent)] InvalidBase64(#[from] base64::DecodeError), #[error("{0}")] TaskJoin(String), } impl AppError { pub fn code(&self) -> Option<&'static str> { match self { Self::Io(_) => None, Self::InvalidBase64(_) => Some(codes::INVALID_BASE64), Self::TaskJoin(_) => Some(codes::TASK_JOIN), } } } impl From for crate::domain::ssh::OperationResponse { fn from(error: AppError) -> Self { match error.code() { Some(code) => Self::coded(code, error.to_string()), None => Self::error(error.to_string()), } } }