1use std::fmt;
8
9use serde::{Deserialize, Serialize};
10
11fn debug_redacted(name: &str, value: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 f.debug_struct(name).field("len", &value.len()).finish()
13}
14
15#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct CapabilityToken(String);
18
19impl CapabilityToken {
20 pub fn new(value: impl Into<String>) -> Self {
22 Self(value.into())
23 }
24
25 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29}
30
31impl fmt::Debug for CapabilityToken {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 debug_redacted("CapabilityToken", &self.0, f)
34 }
35}
36
37#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub struct ActorRef(String);
40
41impl ActorRef {
42 pub fn new(value: impl Into<String>) -> Self {
44 Self(value.into())
45 }
46
47 pub fn as_str(&self) -> &str {
49 &self.0
50 }
51}
52
53impl fmt::Debug for ActorRef {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 debug_redacted("ActorRef", &self.0, f)
56 }
57}
58
59#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
63pub struct OpaqueRef(String);
64
65impl OpaqueRef {
66 pub fn new(value: impl Into<String>) -> Self {
68 Self(value.into())
69 }
70
71 pub fn as_str(&self) -> &str {
73 &self.0
74 }
75}
76
77impl fmt::Debug for OpaqueRef {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 debug_redacted("OpaqueRef", &self.0, f)
80 }
81}
82
83#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub struct PredicateRef(String);
86
87impl PredicateRef {
88 pub fn new(value: impl Into<String>) -> Self {
90 Self(value.into())
91 }
92
93 pub fn as_str(&self) -> &str {
95 &self.0
96 }
97}
98
99impl fmt::Debug for PredicateRef {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 debug_redacted("PredicateRef", &self.0, f)
102 }
103}
104
105#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
107pub struct IdToken(String);
108
109impl IdToken {
110 pub fn new(value: impl Into<String>) -> Self {
112 Self(value.into())
113 }
114
115 pub fn as_str(&self) -> &str {
117 &self.0
118 }
119}
120
121impl fmt::Debug for IdToken {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 f.debug_tuple("IdToken").field(&self.0).finish()
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn ref_debug_does_not_dump_raw_value() {
133 let secret = "sk-this-must-not-appear";
134 let shown = format!("{:?}", OpaqueRef::new(secret));
135 assert!(shown.contains("len"));
136 assert!(!shown.contains(secret));
137 assert!(!shown.contains("sk-"));
138
139 let cap = format!("{:?}", CapabilityToken::new("contract: agent-wait/v0"));
140 assert!(cap.contains("len"));
141 assert!(!cap.contains("agent-wait"));
142
143 let pred = format!("{:?}", PredicateRef::new("pred:secret-query"));
144 assert!(!pred.contains("secret-query"));
145 }
146}