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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// =============================================================================
// Copyright (c) 2025 - 2026 Haixing Hu.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0.
// =============================================================================
//! Immutable policy snapshot for every HTTP redaction context.
use crate::{
DiagnosticBudget,
RedactionPolicy,
};
use super::{
BodyBudget,
HttpRedactionPolicyBuilder,
TextBodyPolicy,
UnkeyedJsonValuePolicy,
UrlPathPolicy,
};
/// Combines independent HTTP field policies, behavior choices, and hard limits.
#[must_use]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HttpRedactionPolicy {
/// Field policy used for HTTP header names and values.
header_policy: RedactionPolicy,
/// Field policy used for URL query and form names and values.
query_policy: RedactionPolicy,
/// Field policy used inside structured HTTP body formats.
body_policy: RedactionPolicy,
/// Visibility choice for non-root URL paths.
url_path_policy: UrlPathPolicy,
/// Visibility choice for opaque UTF-8 text bodies.
text_body_policy: TextBodyPolicy,
/// Visibility choice for JSON scalar values without a field name.
unkeyed_json_value_policy: UnkeyedJsonValuePolicy,
/// Finite parser-input and log-output byte limits.
body_budget: BodyBudget,
/// Finite input and output limits for non-body diagnostics.
diagnostic_budget: DiagnosticBudget,
}
impl HttpRedactionPolicy {
/// Creates a builder without header, query, or body field rules.
///
/// # Returns
///
/// A mutable HTTP policy builder with fail-closed behavior defaults and
/// finite budgets.
#[inline(always)]
pub fn builder() -> HttpRedactionPolicyBuilder {
HttpRedactionPolicyBuilder::new()
}
/// Creates a builder initialized from the current default HTTP policy.
///
/// # Returns
///
/// A mutable HTTP policy builder containing a snapshot of the current
/// default policy.
#[inline(always)]
pub fn builder_from_default() -> HttpRedactionPolicyBuilder {
HttpRedactionPolicyBuilder::from_policy(&Self::default())
}
/// Creates a builder with three mutable copies of `base`.
///
/// # Parameters
///
/// * `base` - Field policy copied for header, query, and body contexts.
///
/// # Returns
///
/// A mutable HTTP policy builder using fail-closed behavior defaults and
/// `base`'s diagnostic budget snapshot.
pub fn builder_from(base: RedactionPolicy) -> HttpRedactionPolicyBuilder {
HttpRedactionPolicyBuilder::from_base_policy(base)
}
/// Creates an immutable HTTP policy from complete builder state.
///
/// # Parameters
///
/// * `header_policy` - Header field-policy snapshot.
/// * `query_policy` - Query and form field-policy snapshot.
/// * `body_policy` - Structured-body field-policy snapshot.
/// * `url_path_policy` - URL path visibility choice.
/// * `text_body_policy` - Opaque text-body visibility choice.
/// * `unkeyed_json_value_policy` - Unkeyed scalar visibility choice.
/// * `body_budget` - Checked body input and output byte limits.
///
/// # Returns
///
/// A complete immutable HTTP policy.
#[inline(always)]
pub(super) fn from_parts(
header_policy: RedactionPolicy,
query_policy: RedactionPolicy,
body_policy: RedactionPolicy,
url_path_policy: UrlPathPolicy,
text_body_policy: TextBodyPolicy,
unkeyed_json_value_policy: UnkeyedJsonValuePolicy,
body_budget: BodyBudget,
) -> Self {
let diagnostic_budget = body_policy.diagnostic_budget();
Self {
header_policy,
query_policy,
body_policy,
url_path_policy,
text_body_policy,
unkeyed_json_value_policy,
body_budget,
diagnostic_budget,
}
}
/// Replaces the non-body diagnostic input and output byte limits.
///
/// # Parameters
///
/// * `diagnostic_budget` - Replacement limits for non-body diagnostics.
///
/// # Returns
///
/// The policy with its diagnostic budget replaced.
#[inline(always)]
pub(super) const fn with_diagnostic_budget(
mut self,
diagnostic_budget: DiagnosticBudget,
) -> Self {
self.diagnostic_budget = diagnostic_budget;
self
}
/// Returns the immutable header-field policy snapshot.
///
/// # Returns
///
/// The policy used for HTTP headers.
#[inline(always)]
pub const fn header_policy(&self) -> &RedactionPolicy {
&self.header_policy
}
/// Returns the immutable query and form field-policy snapshot.
///
/// # Returns
///
/// The policy used for URL query and form fields.
#[inline(always)]
pub const fn query_policy(&self) -> &RedactionPolicy {
&self.query_policy
}
/// Returns the immutable structured-body field-policy snapshot.
///
/// # Returns
///
/// The policy used for fields inside HTTP bodies.
#[inline(always)]
pub const fn body_policy(&self) -> &RedactionPolicy {
&self.body_policy
}
/// Returns the URL path visibility choice.
///
/// # Returns
///
/// The immutable URL path behavior.
#[inline(always)]
pub const fn url_path_policy(&self) -> UrlPathPolicy {
self.url_path_policy
}
/// Returns the opaque text-body visibility choice.
///
/// # Returns
///
/// The immutable text-body behavior.
#[inline(always)]
pub const fn text_body_policy(&self) -> TextBodyPolicy {
self.text_body_policy
}
/// Returns the unkeyed JSON scalar visibility choice.
///
/// # Returns
///
/// The immutable unkeyed JSON behavior.
#[inline(always)]
pub const fn unkeyed_json_value_policy(&self) -> UnkeyedJsonValuePolicy {
self.unkeyed_json_value_policy
}
/// Returns the finite body input and output limits.
///
/// # Returns
///
/// The checked hard body budget.
#[inline(always)]
pub const fn body_budget(&self) -> BodyBudget {
self.body_budget
}
/// Returns the finite diagnostic input and output limits.
///
/// # Returns
///
/// The checked hard diagnostic budget.
#[inline(always)]
pub const fn diagnostic_budget(&self) -> DiagnosticBudget {
self.diagnostic_budget
}
}
impl Default for HttpRedactionPolicy {
/// Creates a fail-closed HTTP policy from the current global field default.
///
/// # Returns
///
/// Three independent default policy snapshots and finite body limits.
#[inline(always)]
fn default() -> Self {
let base = RedactionPolicy::default();
Self::from_parts(
base.clone(),
base.clone(),
base,
UrlPathPolicy::default(),
TextBodyPolicy::default(),
UnkeyedJsonValuePolicy::default(),
BodyBudget::default(),
)
}
}