chio_guards/response_sanitization/
types.rs1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum SensitiveCategory {
9 Secret,
10 Pii,
11 Internal,
12 Custom(String),
13}
14
15#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum RedactionStrategy {
19 Mask,
21 Fingerprint,
23 Drop,
26 Tokenize,
28 Partial,
30 TypeLabel,
32 Keep,
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
38pub struct Span {
39 pub start: usize,
40 pub end: usize,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize)]
45pub struct SensitiveDataFinding {
46 pub id: String,
47 pub category: SensitiveCategory,
48 pub data_type: String,
49 pub confidence: f32,
50 pub span: Span,
51 pub preview: String,
52 pub detector: String,
53 pub recommended_action: RedactionStrategy,
54}
55
56#[derive(Clone, Debug, Serialize, Deserialize)]
58pub struct Redaction {
59 pub finding_id: String,
60 pub strategy: RedactionStrategy,
61 pub original_span: Span,
62 pub replacement: String,
63}
64
65#[derive(Clone, Debug, Default, Serialize, Deserialize)]
67pub struct ProcessingStats {
68 pub input_length: usize,
69 pub output_length: usize,
70 pub findings_count: usize,
71 pub redactions_count: usize,
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize)]
76pub struct SanitizationResult {
77 pub sanitized: String,
78 pub was_redacted: bool,
79 pub findings: Vec<SensitiveDataFinding>,
80 pub redactions: Vec<Redaction>,
81 pub stats: ProcessingStats,
82}
83
84#[derive(Clone, Debug, Serialize, Deserialize)]
86pub struct CategoryConfig {
87 pub secrets: bool,
88 pub pii: bool,
89 pub internal: bool,
90}
91
92impl Default for CategoryConfig {
93 fn default() -> Self {
94 Self {
95 secrets: true,
96 pii: true,
97 internal: true,
98 }
99 }
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize)]
104pub struct EntropyConfig {
105 pub enabled: bool,
106 pub threshold: f64,
107 pub min_token_len: usize,
108}
109
110impl Default for EntropyConfig {
111 fn default() -> Self {
112 Self {
113 enabled: true,
114 threshold: 4.5,
115 min_token_len: 16,
116 }
117 }
118}
119
120#[derive(Clone, Debug, Default, Serialize, Deserialize)]
122pub struct AllowlistConfig {
123 pub exact: Vec<String>,
124 pub patterns: Vec<String>,
125}
126
127#[derive(Clone, Debug, Default, Serialize, Deserialize)]
129pub struct DenylistConfig {
130 pub exact: Vec<String>,
131 pub patterns: Vec<String>,
132}
133
134#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct OutputSanitizerConfig {
137 pub categories: CategoryConfig,
138 pub redaction_strategies: HashMap<SensitiveCategory, RedactionStrategy>,
139 pub entropy: EntropyConfig,
140 pub allowlist: AllowlistConfig,
141 pub denylist: DenylistConfig,
142 pub max_input_bytes: usize,
143 pub include_findings: bool,
144}
145
146impl Default for OutputSanitizerConfig {
147 fn default() -> Self {
148 let mut redaction_strategies = HashMap::new();
149 redaction_strategies.insert(SensitiveCategory::Secret, RedactionStrategy::Mask);
150 redaction_strategies.insert(SensitiveCategory::Pii, RedactionStrategy::Partial);
151 redaction_strategies.insert(SensitiveCategory::Internal, RedactionStrategy::TypeLabel);
152 Self {
153 categories: CategoryConfig::default(),
154 redaction_strategies,
155 entropy: EntropyConfig::default(),
156 allowlist: AllowlistConfig::default(),
157 denylist: DenylistConfig::default(),
158 max_input_bytes: 1_000_000,
159 include_findings: true,
160 }
161 }
162}
163
164#[derive(Debug, thiserror::Error)]
165pub enum OutputSanitizerConfigError {
166 #[error("invalid {list_name} regex `{pattern}`: {source}")]
167 InvalidPattern {
168 list_name: &'static str,
169 pattern: String,
170 #[source]
171 source: regex::Error,
172 },
173}
174
175#[derive(Debug, Clone)]
177pub struct SanitizedValue {
178 pub value: serde_json::Value,
179 pub findings: Vec<SensitiveDataFinding>,
180 pub redactions: Vec<Redaction>,
181 pub was_redacted: bool,
182}