auths_sdk/domains/identity/
error.rs1use auths_core::error::AuthsErrorInfo;
2use thiserror::Error;
3
4#[derive(Debug, Error)]
15#[non_exhaustive]
16pub enum SetupError {
17 #[error("identity already exists: {did}")]
19 IdentityAlreadyExists {
20 did: String,
22 },
23
24 #[error("keychain unavailable ({backend}): {reason}")]
26 KeychainUnavailable {
27 backend: String,
29 reason: String,
31 },
32
33 #[error("crypto error: {0}")]
35 CryptoError(#[source] auths_core::AgentError),
36
37 #[error("storage error: {0}")]
39 StorageError(#[source] crate::error::SdkStorageError),
40
41 #[error("git config error: {0}")]
43 GitConfigError(#[source] crate::ports::git_config::GitConfigError),
44
45 #[error("invalid setup config: {0}")]
47 InvalidSetupConfig(String),
48
49 #[error("registration failed: {0}")]
51 RegistrationFailed(#[source] RegistrationError),
52
53 #[error("platform verification failed: {0}")]
55 PlatformVerificationFailed(String),
56}
57
58#[derive(Debug, Error)]
69#[non_exhaustive]
70pub enum RotationError {
71 #[error("identity not found at {path}")]
73 IdentityNotFound {
74 path: std::path::PathBuf,
76 },
77
78 #[error("key not found: {0}")]
80 KeyNotFound(String),
81
82 #[error("key decryption failed: {0}")]
84 KeyDecryptionFailed(String),
85
86 #[error("KEL history error: {0}")]
88 KelHistoryFailed(String),
89
90 #[error("rotation failed: {0}")]
92 RotationFailed(String),
93
94 #[error(
97 "rotation event committed to KEL but keychain write failed — manual recovery required: {0}"
98 )]
99 PartialRotation(String),
100
101 #[error(
103 "rotation requires a software-backed key; alias '{alias}' is hardware-backed (Secure Enclave) and cannot export the raw key material rotation needs"
104 )]
105 HardwareKeyNotRotatable {
106 alias: String,
108 },
109}
110
111#[derive(Debug, Error)]
123#[non_exhaustive]
124pub enum RegistrationError {
125 #[error("identity already registered at this registry")]
127 AlreadyRegistered,
128
129 #[error("registration quota exceeded — try again later")]
131 QuotaExceeded,
132
133 #[error("network error: {0}")]
135 NetworkError(#[source] auths_core::ports::network::NetworkError),
136
137 #[error("invalid DID format: {did}")]
139 InvalidDidFormat {
140 did: String,
142 },
143
144 #[error("identity load error: {0}")]
146 IdentityLoadError(#[source] auths_id::error::StorageError),
147
148 #[error("registry read error: {0}")]
150 RegistryReadError(#[source] auths_id::storage::registry::backend::RegistryError),
151
152 #[error("serialization error: {0}")]
154 SerializationError(#[source] serde_json::Error),
155}
156
157impl From<auths_core::AgentError> for SetupError {
158 fn from(err: auths_core::AgentError) -> Self {
159 SetupError::CryptoError(err)
160 }
161}
162
163impl From<RegistrationError> for SetupError {
164 fn from(err: RegistrationError) -> Self {
165 SetupError::RegistrationFailed(err)
166 }
167}
168
169impl From<auths_core::ports::network::NetworkError> for RegistrationError {
170 fn from(err: auths_core::ports::network::NetworkError) -> Self {
171 RegistrationError::NetworkError(err)
172 }
173}
174
175impl AuthsErrorInfo for SetupError {
176 fn error_code(&self) -> &'static str {
177 match self {
178 Self::IdentityAlreadyExists { .. } => "AUTHS-E5001",
179 Self::KeychainUnavailable { .. } => "AUTHS-E5002",
180 Self::CryptoError(e) => e.error_code(),
181 Self::StorageError(e) => e.error_code(),
182 Self::GitConfigError(_) => "AUTHS-E5004",
183 Self::InvalidSetupConfig(_) => "AUTHS-E5007",
184 Self::RegistrationFailed(e) => e.error_code(),
185 Self::PlatformVerificationFailed(_) => "AUTHS-E5006",
186 }
187 }
188
189 fn suggestion(&self) -> Option<&'static str> {
190 match self {
191 Self::IdentityAlreadyExists { .. } => {
192 Some("Use `auths id show` to inspect the existing identity")
193 }
194 Self::KeychainUnavailable { .. } => {
195 Some("Run `auths doctor` to diagnose keychain issues")
196 }
197 Self::CryptoError(e) => e.suggestion(),
198 Self::StorageError(e) => e.suggestion(),
199 Self::GitConfigError(_) => {
200 Some("Ensure Git is configured: git config --global user.name/email")
201 }
202 Self::InvalidSetupConfig(_) => Some("Check identity setup configuration parameters"),
203 Self::RegistrationFailed(e) => e.suggestion(),
204 Self::PlatformVerificationFailed(_) => Some(
205 "Platform identity verification failed; check your platform credentials and network connectivity",
206 ),
207 }
208 }
209}
210
211impl AuthsErrorInfo for RotationError {
212 fn error_code(&self) -> &'static str {
213 match self {
214 Self::IdentityNotFound { .. } => "AUTHS-E5301",
215 Self::KeyNotFound(_) => "AUTHS-E5302",
216 Self::KeyDecryptionFailed(_) => "AUTHS-E5303",
217 Self::KelHistoryFailed(_) => "AUTHS-E5304",
218 Self::RotationFailed(_) => "AUTHS-E5305",
219 Self::PartialRotation(_) => "AUTHS-E5306",
220 Self::HardwareKeyNotRotatable { .. } => "AUTHS-E5307",
221 }
222 }
223
224 fn suggestion(&self) -> Option<&'static str> {
225 match self {
226 Self::IdentityNotFound { .. } => Some("Run `auths init` to create an identity first"),
227 Self::KeyNotFound(_) => Some("Run `auths key list` to see available keys"),
228 Self::KeyDecryptionFailed(_) => Some("Check your passphrase and try again"),
229 Self::KelHistoryFailed(_) => Some("Run `auths doctor` to check KEL integrity"),
230 Self::RotationFailed(_) => Some(
231 "Key rotation failed; verify your current key is accessible with `auths key list`",
232 ),
233 Self::PartialRotation(_) => {
234 Some("Re-run the rotation with the same new key to complete the keychain write")
235 }
236 Self::HardwareKeyNotRotatable { .. } => Some(
237 "Hardware-backed keys (Secure Enclave / HSM) cannot be rotated in-place; provision a software-backed identity or rotate by creating a new identity",
238 ),
239 }
240 }
241}
242
243impl AuthsErrorInfo for RegistrationError {
244 fn error_code(&self) -> &'static str {
245 match self {
246 Self::AlreadyRegistered => "AUTHS-E5401",
247 Self::QuotaExceeded => "AUTHS-E5402",
248 Self::NetworkError(e) => e.error_code(),
249 Self::InvalidDidFormat { .. } => "AUTHS-E5403",
250 Self::IdentityLoadError(_) => "AUTHS-E5404",
251 Self::RegistryReadError(_) => "AUTHS-E5405",
252 Self::SerializationError(_) => "AUTHS-E5406",
253 }
254 }
255
256 fn suggestion(&self) -> Option<&'static str> {
257 match self {
258 Self::AlreadyRegistered => Some(
259 "This identity is already registered; use `auths id show` to see registration details",
260 ),
261 Self::QuotaExceeded => Some("Wait a few minutes and try again"),
262 Self::NetworkError(e) => e.suggestion(),
263 Self::InvalidDidFormat { .. } => {
264 Some("Run `auths doctor` to check local identity data")
265 }
266 Self::IdentityLoadError(_) => Some("Run `auths doctor` to check local identity data"),
267 Self::RegistryReadError(_) => Some("Run `auths doctor` to check local identity data"),
268 Self::SerializationError(_) => Some("Run `auths doctor` to check local identity data"),
269 }
270 }
271}