microsandbox_types/
secret.rs1use std::fmt;
4
5use serde::{Deserialize, Serialize};
6use zeroize::{Zeroize, ZeroizeOnDrop};
7
8#[derive(Clone, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
18#[serde(transparent)]
19pub struct SecretValue(pub String);
20
21impl fmt::Debug for SecretValue {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.write_str("[redacted]")
28 }
29}
30
31#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn debug_is_redacted() {
41 let value = SecretValue("sentinel-secret-value".into());
42
43 let debug = format!("{value:?}");
44
45 assert_eq!(debug, "[redacted]");
46 assert!(!debug.contains("sentinel-secret-value"));
47 }
48
49 #[test]
50 fn serde_form_is_a_plain_json_string() {
51 let value = SecretValue("x".into());
52
53 let json = serde_json::to_string(&value).unwrap();
54 let parsed: SecretValue = serde_json::from_str(&json).unwrap();
55
56 assert_eq!(json, "\"x\"");
57 assert_eq!(parsed.0, "x");
58 }
59
60 #[test]
61 fn zeroize_clears_the_value() {
62 fn requires_zeroize_on_drop<T: ZeroizeOnDrop>() {}
63 requires_zeroize_on_drop::<SecretValue>();
64
65 let mut value = SecretValue("sentinel-secret-value".into());
66
67 value.zeroize();
68
69 assert!(value.0.is_empty());
70 }
71}