Skip to main content

rvm_cap/
error.rs

1//! Error types for the capability subsystem.
2//!
3//! [`CapError`] covers table and derivation tree operations.
4//! [`ProofError`] covers the three-layer proof verification (ADR-135).
5
6use core::fmt;
7use rvm_types::RvmError;
8
9/// Errors from capability table and derivation operations.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum CapError {
12    /// The capability handle does not resolve to a valid entry.
13    InvalidHandle,
14    /// The generation counter does not match -- handle is stale.
15    StaleHandle,
16    /// The capability table is full.
17    TableFull,
18    /// The capability has been revoked.
19    Revoked,
20    /// Delegation depth limit exceeded.
21    DelegationDepthExceeded,
22    /// The source capability lacks GRANT rights.
23    GrantNotPermitted,
24    /// Attempted rights escalation (derived rights not a subset of parent).
25    RightsEscalation,
26    /// The derivation tree is full.
27    TreeFull,
28    /// Capability type mismatch.
29    TypeMismatch,
30    /// The capability has been consumed (`GRANT_ONCE`).
31    Consumed,
32}
33
34impl fmt::Display for CapError {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        match self {
37            Self::InvalidHandle => write!(f, "invalid capability handle"),
38            Self::StaleHandle => write!(f, "stale capability handle (generation mismatch)"),
39            Self::TableFull => write!(f, "capability table full"),
40            Self::Revoked => write!(f, "capability revoked"),
41            Self::DelegationDepthExceeded => write!(f, "delegation depth limit exceeded"),
42            Self::GrantNotPermitted => write!(f, "GRANT right not held"),
43            Self::RightsEscalation => write!(f, "rights escalation attempted"),
44            Self::TreeFull => write!(f, "derivation tree full"),
45            Self::TypeMismatch => write!(f, "capability type mismatch"),
46            Self::Consumed => write!(f, "capability consumed (GRANT_ONCE)"),
47        }
48    }
49}
50
51impl From<CapError> for RvmError {
52    fn from(e: CapError) -> Self {
53        match e {
54            CapError::InvalidHandle | CapError::GrantNotPermitted | CapError::RightsEscalation => {
55                RvmError::InsufficientCapability
56            }
57            CapError::StaleHandle | CapError::Revoked => RvmError::StaleCapability,
58            CapError::TableFull | CapError::TreeFull => RvmError::ResourceLimitExceeded,
59            CapError::DelegationDepthExceeded => RvmError::DelegationDepthExceeded,
60            CapError::TypeMismatch => RvmError::CapabilityTypeMismatch,
61            CapError::Consumed => RvmError::CapabilityConsumed,
62        }
63    }
64}
65
66/// Shorthand result type for capability operations.
67pub type CapResult<T> = core::result::Result<T, CapError>;
68
69/// Errors from proof verification (ADR-135 three-layer system).
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum ProofError {
72    /// P1: Handle does not resolve to a valid capability.
73    InvalidHandle,
74    /// P1: Capability epoch does not match (revoked).
75    StaleCapability,
76    /// P1: Capability does not carry the required rights.
77    InsufficientRights,
78    /// P2: One or more structural invariant checks failed.
79    ///
80    /// Deliberately does not specify which check failed to prevent
81    /// timing side-channel leakage (ADR-135).
82    PolicyViolation,
83    /// P3: Deep proof verification not implemented in v1.
84    P3NotImplemented,
85    /// P3: The derivation chain is broken — an ancestor is invalid,
86    /// revoked, or the chain does not terminate at a root.
87    DerivationChainBroken,
88}
89
90impl fmt::Display for ProofError {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        match self {
93            Self::InvalidHandle => write!(f, "P1: invalid capability handle"),
94            Self::StaleCapability => write!(f, "P1: stale capability (epoch mismatch)"),
95            Self::InsufficientRights => write!(f, "P1: insufficient rights"),
96            Self::PolicyViolation => write!(f, "P2: policy violation"),
97            Self::P3NotImplemented => write!(f, "P3: not implemented in v1"),
98            Self::DerivationChainBroken => write!(f, "P3: derivation chain broken"),
99        }
100    }
101}
102
103impl From<ProofError> for RvmError {
104    fn from(e: ProofError) -> Self {
105        match e {
106            ProofError::InvalidHandle | ProofError::InsufficientRights => {
107                RvmError::InsufficientCapability
108            }
109            ProofError::StaleCapability => RvmError::StaleCapability,
110            ProofError::PolicyViolation | ProofError::DerivationChainBroken => {
111                RvmError::ProofInvalid
112            }
113            ProofError::P3NotImplemented => RvmError::Unsupported,
114        }
115    }
116}