Skip to main content

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//! ```rust
149//! use orion_error::protocol::DefaultExposurePolicy;
150//! use orion_error::{StructError, UnifiedReason};
151//!
152//! let proto = StructError::from(UnifiedReason::system_error())
153//!     .exposure(&DefaultExposurePolicy);
154//! let _ = proto.report();
155//! ```
156//!
157//! ```rust,ignore
158//! // This example requires the `derive` feature (enabled by default).
159//! use orion_error::OrionError;
160//! use orion_error::reason::{ErrorCategory, ErrorCode, ErrorIdentityProvider};
161//!
162//! #[derive(Debug, Clone, PartialEq, OrionError)]
163//! enum DemoReason {
164//!     #[orion_error(identity = "logic.demo_reason")]
165//!     Demo,
166//! }
167//!
168//! let reason = DemoReason::Demo;
169//! assert_eq!(reason.error_code(), 500);
170//! assert_eq!(reason.stable_code(), "logic.demo_reason");
171//! assert_eq!(reason.error_category(), ErrorCategory::Logic);
172//! ```
173mod core;
174mod testing;
175mod traits;
176
177extern crate self as orion_error;
178
179#[cfg(feature = "derive")]
180pub use orion_error_derive::{ErrorCode, ErrorIdentityProvider, OrionError};
181
182pub use core::{convert_error, ErrorIdentity, OperationContext, StructError, UnifiedReason};
183
184/// Primary-path traits and types for convenient wildcard imports.
185///
186/// # Example
187/// ```rust,ignore
188/// use orion_error::prelude::*;
189/// ```
190pub mod prelude {
191    pub use crate::core::StructError;
192    pub use crate::traits::{ConvErr, ErrorWith, SourceErr};
193    #[cfg(feature = "derive")]
194    pub use crate::OrionError;
195    pub use crate::UnifiedReason;
196}
197
198/// Runtime-layer types.
199///
200/// These are the primary carriers used while an error is still moving through
201/// application code.
202pub mod runtime {
203    pub use crate::core::{
204        ErrorMetadata, MetadataValue, OperationContext, OperationScope, StructError,
205        StructErrorBuilder, WithContext,
206    };
207
208    /// Source observation models attached to runtime errors.
209    ///
210    /// Keep source payload inspection under this submodule so the top-level
211    /// `runtime::*` surface stays centered on the main carrier and context
212    /// APIs.
213    pub mod source {
214        pub use crate::core::{SourceFrame, SourcePayloadKind, SourcePayloadRef};
215    }
216}
217
218/// Report-layer types for rendering and redaction.
219pub mod report {
220    pub use crate::core::{DiagnosticReport, RedactPolicy};
221}
222
223/// CLI-side output helpers.
224pub mod cli {
225    pub use crate::core::cli::print_error;
226}
227
228/// Standard-error ecosystem interop: bridge types for entering the standard
229/// `std::error::Error` ecosystem.
230///
231/// Provides owned and borrowed wrappers that implement `StdError` and delegate
232/// to the underlying [`StructError`]. Use these when you need to pass an
233/// orion-error through an interface that expects `dyn Error`.
234pub mod interop {
235    pub use crate::core::{OwnedDynStdStructError, OwnedStdStructError, StdStructRef};
236    pub use crate::traits::{raw_source, RawSource, RawStdError};
237}
238
239/// Protocol/exposure-layer types for boundary projections.
240pub mod protocol {
241    pub use crate::core::{
242        DefaultExposurePolicy, ErrorProtocolSnapshot, ExposureDecision, ExposurePolicy, Visibility,
243    };
244}
245
246/// Reason-layer enums and traits.
247pub mod reason {
248    pub use crate::core::{
249        ConfErrReason, DomainReason, ErrorCategory, ErrorCode, ErrorIdentityProvider, UnifiedReason,
250    };
251}
252
253/// Conversion traits for the current primary paths.
254pub mod conversion {
255    pub use crate::traits::{ConvErr, ConvStructError, ErrorWith, SourceErr, ToStructError};
256}
257
258/// Development and validation-only helpers.
259pub mod dev {
260    /// Test assertion helpers and testing-only utility traits.
261    pub mod testing {
262        pub use crate::testing::*;
263    }
264
265    /// Wildcard imports for tests, schema checks, and migration-oriented validation.
266    pub mod prelude {
267        pub use crate::core::{
268            DiagnosticReport, ErrorIdentity, ErrorProtocolSnapshot, ExposureDecision,
269            ExposurePolicy, RedactPolicy, Visibility,
270        };
271        #[cfg(feature = "derive")]
272        pub use crate::OrionError;
273    }
274}