Skip to main content

auths_sdk/domains/agents/
error.rs

1use auths_core::error::AuthsErrorInfo;
2use thiserror::Error;
3
4/// Errors from agent delegation operations (`agents::add` and friends).
5///
6/// An agent is a KERI `dip`-delegated identifier of a root/org identity — the same
7/// engine devices use. These errors mirror the device delegation surface.
8///
9/// Usage:
10/// ```ignore
11/// match agents::add(&ctx, &root_alias, &agent_alias, curve) {
12///     Err(AgentError::AlreadyDelegated { alias }) => { /* key in use */ }
13///     Err(e) => return Err(e.into()),
14///     Ok(result) => { /* agent did:keri */ }
15/// }
16/// ```
17#[derive(Debug, Error)]
18#[non_exhaustive]
19pub enum AgentError {
20    /// The delegating (root/org) identity could not be found in storage.
21    #[error("identity not found: {did}")]
22    IdentityNotFound {
23        /// The DID (or load context) that was not found.
24        did: String,
25    },
26
27    /// A key already exists under the requested agent alias — re-delegating it
28    /// would clobber an existing agent. Choose a fresh `--label`/alias.
29    #[error("an agent key already exists under alias '{alias}'")]
30    AlreadyDelegated {
31        /// The keychain alias already in use.
32        alias: String,
33    },
34
35    /// No agent delegated by this root matches the given DID (or its key is
36    /// missing from the keychain).
37    #[error("agent not found: {did}")]
38    AgentNotFound {
39        /// The agent DID that could not be resolved.
40        did: String,
41    },
42
43    /// The agent has been revoked by the delegator and cannot be rotated.
44    #[error("agent {did} is revoked")]
45    Revoked {
46        /// The revoked agent's DID.
47        did: String,
48    },
49
50    /// The requested agent scope exceeds the delegator's own scope — a delegate's
51    /// authority can only narrow, never widen (subset rule).
52    #[error("requested capability '{capability}' exceeds the delegator's scope")]
53    OutsideDelegatorScope {
54        /// The capability that the delegator does not itself hold.
55        capability: String,
56    },
57
58    /// A cryptographic operation failed (e.g. resolving the root's curve).
59    #[error("crypto error: {0}")]
60    CryptoError(#[source] auths_core::AgentError),
61
62    /// Authoring or anchoring the delegated agent identifier failed.
63    #[error("agent delegation failed: {0}")]
64    DelegationError(#[source] auths_id::error::InitError),
65}
66
67impl From<auths_core::AgentError> for AgentError {
68    fn from(err: auths_core::AgentError) -> Self {
69        AgentError::CryptoError(err)
70    }
71}
72
73impl AuthsErrorInfo for AgentError {
74    fn error_code(&self) -> &'static str {
75        match self {
76            Self::IdentityNotFound { .. } => "AUTHS-E5311",
77            Self::AlreadyDelegated { .. } => "AUTHS-E5312",
78            Self::CryptoError(e) => e.error_code(),
79            Self::DelegationError(_) => "AUTHS-E5313",
80            Self::AgentNotFound { .. } => "AUTHS-E5314",
81            Self::Revoked { .. } => "AUTHS-E5315",
82            Self::OutsideDelegatorScope { .. } => "AUTHS-E5316",
83        }
84    }
85
86    fn suggestion(&self) -> Option<&'static str> {
87        match self {
88            Self::IdentityNotFound { .. } => {
89                Some("Run `auths init` to create a root identity first")
90            }
91            Self::AlreadyDelegated { .. } => {
92                Some("Choose a different --label; run `auths id agent list` to see existing agents")
93            }
94            Self::CryptoError(e) => e.suggestion(),
95            Self::DelegationError(_) => Some(
96                "The agent delegation could not be authored or anchored; check the root identity",
97            ),
98            Self::AgentNotFound { .. } => {
99                Some("Run `auths id agent list` to see the agents this identity has delegated")
100            }
101            Self::Revoked { .. } => {
102                Some("This agent was revoked and cannot be rotated; delegate a new agent instead")
103            }
104            Self::OutsideDelegatorScope { .. } => {
105                Some("Narrow the agent's --scope to a subset of the delegator's own capabilities")
106            }
107        }
108    }
109}