Skip to main content

waitprims_core/
refs.rs

1//! Identifier and reference newtypes.
2//!
3//! `Debug` for refs and capability tokens reports length only so raw
4//! secrets are not dumped. `predicate_ref` is an identifier; this crate
5//! does not evaluate predicates.
6
7use 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/// Host-less capability token such as `contract: agent-wait/v0`.
16#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct CapabilityToken(String);
18
19impl CapabilityToken {
20    /// Wrap a capability token.
21    pub fn new(value: impl Into<String>) -> Self {
22        Self(value.into())
23    }
24
25    /// Borrow the token.
26    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/// Actor identity reference. Never a credential.
38#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub struct ActorRef(String);
40
41impl ActorRef {
42    /// Wrap an actor reference.
43    pub fn new(value: impl Into<String>) -> Self {
44        Self(value.into())
45    }
46
47    /// Borrow the reference.
48    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/// Opaque symbolic reference (delivery, activation, grant, source, seat).
60///
61/// Never an inline body.
62#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
63pub struct OpaqueRef(String);
64
65impl OpaqueRef {
66    /// Wrap an opaque reference.
67    pub fn new(value: impl Into<String>) -> Self {
68        Self(value.into())
69    }
70
71    /// Borrow the reference.
72    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/// Predicate identifier. This crate does not evaluate predicates.
84#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
85pub struct PredicateRef(String);
86
87impl PredicateRef {
88    /// Wrap a predicate identifier.
89    pub fn new(value: impl Into<String>) -> Self {
90        Self(value.into())
91    }
92
93    /// Borrow the identifier.
94    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/// Stable identifier. Never a credential.
106#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
107pub struct IdToken(String);
108
109impl IdToken {
110    /// Wrap a stable identifier.
111    pub fn new(value: impl Into<String>) -> Self {
112        Self(value.into())
113    }
114
115    /// Borrow the identifier.
116    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}