Skip to main content

cuenv_secrets/
salt.rs

1//! Salt configuration for secret fingerprinting with rotation support
2
3/// Salt configuration for secret fingerprinting with rotation support
4#[derive(Debug, Clone, Default)]
5pub struct SaltConfig {
6    /// Current salt (used for writing new fingerprints)
7    pub current: Option<String>,
8    /// Previous salt (accepted for reading during rotation)
9    pub previous: Option<String>,
10}
11
12impl SaltConfig {
13    /// Create a new salt config with only a current salt
14    #[must_use]
15    pub const fn new(current: Option<String>) -> Self {
16        Self {
17            current,
18            previous: None,
19        }
20    }
21
22    /// Create a salt config with rotation support
23    #[must_use]
24    pub const fn with_rotation(current: Option<String>, previous: Option<String>) -> Self {
25        Self { current, previous }
26    }
27
28    /// Check if any salt is available
29    #[must_use]
30    pub const fn has_salt(&self) -> bool {
31        self.current.is_some() || self.previous.is_some()
32    }
33
34    /// Get the current salt for writing (returns current, or previous if current is None)
35    #[must_use]
36    pub fn write_salt(&self) -> Option<&str> {
37        self.current.as_deref().or(self.previous.as_deref())
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn test_salt_config_new() {
47        let config = SaltConfig::new(Some("current".to_string()));
48        assert_eq!(config.current, Some("current".to_string()));
49        assert_eq!(config.previous, None);
50        assert!(config.has_salt());
51        assert_eq!(config.write_salt(), Some("current"));
52    }
53
54    #[test]
55    fn test_salt_config_with_rotation() {
56        let config =
57            SaltConfig::with_rotation(Some("new-salt".to_string()), Some("old-salt".to_string()));
58        assert_eq!(config.current, Some("new-salt".to_string()));
59        assert_eq!(config.previous, Some("old-salt".to_string()));
60        assert!(config.has_salt());
61        assert_eq!(config.write_salt(), Some("new-salt"));
62    }
63
64    #[test]
65    fn test_salt_config_no_current_uses_previous() {
66        let config = SaltConfig::with_rotation(None, Some("old-salt".to_string()));
67        assert!(config.has_salt());
68        assert_eq!(config.write_salt(), Some("old-salt"));
69    }
70
71    #[test]
72    fn test_salt_config_empty() {
73        let config = SaltConfig::default();
74        assert!(!config.has_salt());
75        assert_eq!(config.write_salt(), None);
76    }
77}