#[path = "common/mod.rs"]
mod common;
mod secret_content_edge_cases {
use crate::common::temp_vault;
#[test]
fn base64_secret_roundtrip() {
let (_dir, vault) = temp_vault();
let val = b"sk-proj-abc123+def456/ghi789==";
vault.store("openai-key", val, false).unwrap();
let dec = vault.decrypt("openai-key").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn aws_secret_key_roundtrip() {
let (_dir, vault) = temp_vault();
let val = b"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
vault.store("aws-secret", val, false).unwrap();
let dec = vault.decrypt("aws-secret").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn jwt_token_roundtrip() {
let (_dir, vault) = temp_vault();
let val = b"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U";
vault.store("jwt-token", val, false).unwrap();
let dec = vault.decrypt("jwt-token").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn connection_string_roundtrip() {
let (_dir, vault) = temp_vault();
let val = b"postgres://user:p@$$w0rd!@db.example.com:5432/mydb?sslmode=require&connect_timeout=10";
vault.store("database-url", val, false).unwrap();
let dec = vault.decrypt("database-url").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn multiline_pem_key_roundtrip() {
let (_dir, vault) = temp_vault();
let val = b"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA2mX3...\nvery-long-base64-data\n-----END RSA PRIVATE KEY-----\n";
vault.store("ssh-key", val, false).unwrap();
let dec = vault.decrypt("ssh-key").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn unicode_password_roundtrip() {
let (_dir, vault) = temp_vault();
let val = "密码Пароль🔑Contraseña".as_bytes();
vault.store("unicode-pw", val, false).unwrap();
let dec = vault.decrypt("unicode-pw").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn empty_secret_value() {
let (_dir, vault) = temp_vault();
vault.store("empty-val", b"", false).unwrap();
let dec = vault.decrypt("empty-val").unwrap();
assert!(dec.is_empty());
}
#[test]
fn large_json_service_account() {
let (_dir, vault) = temp_vault();
let mut val = String::from(
"{\"type\":\"service_account\",\"project_id\":\"test\",\"private_key\":\"",
);
val.push_str(&"x".repeat(4096)); val.push_str("\"}");
vault.store("gcp-sa", val.as_bytes(), false).unwrap();
let dec = vault.decrypt("gcp-sa").unwrap();
assert_eq!(&dec[..], val.as_bytes());
}
#[test]
fn null_byte_in_value() {
let (_dir, vault) = temp_vault();
let val = b"before\x00after\x00end";
vault.store("binary-token", val, false).unwrap();
let dec = vault.decrypt("binary-token").unwrap();
assert_eq!(&dec[..], val);
}
#[test]
fn whitespace_only_secret() {
let (_dir, vault) = temp_vault();
vault.store("whitespace", b" \t\n ", false).unwrap();
let dec = vault.decrypt("whitespace").unwrap();
assert_eq!(&dec[..], b" \t\n ");
}
}
mod secret_naming_edge_cases {
use crate::common::temp_vault;
#[test]
fn hyphenated_name() {
let (_dir, vault) = temp_vault();
vault.store("openai-api-key", b"sk", false).unwrap();
assert!(vault
.list()
.unwrap()
.contains(&"openai-api-key".to_string()));
}
#[test]
fn underscore_name() {
let (_dir, vault) = temp_vault();
vault.store("openai_api_key", b"sk", false).unwrap();
assert!(vault
.list()
.unwrap()
.contains(&"openai_api_key".to_string()));
}
#[test]
fn single_char_name() {
let (_dir, vault) = temp_vault();
vault.store("k", b"val", false).unwrap();
let dec = vault.decrypt("k").unwrap();
assert_eq!(&dec[..], b"val");
}
#[test]
fn very_long_name() {
let (_dir, vault) = temp_vault();
let name: String = (0..128).map(|_| 'a').collect();
vault.store(&name, b"val", false).unwrap();
assert!(vault.list().unwrap().contains(&name));
}
#[test]
fn dotted_name() {
let (_dir, vault) = temp_vault();
vault.store("redis.prod.password", b"val", false).unwrap();
let dec = vault.decrypt("redis.prod.password").unwrap();
assert_eq!(&dec[..], b"val");
}
#[test]
fn numeric_prefix_name() {
let (_dir, vault) = temp_vault();
vault.store("3rd-party-key", b"val", false).unwrap();
let dec = vault.decrypt("3rd-party-key").unwrap();
assert_eq!(&dec[..], b"val");
}
}
mod vault_lifecycle {
use crate::common::temp_vault;
#[test]
fn full_crud_lifecycle() {
let (_dir, vault) = temp_vault();
vault.store("api-key", b"sk-abc123", false).unwrap();
let names = vault.list().unwrap();
assert!(names.contains(&"api-key".to_string()));
let val = vault.decrypt("api-key").unwrap();
assert_eq!(&val[..], b"sk-abc123");
vault.revoke("api-key").unwrap();
assert!(!vault.list().unwrap().contains(&"api-key".to_string()));
assert!(vault.decrypt("api-key").is_err());
}
#[test]
fn revoke_one_of_many() {
let (_dir, vault) = temp_vault();
vault.store("a", b"1", false).unwrap();
vault.store("b", b"2", false).unwrap();
vault.store("c", b"3", false).unwrap();
vault.revoke("b").unwrap();
assert_eq!(&vault.decrypt("a").unwrap()[..], b"1");
assert!(vault.decrypt("b").is_err());
assert_eq!(&vault.decrypt("c").unwrap()[..], b"3");
let names = vault.list().unwrap();
assert!(names.contains(&"a".to_string()));
assert!(!names.contains(&"b".to_string()));
assert!(names.contains(&"c".to_string()));
}
#[test]
fn force_overwrite_updates_value() {
let (_dir, vault) = temp_vault();
vault.store("rotating", b"v1", false).unwrap();
vault.store("rotating", b"v2", true).unwrap();
assert_eq!(&vault.decrypt("rotating").unwrap()[..], b"v2");
}
#[test]
fn revoke_and_restore_rotation() {
let (_dir, vault) = temp_vault();
vault.store("rotated", b"old", false).unwrap();
vault.revoke("rotated").unwrap();
vault.store("rotated", b"new", false).unwrap();
assert_eq!(&vault.decrypt("rotated").unwrap()[..], b"new");
}
}
mod envseal_file_edge_cases {
use envseal::envseal_file;
#[test]
fn typical_project_file() {
let content = "\
# .envseal — safe to commit to git
# Format: ENV_VAR=secret-name
OPENAI_API_KEY=openai-key
DATABASE_URL=database-url
REDIS_URL=redis-url
STRIPE_SECRET_KEY=stripe-key
";
let (file, path) = crate::common::temp_file(content);
let mappings = envseal_file::parse_envseal_file(&path).unwrap();
assert_eq!(mappings.len(), 4);
assert_eq!(mappings[0].env_var, "OPENAI_API_KEY");
assert_eq!(mappings[0].secret_name, "openai-key");
drop(file);
}
#[test]
fn heavily_commented_file() {
let content = "\
# ===========================================
# .envseal configuration for the API gateway
# ===========================================
#
# This file maps vault secret names to env vars.
# Format: ENV_VAR=secret-name
#
# To add a secret:
# envseal store my-secret
#
# To inject all:
# envseal inject-file .envseal -- npm start
# --- Database ---
DB_PASSWORD=db-password
# --- External APIs ---
# OPENAI_API_KEY=openai-key # commented out for now
STRIPE_KEY=stripe-key
";
let (file, path) = crate::common::temp_file(content);
let mappings = envseal_file::parse_envseal_file(&path).unwrap();
assert_eq!(mappings.len(), 2);
assert_eq!(mappings[0].secret_name, "db-password");
assert_eq!(mappings[1].secret_name, "stripe-key");
drop(file);
}
#[test]
fn trailing_whitespace() {
let content = "ENV_VAR=secret-name \n";
let (file, path) = crate::common::temp_file(content);
let mappings = envseal_file::parse_envseal_file(&path).unwrap();
assert_eq!(mappings[0].env_var, "ENV_VAR");
assert_eq!(mappings[0].secret_name, "secret-name");
drop(file);
}
}
mod security_config_edge_cases {
use envseal::security_config::{SecurityConfig, SecurityTier};
#[test]
fn default_is_standard_zero_friction() {
let config = SecurityConfig::default();
assert_eq!(config.tier, SecurityTier::Standard);
assert!(!config.challenge_required);
assert_eq!(config.approval_delay_secs, 0);
assert!(config.audit_logging);
assert!(!config.totp_required);
assert!(!config.relay_required);
}
#[test]
fn hardened_preset_values() {
let config = SecurityConfig::preset_hardened();
assert_eq!(config.tier, SecurityTier::Hardened);
assert!(!config.challenge_required);
assert_eq!(config.approval_delay_secs, 2);
}
#[test]
fn lockdown_preset_values() {
let config = SecurityConfig::preset_lockdown();
assert_eq!(config.tier, SecurityTier::Lockdown);
assert!(config.challenge_required);
assert_eq!(config.approval_delay_secs, 5);
}
#[test]
fn auto_lock_defaults_shrink_with_tier() {
assert_eq!(SecurityConfig::preset_standard().auto_lock_secs, 60);
assert_eq!(SecurityConfig::preset_hardened().auto_lock_secs, 30);
assert_eq!(SecurityConfig::preset_lockdown().auto_lock_secs, 15);
}
#[test]
fn preset_preserves_totp_secret() {
let mut config = SecurityConfig::preset_standard();
config.totp_required = true;
config.totp_secret_encrypted = Some("encrypted-secret".to_string());
config.apply_preset(SecurityTier::Hardened);
assert_eq!(
config.totp_secret_encrypted,
Some("encrypted-secret".to_string())
);
assert_eq!(config.tier, SecurityTier::Hardened);
}
#[test]
fn preset_preserves_relay_endpoints() {
let mut config = SecurityConfig::preset_standard();
config.relay_required = true;
config.relay_endpoint = Some("https://relay.example.com".to_string());
config.relay_device_id = Some("device-123".to_string());
config.apply_preset(SecurityTier::Lockdown);
assert_eq!(
config.relay_endpoint,
Some("https://relay.example.com".to_string())
);
assert_eq!(config.relay_device_id, Some("device-123".to_string()));
}
#[test]
fn config_toml_roundtrip() {
let config = SecurityConfig::preset_lockdown();
let toml_str = toml::to_string(&config).unwrap();
let parsed: SecurityConfig = toml::from_str(&toml_str).unwrap();
assert_eq!(parsed.tier, config.tier);
assert_eq!(parsed.challenge_required, config.challenge_required);
assert_eq!(parsed.approval_delay_secs, config.approval_delay_secs);
}
}
mod totp_edge_cases {
use envseal::totp;
#[test]
fn codes_always_6_digits() {
let secret = totp::generate_secret();
for _ in 0..100 {
let code = totp::generate_code(&secret).unwrap();
assert_eq!(code.len(), 6, "code was: {code}");
assert!(code.chars().all(|c| c.is_ascii_digit()), "code was: {code}");
}
}
#[test]
fn reject_empty_code() {
let secret = totp::generate_secret();
assert!(!totp::verify_code(&secret, "").unwrap());
}
#[test]
fn reject_short_code() {
let secret = totp::generate_secret();
assert!(!totp::verify_code(&secret, "123").unwrap());
}
#[test]
fn reject_alpha_code() {
let secret = totp::generate_secret();
assert!(!totp::verify_code(&secret, "abcdef").unwrap());
}
#[test]
fn accepts_whitespace_padded_code() {
let secret = totp::generate_secret();
let code = totp::generate_code(&secret).unwrap();
let padded = format!(" {code} ");
assert!(totp::verify_code(&secret, &padded).unwrap());
}
#[test]
fn invalid_base32_secret() {
assert!(totp::generate_code("!!!not-base32!!!").is_err());
}
#[test]
fn decrypt_with_wrong_key_fails() {
let secret = totp::generate_secret();
let key1 = [1u8; 32];
let key2 = [2u8; 32];
let encrypted = totp::encrypt_secret(&secret, &key1).unwrap();
assert!(totp::decrypt_secret(&encrypted, &key2).is_err());
}
#[test]
fn decrypt_corrupted_ciphertext() {
assert!(totp::decrypt_secret("deadbeef", &[1u8; 32]).is_err());
}
#[test]
fn secret_is_valid_base32() {
for _ in 0..20 {
let secret = totp::generate_secret();
assert!(
base32::decode(base32::Alphabet::Rfc4648 { padding: false }, &secret).is_some(),
"invalid base32: {secret}"
);
}
}
#[test]
fn otpauth_uri_compatible() {
let secret = totp::generate_secret();
let uri = totp::otpauth_uri(&secret, "dev@company.com");
assert!(uri.starts_with("otpauth://totp/envseal:"));
assert!(uri.contains(&secret));
assert!(uri.contains("issuer=envseal"));
assert!(uri.contains("digits=6"));
assert!(uri.contains("period=30"));
assert!(uri.contains("dev@company.com"));
}
}
mod audit_edge_cases {
use envseal::audit;
#[test]
fn log_and_read_events() {
let event = audit::AuditEvent::ApprovalRequested {
binary: "/usr/bin/python3".to_string(),
secret: "openai-key".to_string(),
};
let _ = audit::log(&event);
}
#[test]
fn read_last_zero() {
let entries = audit::read_last(0);
assert!(entries.is_empty());
}
#[test]
fn read_last_very_large() {
let entries = audit::read_last(1_000_000);
assert!(entries.len() <= 1_000_000);
}
}
mod relay_edge_cases {
use envseal::relay;
use envseal::security_config::SecurityConfig;
#[test]
fn relay_not_required_by_default() {
let config = SecurityConfig::default();
assert!(!relay::is_required(&config));
}
#[test]
#[allow(clippy::field_reassign_with_default)]
fn relay_requires_pairing_fields() {
let mut config = SecurityConfig::default();
config.relay_required = true;
assert!(!relay::is_required(&config));
config.relay_endpoint = Some("https://relay.example.com".to_string());
assert!(!relay::is_required(&config));
config.relay_device_id = Some("device-123".to_string());
assert!(!relay::is_required(&config));
config.relay_pairing_key = Some("0123456789abcdef".to_string());
assert!(relay::is_required(&config));
}
#[test]
fn relay_request_fails_without_endpoint() {
let config = SecurityConfig::default();
let result = relay::request_relay_approval(&config, "python", "key", "KEY");
assert!(result.is_err());
}
}
mod policy_edge_cases {
use envseal::policy::Policy;
#[test]
fn many_rules_roundtrip() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("policy.toml");
let mut policy = Policy::default();
for i in 0..50 {
policy.allow_key(&format!("/usr/bin/app-{i}"), &format!("secret-{i}"));
}
policy
.save_signed(&path, &crate::common::TEST_KEY_BYTES)
.unwrap();
let loaded = Policy::load_verified(&path, &crate::common::TEST_KEY_BYTES).unwrap();
for i in 0..50 {
assert!(loaded.is_authorized(&format!("/usr/bin/app-{i}"), &format!("secret-{i}")));
}
}
#[test]
fn binary_multiple_secrets() {
let mut policy = Policy::default();
policy.allow_key("/usr/bin/api", "db-url");
policy.allow_key("/usr/bin/api", "redis-url");
policy.allow_key("/usr/bin/api", "stripe-key");
assert!(policy.is_authorized("/usr/bin/api", "db-url"));
assert!(policy.is_authorized("/usr/bin/api", "redis-url"));
assert!(policy.is_authorized("/usr/bin/api", "stripe-key"));
assert!(!policy.is_authorized("/usr/bin/api", "unknown"));
}
}
mod convenience_patterns {
use crate::common::temp_vault;
#[test]
fn list_sorted_after_bulk_store() {
let (_dir, vault) = temp_vault();
vault.store("z-last", b"v", false).unwrap();
vault.store("a-first", b"v", false).unwrap();
vault.store("m-middle", b"v", false).unwrap();
let names = vault.list().unwrap();
assert_eq!(names, vec!["a-first", "m-middle", "z-last"]);
}
#[test]
fn store_then_decrypt_immediate() {
let (_dir, vault) = temp_vault();
let secret = b"sk-proj-1234567890abcdef";
vault.store("quick-key", secret, false).unwrap();
assert_eq!(&vault.decrypt("quick-key").unwrap()[..], secret);
}
#[test]
fn vaults_are_isolated() {
let (_dir1, vault1) = temp_vault();
let dir2 = crate::common::vault_tempdir();
let pass2 = crate::common::test_passphrase_alt();
let vault2 = envseal::vault::Vault::open_with_passphrase(dir2.path(), &pass2).unwrap();
vault1.store("shared-name", b"value-1", false).unwrap();
vault2.store("shared-name", b"value-2", false).unwrap();
assert_eq!(&vault1.decrypt("shared-name").unwrap()[..], b"value-1");
assert_eq!(&vault2.decrypt("shared-name").unwrap()[..], b"value-2");
}
}