use thiserror::Error;
#[derive(Debug, Error)]
pub enum VaultError {
#[error("incorrect passphrase")]
WrongPassphrase,
#[error("vault metadata is corrupt and unrecoverable")]
VaultMetaCorrupt,
#[error("secret not found: {0}")]
SecretNotFound(String),
#[error("crypto error: {0}")]
Crypto(String),
#[error("storage error: {0}")]
Storage(String),
#[error("no passphrase: use -p or MAGI_PASSPHRASE in non-interactive environments")]
PassphraseUnavailable,
#[error("passphrase rejected: {0}")]
WeakPassphrase(String),
#[error("I/O error: {0}")]
Io(String),
#[error("operation cancelled")]
Aborted,
#[error("value exceeds {0} bytes")]
ValueTooLarge(usize),
}
#[cfg(test)]
mod tests {
use super::VaultError;
#[test]
fn test_wrong_passphrase_display_is_user_facing_and_leaks_nothing() {
let e = VaultError::WrongPassphrase;
assert_eq!(e.to_string(), "incorrect passphrase");
}
#[test]
fn test_vault_meta_corrupt_is_distinct_variant() {
let e = VaultError::VaultMetaCorrupt;
assert!(e.to_string().to_lowercase().contains("corrupt"));
}
#[test]
fn test_secret_not_found_includes_name_only() {
let e = VaultError::SecretNotFound("OPENAI_API_KEY".to_string());
let msg = e.to_string();
assert!(msg.contains("OPENAI_API_KEY"));
}
#[test]
fn test_aborted_display_is_user_facing_and_stable() {
assert_eq!(VaultError::Aborted.to_string(), "operation cancelled");
}
#[test]
fn test_value_too_large_includes_the_limit_only() {
let e = VaultError::ValueTooLarge(10 * 1024 * 1024);
assert!(e.to_string().contains("10485760"));
}
}