Skip to main content

sentinel_dbms/
verification.rs

1use serde::{Deserialize, Serialize};
2
3/// Verification mode for signature and hash checks.
4///
5/// Defines how integrity verification failures are handled when reading documents.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7pub enum VerificationMode {
8    /// Fail with an error when verification fails (default for production).
9    /// This is the strictest mode and is recommended for production use.
10    #[default]
11    Strict,
12    /// Emit a warning when verification fails but continue processing.
13    /// Useful for auditing or migration scenarios where you want to detect issues
14    /// without blocking operations.
15    Warn,
16    /// Silently ignore verification failures.
17    /// Useful for performance-critical scenarios or when documents are known to be unsigned.
18    Silent,
19}
20
21impl std::str::FromStr for VerificationMode {
22    type Err = ();
23
24    fn from_str(s: &str) -> Result<Self, Self::Err> {
25        match s.to_lowercase().as_str() {
26            "strict" => Ok(Self::Strict),
27            "warn" => Ok(Self::Warn),
28            "silent" => Ok(Self::Silent),
29            _ => Err(()),
30        }
31    }
32}
33
34impl VerificationMode {
35    /// Get the string representation of the verification mode.
36    pub const fn as_str(&self) -> &str {
37        match *self {
38            Self::Strict => "strict",
39            Self::Warn => "warn",
40            Self::Silent => "silent",
41        }
42    }
43}
44
45/// Options for controlling verification behavior when reading documents.
46///
47/// These options allow fine-grained control over integrity verification at the method level.
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub struct VerificationOptions {
50    /// Whether to verify document signatures.
51    /// Defaults to true for security.
52    pub verify_signature:            bool,
53    /// Whether to verify document hashes.
54    /// Defaults to true for integrity.
55    pub verify_hash:                 bool,
56    /// How to handle signature verification failures (invalid signatures).
57    /// Defaults to Strict.
58    pub signature_verification_mode: VerificationMode,
59    /// How to handle empty signature documents.
60    /// Defaults to Warn (documents without signatures are common in mixed collections).
61    pub empty_signature_mode:        VerificationMode,
62    /// How to handle hash verification failures.
63    /// Defaults to Strict.
64    pub hash_verification_mode:      VerificationMode,
65}
66
67impl Default for VerificationOptions {
68    fn default() -> Self {
69        Self {
70            verify_signature:            true,
71            verify_hash:                 true,
72            signature_verification_mode: VerificationMode::Strict,
73            empty_signature_mode:        VerificationMode::Warn,
74            hash_verification_mode:      VerificationMode::Strict,
75        }
76    }
77}
78
79impl VerificationOptions {
80    /// Create new verification options with all verifications enabled and strict mode.
81    pub const fn strict() -> Self {
82        Self {
83            verify_signature:            true,
84            verify_hash:                 true,
85            signature_verification_mode: VerificationMode::Strict,
86            empty_signature_mode:        VerificationMode::Strict,
87            hash_verification_mode:      VerificationMode::Strict,
88        }
89    }
90
91    /// Create new verification options with all verifications disabled.
92    pub const fn disabled() -> Self {
93        Self {
94            verify_signature:            false,
95            verify_hash:                 false,
96            signature_verification_mode: VerificationMode::Silent,
97            empty_signature_mode:        VerificationMode::Silent,
98            hash_verification_mode:      VerificationMode::Silent,
99        }
100    }
101
102    /// Create new verification options with warnings instead of errors.
103    pub const fn warn() -> Self {
104        Self {
105            verify_signature:            true,
106            verify_hash:                 true,
107            signature_verification_mode: VerificationMode::Warn,
108            empty_signature_mode:        VerificationMode::Warn,
109            hash_verification_mode:      VerificationMode::Warn,
110        }
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use std::str::FromStr;
117
118    use super::*;
119
120    #[test]
121    fn test_verification_mode_from_str() {
122        assert_eq!(
123            VerificationMode::from_str("strict"),
124            Ok(VerificationMode::Strict)
125        );
126        assert_eq!(
127            VerificationMode::from_str("warn"),
128            Ok(VerificationMode::Warn)
129        );
130        assert_eq!(
131            VerificationMode::from_str("silent"),
132            Ok(VerificationMode::Silent)
133        );
134        assert_eq!(
135            "STRICT".parse::<VerificationMode>(),
136            Ok(VerificationMode::Strict)
137        );
138        assert!("invalid".parse::<VerificationMode>().is_err());
139    }
140
141    #[test]
142    fn test_verification_mode_as_str() {
143        assert_eq!(VerificationMode::Strict.as_str(), "strict");
144        assert_eq!(VerificationMode::Warn.as_str(), "warn");
145        assert_eq!(VerificationMode::Silent.as_str(), "silent");
146    }
147
148    #[test]
149    fn test_verification_options_default() {
150        let opts = VerificationOptions::default();
151        assert!(opts.verify_signature);
152        assert!(opts.verify_hash);
153        assert_eq!(opts.signature_verification_mode, VerificationMode::Strict);
154        assert_eq!(opts.empty_signature_mode, VerificationMode::Warn);
155        assert_eq!(opts.hash_verification_mode, VerificationMode::Strict);
156    }
157
158    #[test]
159    fn test_verification_options_strict() {
160        let opts = VerificationOptions::strict();
161        assert!(opts.verify_signature);
162        assert!(opts.verify_hash);
163        assert_eq!(opts.signature_verification_mode, VerificationMode::Strict);
164        assert_eq!(opts.empty_signature_mode, VerificationMode::Strict);
165        assert_eq!(opts.hash_verification_mode, VerificationMode::Strict);
166    }
167
168    #[test]
169    fn test_verification_options_disabled() {
170        let opts = VerificationOptions::disabled();
171        assert!(!opts.verify_signature);
172        assert!(!opts.verify_hash);
173        assert_eq!(opts.signature_verification_mode, VerificationMode::Silent);
174        assert_eq!(opts.empty_signature_mode, VerificationMode::Silent);
175        assert_eq!(opts.hash_verification_mode, VerificationMode::Silent);
176    }
177
178    #[test]
179    fn test_verification_options_warn() {
180        let opts = VerificationOptions::warn();
181        assert!(opts.verify_signature);
182        assert!(opts.verify_hash);
183        assert_eq!(opts.signature_verification_mode, VerificationMode::Warn);
184        assert_eq!(opts.empty_signature_mode, VerificationMode::Warn);
185        assert_eq!(opts.hash_verification_mode, VerificationMode::Warn);
186    }
187}