Skip to main content

chio_kernel_mobile/
errors.rs

1//! Error surface exposed across the UniFFI boundary.
2//!
3//! Every variant carries a human-readable `message: String` so the
4//! generated Swift / Kotlin code renders a usable error to the host
5//! app without a second lookup. Keeping the payload flat (single
6//! `String` per variant) also keeps the UDL `[Error]` interface
7//! simple.
8
9#![forbid(unsafe_code)]
10
11use core::fmt;
12
13/// Errors raised by the mobile FFI.
14///
15/// The variant names in this enum match the `[Error]` interface in
16/// `chio_kernel_mobile.udl` exactly; UniFFI relies on the name match
17/// to produce the right Swift/Kotlin case for each variant.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum ChioMobileError {
20    /// A JSON argument failed to parse.
21    InvalidJson { message: String },
22    /// A hex-encoded key or seed failed to decode.
23    InvalidHex { message: String },
24    /// A signing seed decoded successfully but is unsafe to use.
25    WeakEntropy { message: String },
26    /// Capability verification (signature, issuer trust, or time
27    /// bounds) failed.
28    InvalidCapability { message: String },
29    /// Portable-passport envelope verification failed.
30    InvalidPassport { message: String },
31    /// Mobile attestation verification has not been provisioned for
32    /// this platform lane yet.
33    AttestationUnavailable { message: String },
34    /// Mobile attestation evidence was present but rejected.
35    AttestationRejected { message: String },
36    /// The receipt body's `kernel_key` did not match the derived
37    /// public key of the provided signing seed. Fail-fast so a
38    /// receipt is never emitted whose embedded key cannot verify
39    /// its own signature.
40    KernelKeyMismatch { message: String },
41    /// The canonical-JSON signing pipeline reported an error.
42    SigningFailed { message: String },
43    /// An `evaluate()` call returned a deny verdict. The message
44    /// carries the kernel-core `deny_reason()`.
45    EvaluationDenied { message: String },
46    /// An internal invariant was violated (canonical-JSON failure,
47    /// unexpected kernel-core error, etc.). Treat as fail-closed.
48    Internal { message: String },
49}
50
51impl ChioMobileError {
52    /// Shared accessor: every variant stores its message in the same slot.
53    pub fn message(&self) -> &str {
54        match self {
55            ChioMobileError::InvalidJson { message }
56            | ChioMobileError::InvalidHex { message }
57            | ChioMobileError::WeakEntropy { message }
58            | ChioMobileError::InvalidCapability { message }
59            | ChioMobileError::InvalidPassport { message }
60            | ChioMobileError::AttestationUnavailable { message }
61            | ChioMobileError::AttestationRejected { message }
62            | ChioMobileError::KernelKeyMismatch { message }
63            | ChioMobileError::SigningFailed { message }
64            | ChioMobileError::EvaluationDenied { message }
65            | ChioMobileError::Internal { message } => message.as_str(),
66        }
67    }
68}
69
70impl fmt::Display for ChioMobileError {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        let tag = match self {
73            ChioMobileError::InvalidJson { .. } => "invalid json",
74            ChioMobileError::InvalidHex { .. } => "invalid hex",
75            ChioMobileError::WeakEntropy { .. } => "weak entropy",
76            ChioMobileError::InvalidCapability { .. } => "invalid capability",
77            ChioMobileError::InvalidPassport { .. } => "invalid passport",
78            ChioMobileError::AttestationUnavailable { .. } => "attestation unavailable",
79            ChioMobileError::AttestationRejected { .. } => "attestation rejected",
80            ChioMobileError::KernelKeyMismatch { .. } => "kernel key mismatch",
81            ChioMobileError::SigningFailed { .. } => "signing failed",
82            ChioMobileError::EvaluationDenied { .. } => "evaluation denied",
83            ChioMobileError::Internal { .. } => "internal",
84        };
85        write!(f, "{tag}: {}", self.message())
86    }
87}
88
89impl std::error::Error for ChioMobileError {}