Skip to main content

enfinitos_auditor/
errors.rs

1//! Typed error envelope. Mirrors the TS/Py shape: audit failures stay
2//! inside the report; operational errors raise this type.
3
4use crate::types::AuditReasonCode;
5use thiserror::Error;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum AuditorErrorCode {
9    InvalidInput,
10    KeysUnavailable,
11    KeysMalformed,
12    PlatformResponse,
13    Internal,
14}
15
16impl AuditorErrorCode {
17    pub fn as_str(&self) -> &'static str {
18        match self {
19            AuditorErrorCode::InvalidInput => "INVALID_INPUT",
20            AuditorErrorCode::KeysUnavailable => "KEYS_UNAVAILABLE",
21            AuditorErrorCode::KeysMalformed => "KEYS_MALFORMED",
22            AuditorErrorCode::PlatformResponse => "PLATFORM_RESPONSE",
23            AuditorErrorCode::Internal => "INTERNAL",
24        }
25    }
26}
27
28/// Raised only for operational failures the SDK could not reduce to a
29/// structured AuditReport step.
30#[derive(Debug, Error)]
31#[error("{message}")]
32pub struct AuditorError {
33    pub code: AuditorErrorCode,
34    pub message: String,
35    pub reason: Option<AuditReasonCode>,
36    pub detail: Option<serde_json::Value>,
37}
38
39impl AuditorError {
40    pub fn invalid_input(message: impl Into<String>) -> Self {
41        Self {
42            code: AuditorErrorCode::InvalidInput,
43            message: message.into(),
44            reason: None,
45            detail: None,
46        }
47    }
48
49    pub fn with_reason(mut self, reason: AuditReasonCode) -> Self {
50        self.reason = Some(reason);
51        self
52    }
53
54    pub fn with_detail(mut self, detail: serde_json::Value) -> Self {
55        self.detail = Some(detail);
56        self
57    }
58
59    pub fn keys_malformed(message: impl Into<String>) -> Self {
60        Self {
61            code: AuditorErrorCode::KeysMalformed,
62            message: message.into(),
63            reason: None,
64            detail: None,
65        }
66    }
67
68    pub fn keys_unavailable(message: impl Into<String>) -> Self {
69        Self {
70            code: AuditorErrorCode::KeysUnavailable,
71            message: message.into(),
72            reason: None,
73            detail: None,
74        }
75    }
76
77    pub fn platform_response(message: impl Into<String>) -> Self {
78        Self {
79            code: AuditorErrorCode::PlatformResponse,
80            message: message.into(),
81            reason: None,
82            detail: None,
83        }
84    }
85
86    pub fn internal(message: impl Into<String>) -> Self {
87        Self {
88            code: AuditorErrorCode::Internal,
89            message: message.into(),
90            reason: None,
91            detail: None,
92        }
93    }
94}
95
96impl From<serde_json::Error> for AuditorError {
97    fn from(e: serde_json::Error) -> Self {
98        AuditorError::invalid_input(format!("JSON parse error: {e}"))
99    }
100}