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
//! Secret swapping and streaming restoration for arbitrary byte payloads.
//!
//! `doppel` intercepts secrets in outbound payloads, replaces them with
//! structurally-equivalent fakes, and restores the originals in streaming responses.
//!
//! Three operations form the core workflow:
//!
//! 1. **[`swap`]** — scan a payload for secrets matching the supplied [`Pattern`]s,
//! replace each with a fake, and return the swapped payload, encrypted entries,
//! and a session key.
//! 2. **Transmit** — send the swapped payload to the external service. Hold the
//! entries and session key locally.
//! 3. **[`restore`]** — stream the response through the restore function, which
//! replaces fakes with originals using the session key and entries.
//!
//! # Quick start
//!
//! ```rust
//! use doppel::{swap, restore, patterns};
//!
//! // NOT real credentials — synthetic key matching the Anthropic structural pattern
//! let payload = b"Authorization: sk-ant-api03-w8bVJRHra9S96i3ios_XhbLgzEBjS6qjPUEgiPrWjN2OeICCY1lwhK3Z35Z_jM89STjqSOxHh6GWGkG2R7uv-AohQLmK9AA";
//!
//! // 1. Swap: detect and replace the key before sending to an external service
//! // Note: `patterns::all()` uses ephemeral salts — fakes differ across process restarts.
//! // For persistent fake stability, use `SecretsFile::to_patterns()`.
//! let result = swap(payload, &patterns::all()).unwrap();
//! assert_eq!(result.entries.len(), 1); // one secret detected
//! assert_ne!(result.payload.as_slice(), payload as &[u8]); // key replaced with a fake
//!
//! // result.payload — send to external service (key replaced with a fake)
//! // result.entries — keep locally; needed to restore secrets in the response
//! // result.session_key — keep locally; zeroized on drop
//!
//! // 2. Restore: recover the original secret from the response stream
//! let mut response = result.payload.as_slice();
//! let mut restored = Vec::new();
//! restore(
//! &mut response,
//! &mut restored,
//! &result.entries,
//! &result.session_key,
//! )
//! .unwrap();
//! assert_eq!(restored, payload.as_slice());
//! ```
pub
pub
pub
pub
pub
pub
pub
pub
pub use Pattern;
pub use ;
pub use ;
pub use ;
pub use ;
pub use swap;
pub use ;