Skip to main content

redaction/
lib.rs

1//! Type-directed redaction for structured data.
2//!
3//! This crate separates:
4//! - **Classification**: what kind of sensitive data this is.
5//! - **Policy**: how that data should be redacted.
6//!
7//! The derive macro walks your data and applies the policy at the boundary when
8//! you call `redact()` or `Redactable::redact()`.
9//!
10//! Key rules:
11//! - Use `#[sensitive(Classification)]` for string-like leaf values.
12//! - Use `#[sensitive]` for scalars and nested `Sensitive` types.
13//! - Unannotated fields pass through unchanged.
14//! - `Debug` always prints `"[REDACTED]"` for sensitive fields; policies apply only
15//!   when calling `.redact()`.
16//!
17//! Boxed trait objects:
18//! - `#[sensitive]` supports `Box<dyn Trait>` by calling `redact_boxed`.
19//! - Detection is conservative and only matches the simple `Box<dyn Trait>` syntax,
20//!   not qualified paths or type aliases.
21//!
22//! What this crate does:
23//! - defines classification marker types and the [`Classification`] trait
24//! - defines redaction policies and the `redact` entrypoint
25//! - provides integrations behind feature flags (e.g. `slog`)
26//!
27//! What it does not do:
28//! - perform I/O or logging
29//! - validate your policy choices
30//!
31//! The `Sensitive` derive macro lives in `redaction-derive` and is re-exported when
32//! the `derive` feature is enabled.
33
34// <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
35#![warn(
36    anonymous_parameters,
37    bare_trait_objects,
38    elided_lifetimes_in_paths,
39    missing_copy_implementations,
40    rust_2018_idioms,
41    trivial_casts,
42    trivial_numeric_casts,
43    unreachable_pub,
44    unsafe_code,
45    unused_extern_crates,
46    unused_import_braces
47)]
48// <https://rust-lang.github.io/rust-clippy/stable>
49#![warn(
50    clippy::all,
51    clippy::cargo,
52    clippy::dbg_macro,
53    clippy::float_cmp_const,
54    clippy::get_unwrap,
55    clippy::mem_forget,
56    clippy::nursery,
57    clippy::pedantic,
58    clippy::todo,
59    clippy::unwrap_used,
60    clippy::uninlined_format_args
61)]
62// Allow some clippy lints
63#![allow(
64    clippy::default_trait_access,
65    clippy::doc_markdown,
66    clippy::if_not_else,
67    clippy::module_name_repetitions,
68    clippy::multiple_crate_versions,
69    clippy::must_use_candidate,
70    clippy::needless_pass_by_value,
71    clippy::needless_ifs,
72    clippy::use_self,
73    clippy::cargo_common_metadata,
74    clippy::missing_errors_doc,
75    clippy::enum_glob_use,
76    clippy::struct_excessive_bools,
77    clippy::missing_const_for_fn,
78    clippy::redundant_pub_crate,
79    clippy::result_large_err,
80    clippy::future_not_send,
81    clippy::option_if_let_else,
82    clippy::from_over_into,
83    clippy::manual_inspect
84)]
85// Allow some lints while testing
86#![cfg_attr(test, allow(clippy::non_ascii_literal, clippy::unwrap_used))]
87
88pub use redaction_derive::{Sensitive, SensitiveError};
89
90#[allow(unused_extern_crates)]
91extern crate self as redact;
92
93// Module declarations
94#[cfg(feature = "classification")]
95mod classification;
96#[cfg(feature = "policy")]
97mod redaction;
98#[cfg(feature = "slog")]
99pub mod slog;
100
101// Re-exports
102#[cfg(feature = "classification")]
103pub use classification::{
104    AccountId, BlockchainAddress, Classification, CreditCard, DateOfBirth, Email, IpAddress,
105    NationalId, PhoneNumber, Pii, Secret, SessionId, Token,
106};
107#[cfg(feature = "policy")]
108pub use redaction::{
109    apply_classification, redact, redact_boxed, KeepConfig, MaskConfig, Redactable,
110    RedactableBoxed, RedactionPolicy, ScalarRedaction, SensitiveValue, TextRedactionPolicy,
111    REDACTED_PLACEHOLDER,
112};
113#[doc(hidden)]
114#[cfg(feature = "policy")]
115pub use redaction::{Classifiable, RedactionMapper, SensitiveType};