1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! The klauthed error **kernel**.
//!
//! This crate deliberately holds no error *types* — those live with the domains
//! that raise them (`ConfigError` in `klauthed-core`, `DataError` in
//! `klauthed-data`, …). Instead it defines the shared *contract* every klauthed
//! error implements, so the whole system classifies, codes, and surfaces errors
//! the same way:
//!
//! * [`ErrorCategory`] — coarse classification driving HTTP status / retryability.
//! * [`ErrorCode`] — a stable `domain.reason` code for logs and API responses.
//! * [`DomainError`] — the trait each concrete error type implements.
//!
//! It has zero required dependencies (enable the `serde` feature to serialize
//! codes/categories), so everything can depend on it without pulling weight and
//! without creating cycles: types stay home, only the contract is shared.
//!
//! ```
//! use klauthed_error::{DomainError, ErrorCategory, ErrorCode};
//!
//! #[derive(Debug)]
//! struct WidgetMissing(String);
//! impl std::fmt::Display for WidgetMissing {
//! fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
//! write!(f, "widget {} not found", self.0)
//! }
//! }
//! impl std::error::Error for WidgetMissing {}
//!
//! impl DomainError for WidgetMissing {
//! fn category(&self) -> ErrorCategory { ErrorCategory::NotFound }
//! fn code(&self) -> ErrorCode { ErrorCode::new("widget.not_found") }
//! }
//!
//! let err = WidgetMissing("w-1".into());
//! assert_eq!(err.http_status(), 404);
//! assert!(!err.is_retryable());
//! ```
pub use ErrorCategory;
pub use ErrorCode;
/// The contract every klauthed error type implements.
///
/// Concrete error enums stay in their own crates and implement this to plug into
/// shared handling (HTTP mapping, retry decisions, structured logging). The
/// `category()` answer supplies sensible defaults for [`is_retryable`] and
/// [`http_status`], so most impls only define `category` and `code`.
///
/// [`is_retryable`]: DomainError::is_retryable
/// [`http_status`]: DomainError::http_status