1#![allow(missing_docs)]
7
8use std::fmt;
9use thiserror::Error;
10
11#[derive(Error, Debug)]
13pub enum EncryptionError {
14 #[error("Invalid key: {message}")]
16 InvalidKey { message: String },
17
18 #[error("Invalid nonce: {message}")]
20 InvalidNonce { message: String },
21
22 #[error("Authentication failed: {message}")]
24 AuthenticationFailed { message: String },
25
26 #[error("Invalid ciphertext: {message}")]
28 InvalidCiphertext { message: String },
29
30 #[error("Key derivation failed: {message}")]
32 KeyDerivationFailed { message: String },
33
34 #[error("Key not found: {key_id}")]
36 KeyNotFound { key_id: String },
37
38 #[error("Access denied: {message}")]
40 AccessDenied { message: String },
41
42 #[error("Key store error: {message}")]
44 KeyStoreError { message: String },
45
46 #[error("Random generation failed: {message}")]
48 RandomGenerationFailed { message: String },
49
50 #[error("Invalid algorithm: {message}")]
52 InvalidAlgorithm { message: String },
53
54 #[error("Cipher operation failed: {message}")]
56 CipherOperationFailed { message: String },
57
58 #[error("Base64 operation failed: {message}")]
60 Base64Error { message: String },
61
62 #[error("Serialization failed: {message}")]
64 SerializationError { message: String },
65
66 #[error("Template processing failed: {message}")]
68 TemplateError { message: String },
69
70 #[error("Auto-encryption configuration error: {message}")]
72 AutoEncryptionConfigError { message: String },
73
74 #[error("Workspace encryption error: {message}")]
76 Workspace { message: String },
77
78 #[error("Encryption error: {message}")]
80 Generic { message: String },
81}
82
83impl EncryptionError {
84 pub fn invalid_key(message: impl Into<String>) -> Self {
86 Self::InvalidKey {
87 message: message.into(),
88 }
89 }
90
91 pub fn invalid_nonce(message: impl Into<String>) -> Self {
93 Self::InvalidNonce {
94 message: message.into(),
95 }
96 }
97
98 pub fn authentication_failed(message: impl Into<String>) -> Self {
100 Self::AuthenticationFailed {
101 message: message.into(),
102 }
103 }
104
105 pub fn invalid_ciphertext(message: impl Into<String>) -> Self {
107 Self::InvalidCiphertext {
108 message: message.into(),
109 }
110 }
111
112 pub fn key_derivation_failed(message: impl Into<String>) -> Self {
114 Self::KeyDerivationFailed {
115 message: message.into(),
116 }
117 }
118
119 pub fn key_not_found(key_id: impl Into<String>) -> Self {
121 Self::KeyNotFound {
122 key_id: key_id.into(),
123 }
124 }
125
126 pub fn access_denied(message: impl Into<String>) -> Self {
128 Self::AccessDenied {
129 message: message.into(),
130 }
131 }
132
133 pub fn key_store_error(message: impl Into<String>) -> Self {
135 Self::KeyStoreError {
136 message: message.into(),
137 }
138 }
139
140 pub fn random_generation_failed(message: impl Into<String>) -> Self {
142 Self::RandomGenerationFailed {
143 message: message.into(),
144 }
145 }
146
147 pub fn invalid_algorithm(message: impl Into<String>) -> Self {
149 Self::InvalidAlgorithm {
150 message: message.into(),
151 }
152 }
153
154 pub fn cipher_operation_failed(message: impl Into<String>) -> Self {
156 Self::CipherOperationFailed {
157 message: message.into(),
158 }
159 }
160
161 pub fn base64_error(message: impl Into<String>) -> Self {
163 Self::Base64Error {
164 message: message.into(),
165 }
166 }
167
168 pub fn serialization_error(message: impl Into<String>) -> Self {
170 Self::SerializationError {
171 message: message.into(),
172 }
173 }
174
175 pub fn template_error(message: impl Into<String>) -> Self {
177 Self::TemplateError {
178 message: message.into(),
179 }
180 }
181
182 pub fn auto_encryption_config_error(message: impl Into<String>) -> Self {
184 Self::AutoEncryptionConfigError {
185 message: message.into(),
186 }
187 }
188
189 pub fn workspace_encryption_error(message: impl Into<String>) -> Self {
191 Self::Workspace {
192 message: message.into(),
193 }
194 }
195
196 pub fn generic(message: impl Into<String>) -> Self {
198 Self::Generic {
199 message: message.into(),
200 }
201 }
202
203 pub fn is_recoverable(&self) -> bool {
205 match self {
206 Self::InvalidKey { .. }
207 | Self::InvalidNonce { .. }
208 | Self::AuthenticationFailed { .. }
209 | Self::InvalidCiphertext { .. }
210 | Self::KeyNotFound { .. }
211 | Self::InvalidAlgorithm { .. }
212 | Self::Base64Error { .. }
213 | Self::SerializationError { .. }
214 | Self::TemplateError { .. }
215 | Self::AutoEncryptionConfigError { .. } => false,
216
217 Self::KeyDerivationFailed { .. }
218 | Self::AccessDenied { .. }
219 | Self::KeyStoreError { .. }
220 | Self::RandomGenerationFailed { .. }
221 | Self::CipherOperationFailed { .. }
222 | Self::Workspace { .. }
223 | Self::Generic { .. } => true,
224 }
225 }
226
227 pub fn severity(&self) -> ErrorSeverity {
229 match self {
230 Self::AuthenticationFailed { .. } | Self::AccessDenied { .. } => {
231 ErrorSeverity::Critical
232 }
233
234 Self::InvalidKey { .. }
235 | Self::InvalidNonce { .. }
236 | Self::InvalidCiphertext { .. }
237 | Self::InvalidAlgorithm { .. } => ErrorSeverity::High,
238
239 Self::KeyDerivationFailed { .. }
240 | Self::KeyStoreError { .. }
241 | Self::RandomGenerationFailed { .. }
242 | Self::CipherOperationFailed { .. } => ErrorSeverity::Medium,
243
244 Self::Base64Error { .. }
245 | Self::SerializationError { .. }
246 | Self::TemplateError { .. }
247 | Self::AutoEncryptionConfigError { .. }
248 | Self::Workspace { .. }
249 | Self::Generic { .. } => ErrorSeverity::Low,
250
251 Self::KeyNotFound { .. } => ErrorSeverity::Info,
252 }
253 }
254}
255
256#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
258pub enum ErrorSeverity {
259 Info,
261 Low,
263 Medium,
265 High,
267 Critical,
269}
270
271pub type EncryptionResult<T> = Result<T, EncryptionError>;
273
274#[derive(Debug, Clone)]
276pub struct ErrorContext {
277 pub operation: String,
279 pub context: HashMap<String, String>,
281 pub timestamp: chrono::DateTime<chrono::Utc>,
283}
284
285impl ErrorContext {
286 pub fn new(operation: impl Into<String>) -> Self {
288 Self {
289 operation: operation.into(),
290 context: HashMap::new(),
291 timestamp: chrono::Utc::now(),
292 }
293 }
294
295 pub fn with_context(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
297 self.context.insert(key.into(), value.into());
298 self
299 }
300}
301
302#[derive(Debug)]
304pub struct ContextualError {
305 pub error: EncryptionError,
307 pub context: ErrorContext,
309}
310
311impl fmt::Display for ContextualError {
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 write!(
314 f,
315 "Encryption error in {} at {}: {} (context: {:?})",
316 self.context.operation, self.context.timestamp, self.error, self.context.context
317 )
318 }
319}
320
321impl std::error::Error for ContextualError {
322 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
323 Some(&self.error)
324 }
325}
326
327#[derive(Debug, Clone)]
329pub enum ErrorRecoveryStrategy {
330 RetryWithBackoff {
332 max_attempts: usize,
334 base_delay_ms: u64,
336 },
337 FallbackMethod,
339 SkipEncryption,
341 ManualIntervention,
343 FailFast,
345}
346
347impl EncryptionError {
348 pub fn suggested_recovery(&self) -> ErrorRecoveryStrategy {
350 match self {
351 Self::RandomGenerationFailed { .. } => ErrorRecoveryStrategy::RetryWithBackoff {
352 max_attempts: 3,
353 base_delay_ms: 100,
354 },
355
356 Self::KeyStoreError { .. } | Self::KeyDerivationFailed { .. } => {
357 ErrorRecoveryStrategy::ManualIntervention
358 }
359
360 Self::AuthenticationFailed { .. } | Self::AccessDenied { .. } => {
361 ErrorRecoveryStrategy::FailFast
362 }
363
364 Self::InvalidKey { .. } | Self::InvalidNonce { .. } => {
365 ErrorRecoveryStrategy::FallbackMethod
366 }
367
368 _ => ErrorRecoveryStrategy::RetryWithBackoff {
369 max_attempts: 2,
370 base_delay_ms: 50,
371 },
372 }
373 }
374
375 pub fn with_context(self, context: ErrorContext) -> ContextualError {
377 ContextualError {
378 error: self,
379 context,
380 }
381 }
382}
383
384use std::collections::HashMap;