1use auths_core::error::AuthsErrorInfo;
2use thiserror::Error;
3
4#[derive(Debug, Error)]
16#[non_exhaustive]
17pub enum OrgError {
18 #[error("no admin with the given public key found in organization '{org}'")]
20 AdminNotFound {
21 org: String,
23 },
24
25 #[error("member '{did}' not found in organization '{org}'")]
27 MemberNotFound {
28 org: String,
30 did: String,
32 },
33
34 #[error("member '{did}' is already revoked")]
36 AlreadyRevoked {
37 did: String,
39 },
40
41 #[error("invalid capability '{cap}': {reason}")]
43 InvalidCapability {
44 cap: String,
46 reason: String,
48 },
49
50 #[error("invalid organization DID: {0}")]
52 InvalidDid(String),
53
54 #[error("invalid public key: {0}")]
56 InvalidPublicKey(String),
57
58 #[error("signing error: {0}")]
60 Signing(String),
61
62 #[error("identity error: {0}")]
64 Identity(String),
65
66 #[error("key storage error: {0}")]
68 KeyStorage(String),
69
70 #[error("storage error: {0}")]
72 Storage(#[source] auths_id::storage::registry::backend::RegistryError),
73
74 #[error("anchor error: {0}")]
76 Anchor(#[from] auths_id::keri::AnchorError),
77
78 #[error(
82 "organization '{org}' uses a multi-signature controller (kt≥2); KERI-native member delegation requires a single-signature (kt=1) org"
83 )]
84 OrgThresholdDelegationUnsupported {
85 org: String,
87 },
88
89 #[error("a member key already exists under alias '{alias}'")]
92 MemberKeyExists {
93 alias: String,
95 },
96
97 #[error("member '{did}' is not a delegated identifier of organization '{org}'")]
101 MemberNotDelegable {
102 did: String,
104 org: String,
106 },
107
108 #[error("crypto error: {0}")]
110 CryptoError(#[source] auths_core::AgentError),
111
112 #[error("member delegation failed: {0}")]
114 Delegation(#[source] auths_id::error::InitError),
115
116 #[error("an identity already exists at {location}; refusing to create an organization over it")]
119 IdentityExists {
120 location: String,
122 },
123
124 #[error("failed to initialize organization identity: {0}")]
126 IdentityInit(#[source] auths_id::error::InitError),
127
128 #[error("failed to create admin attestation: {0}")]
130 Attestation(#[source] auths_verifier::error::AttestationError),
131
132 #[error(transparent)]
136 Bundle(#[from] auths_verifier::org_bundle::OrgBundleError),
137
138 #[error("invalid org policy: {reason}")]
142 PolicyCompile {
143 reason: String,
145 },
146
147 #[error("invalid OIDC-subject policy: {reason}")]
151 OidcPolicyInvalid {
152 reason: String,
154 },
155
156 #[error("org policy blob for hash '{hash}' is missing from storage")]
159 PolicyBlobMissing {
160 hash: String,
162 },
163
164 #[error(
167 "org policy integrity failure: KEL committed hash '{expected}' but the stored blob hashes to '{actual}'"
168 )]
169 PolicyIntegrity {
170 expected: String,
172 actual: String,
174 },
175
176 #[error("delegation chain cycle detected at '{did}'")]
179 ChainCycle {
180 did: String,
182 },
183
184 #[error("delegation chain exceeds the maximum depth of {max} hops")]
186 ChainTooDeep {
187 max: u32,
189 },
190
191 #[error("delegation chain is broken: no KEL found for '{did}'")]
194 ChainBrokenHop {
195 did: String,
197 },
198}
199
200impl AuthsErrorInfo for OrgError {
201 fn error_code(&self) -> &'static str {
202 match self {
203 Self::AdminNotFound { .. } => "AUTHS-E5601",
204 Self::MemberNotFound { .. } => "AUTHS-E5602",
205 Self::AlreadyRevoked { .. } => "AUTHS-E5603",
206 Self::InvalidCapability { .. } => "AUTHS-E5604",
207 Self::InvalidDid(_) => "AUTHS-E5605",
208 Self::InvalidPublicKey(_) => "AUTHS-E5606",
209 Self::Signing(_) => "AUTHS-E5607",
210 Self::Identity(_) => "AUTHS-E5608",
211 Self::KeyStorage(_) => "AUTHS-E5609",
212 Self::Storage(_) => "AUTHS-E5610",
213 Self::Anchor(_) => "AUTHS-E5611",
214 Self::OrgThresholdDelegationUnsupported { .. } => "AUTHS-E5612",
215 Self::MemberKeyExists { .. } => "AUTHS-E5613",
216 Self::MemberNotDelegable { .. } => "AUTHS-E5618",
217 Self::CryptoError(e) => e.error_code(),
218 Self::Delegation(_) => "AUTHS-E5614",
219 Self::IdentityExists { .. } => "AUTHS-E5615",
220 Self::IdentityInit(_) => "AUTHS-E5616",
221 Self::Attestation(_) => "AUTHS-E5617",
222 Self::Bundle(e) => e.error_code(),
223 Self::PolicyCompile { .. } => "AUTHS-E5622",
224 Self::OidcPolicyInvalid { .. } => "AUTHS-E5628",
225 Self::PolicyBlobMissing { .. } => "AUTHS-E5623",
226 Self::PolicyIntegrity { .. } => "AUTHS-E5624",
227 Self::ChainCycle { .. } => "AUTHS-E5625",
228 Self::ChainTooDeep { .. } => "AUTHS-E5626",
229 Self::ChainBrokenHop { .. } => "AUTHS-E5627",
230 }
231 }
232
233 fn suggestion(&self) -> Option<&'static str> {
234 match self {
235 Self::AdminNotFound { .. } => {
236 Some("Verify you are using the correct admin key for this organization")
237 }
238 Self::MemberNotFound { .. } => {
239 Some("Run `auths org list-members` to see current members")
240 }
241 Self::AlreadyRevoked { .. } => {
242 Some("This member has already been revoked from the organization")
243 }
244 Self::InvalidCapability { .. } => {
245 Some("Use a valid capability (e.g., 'sign_commit', 'manage_members', 'admin')")
246 }
247 Self::InvalidDid(_) => Some("Organization DIDs must be valid did:keri identifiers"),
248 Self::InvalidPublicKey(_) => Some("Public keys must be hex-encoded Ed25519 keys"),
249 Self::Signing(_) => {
250 Some("The signing operation failed; check your key access with `auths key list`")
251 }
252 Self::Identity(_) => {
253 Some("Failed to load identity; run `auths id show` to check identity status")
254 }
255 Self::KeyStorage(_) => {
256 Some("Failed to access key storage; run `auths doctor` to diagnose")
257 }
258 Self::Storage(_) => {
259 Some("Failed to access organization storage; check repository permissions")
260 }
261 Self::Anchor(_) => Some("KEL anchoring failed; check identity and registry state"),
262 Self::OrgThresholdDelegationUnsupported { .. } => Some(
263 "Multi-signature org anchoring is not yet supported; use a single-signature (kt=1) org",
264 ),
265 Self::MemberKeyExists { .. } => Some(
266 "Choose a different member alias; run `auths org list-members` to see existing members",
267 ),
268 Self::MemberNotDelegable { .. } => Some(
269 "The member must first incept a delegated identity naming this org as delegator (pairing) before it can be off-boarded",
270 ),
271 Self::CryptoError(e) => e.suggestion(),
272 Self::Delegation(_) => Some(
273 "The member delegation could not be authored or anchored; check the org identity",
274 ),
275 Self::IdentityExists { .. } => Some(
276 "An identity already exists here; use a fresh repository path to create a new organization",
277 ),
278 Self::IdentityInit(_) => {
279 Some("Failed to initialize the org identity; check key access and repository state")
280 }
281 Self::Attestation(_) => Some(
282 "Failed to sign the admin attestation; check your key access with `auths key list`",
283 ),
284 Self::Bundle(e) => e.suggestion(),
285 Self::PolicyCompile { .. } => Some(
286 "Fix the policy JSON (a serialized `Expr`); see `auths org policy show` for the current policy",
287 ),
288 Self::OidcPolicyInvalid { .. } => Some(
289 "Fix the OIDC-subject policy JSON (issuer + repository, optional workflow_ref); nothing was anchored",
290 ),
291 Self::PolicyBlobMissing { .. } => {
292 Some("The policy blob is missing; re-anchor it with `auths org policy set`")
293 }
294 Self::PolicyIntegrity { .. } => Some(
295 "The stored policy was modified after anchoring; re-anchor a trusted policy with `auths org policy set`",
296 ),
297 Self::ChainCycle { .. } => {
298 Some("The delegation chain is malformed (a cycle); inspect the identifiers' KELs")
299 }
300 Self::ChainTooDeep { .. } => {
301 Some("The delegation chain is too deep; reduce delegation nesting")
302 }
303 Self::ChainBrokenHop { .. } => Some(
304 "A KEL in the delegation chain is missing; ensure all delegators' KELs are present",
305 ),
306 }
307 }
308}