orion_error/lib.rs
1//! # orion-error — structured error governance for large Rust codebases
2//!
3//! ## Decision flow
4//!
5//! When you have an error, the question is: **what do you need to do with it?**
6//!
7//! ```text
8//! ┌─ I have an error ──────────────────────────────────────────┐
9//! │ │
10//! │ Need to print it for a human? │
11//! │ → err.report().render() │
12//! │ │
13//! │ Need to return it to an HTTP/RPC/CLI boundary? │
14//! │ → err.exposure(&policy).to_http_error_json() │
15//! │ → err.exposure(&policy).to_rpc_error_json() │
16//! │ → err.exposure(&policy).to_cli_error_json() │
17//! │ │
18//! │ Need to bridge to std::error::Error? │
19//! │ → err.as_std() / err.into_std() / err.into_dyn_std() │
20//! │ │
21//! │ Just need to log and move on? │
22//! │ → err.display_chain() │
23//! │ → cli::print_error(&err) │
24//! └─────────────────────────────────────────────────────────────┘
25//! ```
26//!
27//! The key boundary:
28//!
29//! - [`StructError::report()`] gives you a [`DiagnosticReport`] — human diagnostics,
30//! redaction, text rendering. Only requires [`reason::DomainReason`].
31//! - [`StructError::exposure()`] gives you an [`ErrorProtocolSnapshot`] —
32//! identity + exposure decision + report, the unified protocol input.
33//! Requires [`reason::DomainReason`] + [`reason::ErrorIdentityProvider`].
34//!
35//! If you only have [`reason::DomainReason`], you can always `report()`. If you
36//! also implement [`reason::ErrorIdentityProvider`] (via `#[derive(OrionError)]`),
37//! you can use `exposure()` and the full protocol projection stack.
38//!
39//! Module split:
40//!
41//! - [`report`] is the human-facing diagnostics layer
42//! - [`protocol`] is the protocol/exposure projection layer
43//!
44//! Root-surface guardrails:
45//!
46//! - derive macros stay importable from the crate root
47//! - runtime identity traits live under [`reason`]
48//! - removed root trait/type re-exports and old extension modules must not drift back
49//!
50//! ```compile_fail
51//! use orion_error::DomainReason;
52//! ```
53//!
54//! ```compile_fail
55//! use orion_error::ErrorCode;
56//!
57//! trait NeedsRootTrait: ErrorCode {}
58//! ```
59//!
60//! ```compile_fail
61//! use orion_error::ErrorIdentityProvider;
62//!
63//! fn accepts_root_trait<T: ErrorIdentityProvider>(_value: &T) {}
64//! ```
65//!
66//! ```compile_fail
67//! use orion_error::bridge::*;
68//! ```
69//!
70//! ```compile_fail
71//! use orion_error::testing::*;
72//! ```
73//!
74//! ```compile_fail
75//! use orion_error::test_prelude::*;
76//! ```
77//!
78//! ```compile_fail
79//! use orion_error::ErrorWith;
80//! ```
81//!
82//! ```compile_fail
83//! use orion_error::ErrorWrapAs;
84//! ```
85//!
86//! ```compile_fail
87//! use orion_error::IntoAs;
88//! ```
89//!
90//! ```compile_fail
91//! use orion_error::{StructError, UnifiedReason};
92//!
93//! let _ = StructError::from(UnifiedReason::system_error())
94//! .attach_source(std::io::Error::other("disk offline"));
95//! ```
96//!
97//! ```compile_fail
98//! use orion_error::types::ErrorIdentity;
99//! ```
100//!
101//! ```compile_fail
102//! use orion_error::DefaultExposurePolicy;
103//! ```
104//!
105//! ```compile_fail
106//! use orion_error::traits_ext::*;
107//! ```
108//!
109//! ```compile_fail
110//! use orion_error::{StructError, UnifiedReason};
111//!
112//! let report = StructError::from(UnifiedReason::system_error()).report();
113//! let _ = report.projection;
114//! ```
115//!
116//! ```compile_fail
117//! use orion_error::report::print_error;
118//! ```
119//!
120//! ```compile_fail
121//! use orion_error::{StructError, UnifiedReason};
122//!
123//! let report = StructError::from(UnifiedReason::system_error()).report();
124//! let _ = report.path();
125//! ```
126//!
127//! ```compile_fail
128//! use orion_error::{StructError, UnifiedReason};
129//!
130//! let report = StructError::from(UnifiedReason::system_error()).report();
131//! let _ = report.root_metadata();
132//! ```
133//!
134//! ```compile_fail
135//! use orion_error::{StructError, UnifiedReason};
136//!
137//! let report = StructError::from(UnifiedReason::system_error()).report();
138//! let _ = report.source_frames();
139//! ```
140//!
141//! ```compile_fail
142//! use orion_error::{OperationContext, StructError, UnifiedReason};
143//!
144//! let _ = OperationContext::doing("load config").target();
145//! let _ = StructError::from(UnifiedReason::system_error()).target_main();
146//! ```
147//!
148//! ```compile_fail
149//! // `AutoLogGuard` is a non-`Clone` drop guard: cloning the drop-time log
150//! // side effect is the bug this type exists to prevent (issue #64).
151//! use orion_error::runtime::AutoLogGuard;
152//!
153//! fn requires_clone<T: Clone>() {}
154//! requires_clone::<AutoLogGuard>();
155//! ```
156//!
157//! ```rust
158//! use orion_error::protocol::DefaultExposurePolicy;
159//! use orion_error::{StructError, UnifiedReason};
160//!
161//! let proto = StructError::from(UnifiedReason::system_error())
162//! .exposure(&DefaultExposurePolicy);
163//! let _ = proto.report();
164//! ```
165//!
166//! ```rust,ignore
167//! // This example requires the `derive` feature (enabled by default).
168//! use orion_error::OrionError;
169//! use orion_error::reason::{ErrorCategory, ErrorCode, ErrorIdentityProvider};
170//!
171//! #[derive(Debug, Clone, PartialEq, OrionError)]
172//! enum DemoReason {
173//! #[orion_error(identity = "logic.demo_reason")]
174//! Demo,
175//! }
176//!
177//! let reason = DemoReason::Demo;
178//! assert_eq!(reason.error_code(), 500);
179//! assert_eq!(reason.stable_code(), "logic.demo_reason");
180//! assert_eq!(reason.error_category(), ErrorCategory::Logic);
181//! ```
182mod core;
183mod testing;
184mod traits;
185
186extern crate self as orion_error;
187
188#[cfg(feature = "derive")]
189pub use orion_error_derive::{ErrorCode, ErrorIdentityProvider, OrionError};
190
191pub use core::{convert_error, ErrorIdentity, OperationContext, StructError, UnifiedReason};
192
193/// Primary-path traits and types for convenient wildcard imports.
194///
195/// # Example
196/// ```rust,ignore
197/// use orion_error::prelude::*;
198/// ```
199pub mod prelude {
200 pub use crate::core::StructError;
201 pub use crate::traits::{ConvErr, ErrorWith, SourceErr, SourceRawErr};
202 #[cfg(feature = "derive")]
203 pub use crate::OrionError;
204 pub use crate::UnifiedReason;
205}
206
207/// Runtime-layer types.
208///
209/// These are the primary carriers used while an error is still moving through
210/// application code.
211pub mod runtime {
212 pub use crate::core::{
213 AutoLogGuard, ErrorMetadata, MetadataValue, OperationContext, OperationScope, StructError,
214 StructErrorBuilder, WithContext,
215 };
216
217 /// Source observation models attached to runtime errors.
218 ///
219 /// Keep source payload inspection under this submodule so the top-level
220 /// `runtime::*` surface stays centered on the main carrier and context
221 /// APIs.
222 pub mod source {
223 pub use crate::core::{SourceFrame, SourcePayloadKind, SourcePayloadRef};
224 }
225}
226
227/// Report-layer types for rendering and redaction.
228pub mod report {
229 pub use crate::core::{DiagnosticReport, RedactPolicy};
230}
231
232/// CLI-side output helpers.
233pub mod cli {
234 pub use crate::core::cli::print_error;
235}
236
237/// Standard-error ecosystem interop: bridge types for entering the standard
238/// `std::error::Error` ecosystem.
239///
240/// Provides owned and borrowed wrappers that implement `StdError` and delegate
241/// to the underlying [`StructError`]. Use these when you need to pass an
242/// orion-error through an interface that expects `dyn Error`.
243pub mod interop {
244 pub use crate::core::{OwnedDynStdStructError, OwnedStdStructError, StdStructRef};
245 pub use crate::traits::{any_err, raw_source, AnyErr, RawSource, RawStdError};
246}
247
248/// Protocol/exposure-layer types for boundary projections.
249pub mod protocol {
250 pub use crate::core::{
251 DefaultExposurePolicy, ErrorProtocolSnapshot, ExposureDecision, ExposurePolicy, Visibility,
252 };
253}
254
255/// Reason-layer enums and traits.
256pub mod reason {
257 pub use crate::core::{
258 ConfErrReason, DomainReason, ErrorCategory, ErrorCode, ErrorIdentityProvider, UnifiedReason,
259 };
260}
261
262/// Conversion traits for the current primary paths.
263pub mod conversion {
264 pub use crate::traits::{
265 ConvErr, ConvStructError, ErrorWith, SourceErr, SourceRawErr, ToStructError,
266 };
267}
268
269/// Development and validation-only helpers.
270pub mod dev {
271 /// Test assertion helpers and testing-only utility traits.
272 pub mod testing {
273 pub use crate::testing::*;
274 }
275
276 /// Wildcard imports for tests, schema checks, and migration-oriented validation.
277 pub mod prelude {
278 pub use crate::core::{
279 DiagnosticReport, ErrorIdentity, ErrorProtocolSnapshot, ExposureDecision,
280 ExposurePolicy, RedactPolicy, Visibility,
281 };
282 #[cfg(feature = "derive")]
283 pub use crate::OrionError;
284 }
285}