← back to jdx__fnox

Function bodies 391 total

All specs Real LLM only Function bodies
get_profile_secrets_mut function · rust · L779-L788 (10 LOC)
src/config.rs
    pub fn get_profile_secrets_mut(
        &mut self,
        profile: &str,
    ) -> &mut IndexMap<String, SecretConfig> {
        &mut self
            .profiles
            .entry(profile.to_string())
            .or_default()
            .secrets
    }
get_secrets function · rust · L796-L817 (22 LOC)
src/config.rs
    pub fn get_secrets(&self, profile: &str) -> Result<IndexMap<String, SecretConfig>> {
        if profile == "default" {
            return Ok(self.secrets.clone());
        }

        let mut secrets = if Settings::get().no_defaults {
            // Profile-only mode: do not merge top-level secrets.
            IndexMap::new()
        } else {
            // Start with top-level secrets as base
            self.secrets.clone()
        };

        // Get profile-specific secrets and merge/override (if profile exists)
        if let Some(profile_config) = self.profiles.get(profile) {
            // Profile-specific secrets override top-level ones
            secrets.extend(profile_config.secrets.clone());
        }
        // If profile doesn't exist in [profiles], that's OK - just use top-level secrets
        // This allows fnox.$FNOX_PROFILE.toml to work without requiring [profiles.xxx]
        Ok(secrets)
    }
get_secrets_mut function · rust · L820-L826 (7 LOC)
src/config.rs
    pub fn get_secrets_mut(&mut self, profile: &str) -> &mut IndexMap<String, SecretConfig> {
        if profile == "default" {
            self.get_default_secrets_mut()
        } else {
            self.get_profile_secrets_mut(profile)
        }
    }
get_providers function · rust · L829-L839 (11 LOC)
src/config.rs
    pub fn get_providers(&self, profile: &str) -> IndexMap<String, ProviderConfig> {
        let mut providers = self.providers.clone(); // Start with global providers

        if profile != "default"
            && let Some(profile_config) = self.profiles.get(profile)
        {
            providers.extend(profile_config.providers.clone());
        }

        providers
    }
get_default_provider function · rust · L843-L925 (83 LOC)
src/config.rs
    pub fn get_default_provider(&self, profile: &str) -> Result<Option<String>> {
        let providers = self.get_providers(profile);

        // If no providers configured and this is a root config, return None
        if providers.is_empty() && self.root {
            return Ok(None);
        }

        // If no providers configured, that's an error
        if providers.is_empty() {
            return Err(FnoxError::Config(
                "No providers configured. Add at least one provider to fnox.toml".to_string(),
            ));
        }

        // Check for profile-specific default provider
        if profile != "default"
            && let Some(profile_config) = self.profiles.get(profile)
            && let Some(default_provider_name) = profile_config.default_provider()
        {
            // Validate that the default provider exists
            if !providers.contains_key(default_provider_name) {
                // Try to get source info for better error reporting
        
set_source_paths function · rust · L928-L966 (39 LOC)
src/config.rs
    fn set_source_paths(&mut self, path: &Path) {
        // Set source paths for default profile secrets
        for (key, secret) in self.secrets.iter_mut() {
            secret.source_path = Some(path.to_path_buf());
            self.secret_sources.insert(key.clone(), path.to_path_buf());
        }

        // Set source paths for default profile providers
        for (provider_name, _) in self.providers.iter() {
            self.provider_sources
                .insert(provider_name.clone(), path.to_path_buf());
        }

        // Set source path for default_provider if set
        if self.default_provider().is_some() {
            self.default_provider_source = Some(path.to_path_buf());
        }

        // Set source paths for named profiles
        for (_profile_name, profile) in self.profiles.iter_mut() {
            for (key, secret) in profile.secrets.iter_mut() {
                secret.source_path = Some(path.to_path_buf());
                profile
                    .s
check_empty_value function · rust · L970-L1001 (32 LOC)
src/config.rs
    fn check_empty_value(
        &self,
        key: &str,
        secret: &SecretConfig,
        profile: &str,
    ) -> Option<crate::error::ValidationIssue> {
        // Early return if value is not an empty string
        let Some(value) = secret.value() else {
            return None; // No value specified - not an issue
        };
        if !value.is_empty() {
            return None; // Non-empty value - not an issue
        }

        // At this point, value is an empty string
        // Allow empty values for plain provider (empty string is a valid secret value)
        if self.is_plain_provider(secret.provider(), profile) {
            return None;
        }
        let message = if profile == "default" {
            format!("Secret '{}' has an empty value", key)
        } else {
            format!(
                "Secret '{}' in profile '{}' has an empty value",
                key, profile
            )
        };
        Some(crate::error::ValidationIssue::with_help(
 
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
is_plain_provider function · rust · L1005-L1040 (36 LOC)
src/config.rs
    fn is_plain_provider(&self, secret_provider: Option<&str>, profile: &str) -> bool {
        // Get providers for this profile first (needed for auto-selection)
        let providers = self.get_providers(profile);

        // Determine which provider name to use
        let provider_name = secret_provider
            .map(String::from)
            .or_else(|| {
                // Try profile's default_provider first (only for non-default profiles)
                if profile != "default" {
                    self.profiles
                        .get(profile)
                        .and_then(|p| p.default_provider().map(|s| s.to_string()))
                } else {
                    None
                }
            })
            .or_else(|| self.default_provider().map(|s| s.to_string()))
            .or_else(|| {
                // Auto-select if exactly one provider exists (matching get_default_provider behavior)
                if providers.len() == 1 {
                    pr
validate function · rust · L1044-L1161 (118 LOC)
src/config.rs
    pub fn validate(&self) -> Result<()> {
        use crate::error::ValidationIssue;

        // If root=true and no providers AND no secrets, that's OK (empty config)
        if self.root
            && self.providers.is_empty()
            && self.profiles.is_empty()
            && self.secrets.is_empty()
        {
            return Ok(());
        }

        let mut issues = Vec::new();

        // Check for secrets with empty values (likely a mistake, but allowed for plain provider)
        for (key, secret) in &self.secrets {
            if let Some(issue) = self.check_empty_value(key, secret, "default") {
                issues.push(issue);
            }
        }

        // Check that there's at least one provider if there are any secrets
        if self.providers.is_empty() && self.profiles.is_empty() && !self.secrets.is_empty() {
            issues.push(ValidationIssue::with_help(
                "No providers configured",
                "Add at least one provider to fnox.
new function · rust · L1192-L1203 (12 LOC)
src/config.rs
    pub fn new() -> Self {
        Self {
            description: None,
            if_missing: None,
            default: None,
            provider: None,
            value: None,
            as_file: false,
            json_path: None,
            source_path: None,
        }
    }
to_inline_table function · rust · L1206-L1238 (33 LOC)
src/config.rs
    pub fn to_inline_table(&self) -> toml_edit::InlineTable {
        let mut inline = toml_edit::InlineTable::new();

        if let Some(provider) = self.provider() {
            inline.insert("provider", toml_edit::Value::from(provider));
        }
        if let Some(value) = self.value() {
            inline.insert("value", toml_edit::Value::from(value));
        }
        if let Some(ref json_path) = self.json_path {
            inline.insert("json_path", toml_edit::Value::from(json_path.as_str()));
        }
        if let Some(ref description) = self.description {
            inline.insert("description", toml_edit::Value::from(description.as_str()));
        }
        if let Some(ref default) = self.default {
            inline.insert("default", toml_edit::Value::from(default.as_str()));
        }
        if let Some(if_missing) = self.if_missing {
            let if_missing_str = match if_missing {
                IfMissing::Error => "error",
                IfMissing::Warn =>
new function · rust · L1276-L1285 (10 LOC)
src/config.rs
    pub fn new() -> Self {
        Self {
            providers: IndexMap::new(),
            default_provider: None,
            secrets: IndexMap::new(),
            provider_sources: HashMap::new(),
            secret_sources: HashMap::new(),
            default_provider_source: None,
        }
    }
test_empty_import_not_serialized function · rust · L1329-L1336 (8 LOC)
src/config.rs
    fn test_empty_import_not_serialized() {
        let config = Config::new();
        let toml = toml_edit::ser::to_string_pretty(&config).unwrap();
        assert!(
            !toml.contains("import"),
            "Empty import should not be serialized"
        );
    }
test_non_empty_import_is_serialized function · rust · L1339-L1351 (13 LOC)
src/config.rs
    fn test_non_empty_import_is_serialized() {
        let mut config = Config::new();
        config.import.push("other.toml".to_string());
        let toml = toml_edit::ser::to_string_pretty(&config).unwrap();
        assert!(
            toml.contains("import"),
            "Non-empty import should be serialized"
        );
        assert!(
            toml.contains("other.toml"),
            "Import value should be present"
        );
    }
test_empty_profiles_not_serialized function · rust · L1354-L1361 (8 LOC)
src/config.rs
    fn test_empty_profiles_not_serialized() {
        let config = Config::new();
        let toml = toml_edit::ser::to_string_pretty(&config).unwrap();
        assert!(
            !toml.contains("profiles"),
            "Empty profiles should not be serialized"
        );
    }
Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
test_non_empty_profiles_is_serialized function · rust · L1364-L1396 (33 LOC)
src/config.rs
    fn test_non_empty_profiles_is_serialized() {
        let mut config = Config::new();

        // Add a provider and secret to the prod profile
        let mut prod_profile = ProfileConfig::new();
        prod_profile
            .providers
            .insert("plain".to_string(), ProviderConfig::Plain);
        let mut secret = SecretConfig::new();
        secret.set_value(Some("test-value".to_string()));
        prod_profile
            .secrets
            .insert("TEST_SECRET".to_string(), secret);

        config.profiles.insert("prod".to_string(), prod_profile);
        let toml = toml_edit::ser::to_string_pretty(&config).unwrap();

        // Print the TOML for debugging
        eprintln!("Generated TOML:\n{}", toml);

        assert!(
            toml.contains("profiles"),
            "Non-empty profiles should be serialized"
        );
        assert!(toml.contains("prod"), "Profile name should be present");

        // Check that we don't have a standalone [profiles] heade
test_empty_profile_not_serialized function · rust · L1399-L1431 (33 LOC)
src/config.rs
    fn test_empty_profile_not_serialized() {
        use std::io::Read;

        let mut config = Config::new();
        // Add an empty profile (no providers, no secrets)
        config
            .profiles
            .insert("prod".to_string(), ProfileConfig::new());

        // Use save() which cleans up empty profiles
        let temp_file = std::env::temp_dir().join("fnox_test_empty_profile.toml");
        config.save(&temp_file).unwrap();

        let mut toml = String::new();
        std::fs::File::open(&temp_file)
            .unwrap()
            .read_to_string(&mut toml)
            .unwrap();
        std::fs::remove_file(&temp_file).ok();

        eprintln!("Generated TOML with empty profile:\n{}", toml);

        // Empty profiles should not appear in the output at all
        // Because save() cleans them up
        assert!(
            !toml.contains("[profiles"),
            "Empty profile should not be serialized"
        );
        assert!(
            !toml.contain
test_no_defaults_profile_only_secrets function · rust · L1434-L1457 (24 LOC)
src/config.rs
    fn test_no_defaults_profile_only_secrets() {
        crate::settings::Settings::reset_for_tests();
        crate::settings::Settings::set_cli_snapshot(crate::settings::CliSnapshot {
            age_key_file: None,
            profile: Some("prod".to_string()),
            if_missing: None,
            no_defaults: true,
        });

        let mut config = Config::new();
        config
            .secrets
            .insert("DEFAULT_ONLY".to_string(), SecretConfig::new());

        let mut prod_profile = ProfileConfig::new();
        prod_profile
            .secrets
            .insert("PROD_ONLY".to_string(), SecretConfig::new());
        config.profiles.insert("prod".to_string(), prod_profile);

        let secrets = config.get_secrets("prod").unwrap();
        assert!(secrets.contains_key("PROD_ONLY"));
        assert!(!secrets.contains_key("DEFAULT_ONLY"));
    }
test_no_defaults_profile_without_section_is_empty function · rust · L1460-L1476 (17 LOC)
src/config.rs
    fn test_no_defaults_profile_without_section_is_empty() {
        crate::settings::Settings::reset_for_tests();
        crate::settings::Settings::set_cli_snapshot(crate::settings::CliSnapshot {
            age_key_file: None,
            profile: Some("prod".to_string()),
            if_missing: None,
            no_defaults: true,
        });

        let mut config = Config::new();
        config
            .secrets
            .insert("DEFAULT_ONLY".to_string(), SecretConfig::new());

        let secrets = config.get_secrets("prod").unwrap();
        assert!(secrets.is_empty());
    }
set_var function · rust · L12-L18 (7 LOC)
src/env.rs
pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, val: V) {
    let _lock = ENV_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
    // SAFETY: set_var is unsafe in Rust 2024 edition. Access is serialized via ENV_MUTEX.
    unsafe {
        std::env::set_var(key, val);
    }
}
is_valid_profile_name function · rust · L61-L88 (28 LOC)
src/env.rs
fn is_valid_profile_name(name: &str) -> bool {
    // Profile names must be non-empty
    if name.is_empty() {
        return false;
    }

    // Reject path separators and other dangerous characters
    // Allow: alphanumeric, dash, underscore, dot (but not .. or .)
    if name == "." || name == ".." {
        return false;
    }

    // Check for path separators or other dangerous characters
    for ch in name.chars() {
        match ch {
            // Path separators
            '/' | '\\' => return false,
            // Null byte (could truncate paths)
            '\0' => return false,
            // Control characters
            c if c.is_control() => return false,
            // Allow everything else (alphanumeric, dash, underscore, dot)
            _ => {}
        }
    }

    true
}
test_var_path function · rust · L95-L104 (10 LOC)
src/env.rs
    fn test_var_path() {
        unsafe {
            set_var("FNOX_TEST_PATH", "/foo/bar");
            assert_eq!(
                var_path("FNOX_TEST_PATH").unwrap(),
                PathBuf::from("/foo/bar")
            );
            remove_var("FNOX_TEST_PATH");
        }
    }
test_valid_profile_names function · rust · L107-L116 (10 LOC)
src/env.rs
    fn test_valid_profile_names() {
        // Valid profile names
        assert!(is_valid_profile_name("production"));
        assert!(is_valid_profile_name("staging"));
        assert!(is_valid_profile_name("dev"));
        assert!(is_valid_profile_name("test-env"));
        assert!(is_valid_profile_name("test_env"));
        assert!(is_valid_profile_name("prod-v2.0"));
        assert!(is_valid_profile_name("env123"));
    }
All rows scored by the Repobility analyzer (https://repobility.com)
test_invalid_profile_names function · rust · L119-L140 (22 LOC)
src/env.rs
    fn test_invalid_profile_names() {
        // Path traversal attempts
        assert!(!is_valid_profile_name("../../../etc/passwd"));
        assert!(!is_valid_profile_name(".."));
        assert!(!is_valid_profile_name("."));
        assert!(!is_valid_profile_name("../production"));
        assert!(!is_valid_profile_name("production/../../etc/passwd"));

        // Absolute paths
        assert!(!is_valid_profile_name("/etc/passwd"));
        assert!(!is_valid_profile_name("/tmp/evil"));

        // Windows paths
        assert!(!is_valid_profile_name("C:\\Windows\\System32"));
        assert!(!is_valid_profile_name("..\\..\\evil"));

        // Empty and special characters
        assert!(!is_valid_profile_name(""));
        assert!(!is_valid_profile_name("prod\0uction")); // null byte
        assert!(!is_valid_profile_name("prod\ntest")); // newline
        assert!(!is_valid_profile_name("prod\rtest")); // carriage return
    }
with_help function · rust · L18-L23 (6 LOC)
src/error.rs
    pub fn with_help(message: impl Into<String>, help: impl Into<String>) -> Self {
        Self {
            message: message.into(),
            help: Some(help.into()),
        }
    }
new function · rust · L54-L112 (59 LOC)
src/hook_env.rs
    pub fn new(
        dir: Option<PathBuf>,
        config_path: Option<PathBuf>,
        loaded_secrets: HashMap<String, String>,
        temp_files: HashMap<String, String>,
    ) -> Result<Self> {
        let config_mtime = if let Some(ref path) = config_path {
            std::fs::metadata(path)
                .and_then(|m| m.modified())
                .ok()
                .and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok())
                .map(|d| d.as_millis())
        } else {
            None
        };

        let env_var_hash = hash_fnox_env_vars();

        // Calculate hash of all config files in the hierarchy
        let config_files_hash = if let Some(ref d) = dir {
            let configs = collect_config_files(d);
            hash_config_files(&configs)
        } else {
            String::new()
        };

        // Generate a random key for this session's hashes
        use blake3::Hasher;
        let hash_key = *Hasher::new()
            .update(b"fno
decode_session function · rust · L123-L129 (7 LOC)
src/hook_env.rs
fn decode_session(encoded: &str) -> Result<HookEnvSession> {
    let compressed = data_encoding::BASE64.decode(encoded.as_bytes())?;
    let bytes = miniz_oxide::inflate::decompress_to_vec(&compressed)
        .map_err(|e| anyhow::anyhow!("failed to decompress session: {:?}", e))?;
    let session = rmp_serde::from_slice(&bytes)?;
    Ok(session)
}
hash_secret_with_key function · rust · L134-L140 (7 LOC)
src/hook_env.rs
fn hash_secret_with_key(hash_key: &[u8; 32], key: &str, value: &str) -> String {
    let mut hasher = blake3::Hasher::new_keyed(hash_key);
    hasher.update(key.as_bytes());
    hasher.update(b"\x00"); // separator
    hasher.update(value.as_bytes());
    hasher.finalize().to_hex().to_string()
}
should_exit_early function · rust · L149-L170 (22 LOC)
src/hook_env.rs
pub fn should_exit_early() -> bool {
    // Check if directory changed
    if has_directory_changed() {
        tracing::debug!("directory changed, must run hook-env");
        return false;
    }

    // Check if fnox.toml was modified
    if has_config_been_modified() {
        tracing::debug!("fnox.toml modified, must run hook-env");
        return false;
    }

    // Check if FNOX_* env vars changed
    if has_fnox_env_vars_changed() {
        tracing::debug!("FNOX_* env vars changed, must run hook-env");
        return false;
    }

    tracing::debug!("no changes detected, exiting early");
    true
}
has_config_been_modified function · rust · L180-L204 (25 LOC)
src/hook_env.rs
fn has_config_been_modified() -> bool {
    let current_dir = match std::env::current_dir() {
        Ok(dir) => dir,
        Err(_) => return true, // If we can't get current dir, force reload
    };

    // Build a hash of all current config files and their mtimes
    let current_configs = collect_config_files(&current_dir);
    let current_hash = hash_config_files(&current_configs);

    // Compare with the stored hash from the previous session
    if PREV_SESSION.config_files_hash.is_empty() {
        // Old session without config_files_hash - use conservative fallback
        // Without the hash, we can't reliably detect changes, so we must be conservative:
        // - Reload if there was a previous config (might have changed or been deleted)
        // - Reload if there's a current config (might be new or changed)
        // - Only skip if neither previous nor current config exists
        let had_config = PREV_SESSION.config_path.is_some();
        let has_config = !current_con
collect_config_files function · rust · L208-L246 (39 LOC)
src/hook_env.rs
fn collect_config_files(start_dir: &Path) -> Vec<(PathBuf, u128)> {
    use crate::config::Config;

    let mut configs = Vec::new();
    let mut current = start_dir.to_path_buf();

    // Get profile name using Settings system which respects: CLI flag > Env var > Default
    let profile_name = crate::settings::Settings::get().profile.clone();
    let filenames = crate::config::all_config_filenames(Some(&profile_name));

    loop {
        // Check all config filenames (fnox.toml, .fnox.toml, fnox.$PROFILE.toml, etc.)
        for filename in &filenames {
            let config_path = current.join(filename);
            if let Ok(metadata) = std::fs::metadata(&config_path)
                && let Ok(modified) = metadata.modified()
                && let Ok(duration) = modified.duration_since(SystemTime::UNIX_EPOCH)
            {
                configs.push((config_path, duration.as_millis()));
            }
        }

        // Move to parent directory
        if !current.pop() {
     
Repobility · open methodology · https://repobility.com/research/
hash_fnox_env_vars function · rust · L268-L282 (15 LOC)
src/hook_env.rs
fn hash_fnox_env_vars() -> String {
    use std::collections::BTreeMap;
    use std::hash::{Hash, Hasher};

    let mut vars: BTreeMap<String, String> = BTreeMap::new();
    for (key, value) in std::env::vars() {
        if key.starts_with("FNOX_") {
            vars.insert(key, value);
        }
    }

    let mut hasher = std::collections::hash_map::DefaultHasher::new();
    vars.hash(&mut hasher);
    format!("{:x}", hasher.finish())
}
find_config function · rust · L287-L316 (30 LOC)
src/hook_env.rs
pub fn find_config() -> Option<PathBuf> {
    use crate::config::{Config, all_config_filenames};

    let profile = crate::settings::Settings::get().profile.clone();
    let filenames = all_config_filenames(Some(&profile));

    let mut current = std::env::current_dir().ok()?;

    loop {
        // Check all config files (returns first match)
        for filename in &filenames {
            let path = current.join(filename);
            if path.exists() {
                return Some(path);
            }
        }

        if !current.pop() {
            break;
        }
    }

    // Check global config as fallback
    let global = Config::global_config_path();
    if global.is_file() {
        return Some(global);
    }

    None
}
main function · rust · L26-L61 (36 LOC)
src/main.rs
async fn main() -> miette::Result<()> {
    miette::set_panic_hook();

    // Initialize rustls crypto provider for GCP SDKs
    let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();

    let cli = Cli::parse();

    // Set CLI snapshot for settings system
    settings::Settings::set_cli_snapshot(settings::CliSnapshot {
        age_key_file: cli.age_key_file.clone(),
        profile: cli.profile.clone(),
        if_missing: cli.if_missing.clone(),
        no_defaults: cli.no_defaults,
    });

    // Handle --no-color flag
    if cli.no_color {
        console::set_colors_enabled(false);
        console::set_colors_enabled_stderr(false);
    }

    // Initialize tracing
    let log_level = if cli.verbose { "debug" } else { "info" };
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| format!("fnox={}", log_level).into()),
        )
        .with(tracing_subscriber::fmt
new function · rust · L17-L22 (6 LOC)
src/providers/age.rs
    pub fn new(recipients: Vec<String>, key_file: Option<String>) -> Self {
        Self {
            recipients,
            key_file: key_file.map(|k| PathBuf::from(shellexpand::tilde(&k).to_string())),
        }
    }
encrypt function · rust · L30-L99 (70 LOC)
src/providers/age.rs
    async fn encrypt(&self, plaintext: &str) -> Result<String> {
        use std::io::Write;

        if self.recipients.is_empty() {
            return Err(FnoxError::AgeNotConfigured);
        }

        // Parse recipients - try both SSH and native age formats
        let mut parsed_recipients: Vec<Box<dyn age::Recipient + Send + Sync>> = Vec::new();

        for recipient in &self.recipients {
            // Try parsing as SSH recipient first
            if let Ok(ssh_recipient) = recipient.parse::<age::ssh::Recipient>() {
                parsed_recipients.push(Box::new(ssh_recipient));
                continue;
            }

            // Fall back to native age recipient
            match recipient.parse::<age::x25519::Recipient>() {
                Ok(age_recipient) => {
                    parsed_recipients.push(Box::new(age_recipient));
                }
                Err(e) => {
                    return Err(FnoxError::AgeEncryptionFailed {
                        detai
get_secret function · rust · L100-L209 (110 LOC)
src/providers/age.rs
    async fn get_secret(&self, value: &str) -> Result<String> {
        // value contains the encrypted blob (might be base64 encoded or raw)

        // Try to decode as base64 first, if that fails, treat as raw bytes
        let encrypted_bytes =
            match base64::Engine::decode(&base64::engine::general_purpose::STANDARD, value) {
                Ok(bytes) => bytes,
                Err(_) => {
                    // Not base64 encoded, treat as raw bytes
                    value.as_bytes().to_vec()
                }
            };

        // Priority for key file:
        // 1. FNOX_AGE_KEY env var (inline key content)
        // 2. self.key_file (from provider config)
        // 3. Settings age_key_file (from CLI flag - deprecated)
        // 4. Default path (~/.config/fnox/age.txt)
        let (identity_content, key_file_path_opt) = if let Some(ref age_key) = *env::FNOX_AGE_KEY {
            // Use the key directly from the environment variable
            (age_key.clone
aws_kms_error_to_fnox function · rust · L14-L119 (106 LOC)
src/providers/aws_kms.rs
fn aws_kms_error_to_fnox<E, R>(
    err: &aws_sdk_kms::error::SdkError<E, R>,
    operation: &str,
    key_id: &str,
) -> FnoxError
where
    E: std::fmt::Debug + std::fmt::Display,
    R: std::fmt::Debug,
{
    use aws_sdk_kms::error::SdkError;

    match err {
        SdkError::ServiceError(service_err) => {
            let err_str = service_err.err().to_string();
            if err_str.contains("AccessDenied") || err_str.contains("UnauthorizedAccess") {
                FnoxError::ProviderAuthFailed {
                    provider: "AWS KMS".to_string(),
                    details: err_str,
                    hint: format!("Check IAM permissions for kms:{}", operation),
                    url: URL.to_string(),
                }
            } else if err_str.contains("NotFoundException") {
                FnoxError::ProviderSecretNotFound {
                    provider: "AWS KMS".to_string(),
                    secret: key_id.to_string(),
                    hint: "Check that the K
create_client function · rust · L132-L140 (9 LOC)
src/providers/aws_kms.rs
    async fn create_client(&self) -> Result<Client> {
        // Load AWS config with the specified region
        let config = aws_config::defaults(BehaviorVersion::latest())
            .region(aws_sdk_kms::config::Region::new(self.region.clone()))
            .load()
            .await;

        Ok(Client::new(&config))
    }
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
decrypt function · rust · L143-L185 (43 LOC)
src/providers/aws_kms.rs
    async fn decrypt(&self, ciphertext_base64: &str) -> Result<String> {
        let client = self.create_client().await?;

        // Decode from base64
        let ciphertext_bytes = base64::Engine::decode(
            &base64::engine::general_purpose::STANDARD,
            ciphertext_base64,
        )
        .map_err(|e| FnoxError::ProviderInvalidResponse {
            provider: "AWS KMS".to_string(),
            details: format!("Failed to decode base64 ciphertext: {}", e),
            hint: "The encrypted value appears to be corrupted".to_string(),
            url: URL.to_string(),
        })?;

        let result = client
            .decrypt()
            .key_id(&self.key_id)
            .ciphertext_blob(Blob::new(ciphertext_bytes))
            .send()
            .await
            .map_err(|e| aws_kms_error_to_fnox(&e, "Decrypt", &self.key_id))?;

        let plaintext_blob =
            result
                .plaintext()
                .ok_or_else(|| FnoxError::ProviderIn
encrypt function · rust · L198-L225 (28 LOC)
src/providers/aws_kms.rs
    async fn encrypt(&self, plaintext: &str) -> Result<String> {
        let client = self.create_client().await?;

        let result = client
            .encrypt()
            .key_id(&self.key_id)
            .plaintext(Blob::new(plaintext.as_bytes()))
            .send()
            .await
            .map_err(|e| aws_kms_error_to_fnox(&e, "Encrypt", &self.key_id))?;

        let ciphertext_blob =
            result
                .ciphertext_blob()
                .ok_or_else(|| FnoxError::ProviderInvalidResponse {
                    provider: "AWS KMS".to_string(),
                    details: "Encrypt returned no ciphertext".to_string(),
                    hint: "This is an unexpected error".to_string(),
                    url: URL.to_string(),
                })?;

        // Encode as base64 for storage
        Ok(base64::Engine::encode(
            &base64::engine::general_purpose::STANDARD,
            ciphertext_blob.as_ref(),
        ))
    }
test_connection function · rust · L226-L239 (14 LOC)
src/providers/aws_kms.rs
    async fn test_connection(&self) -> Result<()> {
        let client = self.create_client().await?;

        // Try to describe the key to verify access
        client
            .describe_key()
            .key_id(&self.key_id)
            .send()
            .await
            .map_err(|e| aws_kms_error_to_fnox(&e, "DescribeKey", &self.key_id))?;

        Ok(())
    }
aws_ps_error_to_fnox function · rust · L14-L118 (105 LOC)
src/providers/aws_ps.rs
fn aws_ps_error_to_fnox<E, R>(
    err: &aws_sdk_ssm::error::SdkError<E, R>,
    param_name: &str,
) -> FnoxError
where
    E: std::fmt::Debug + std::fmt::Display,
    R: std::fmt::Debug,
{
    use aws_sdk_ssm::error::SdkError;

    match err {
        SdkError::ServiceError(service_err) => {
            let err_str = service_err.err().to_string();
            if err_str.contains("ParameterNotFound") {
                FnoxError::ProviderSecretNotFound {
                    provider: "AWS Parameter Store".to_string(),
                    secret: param_name.to_string(),
                    hint: "Check that the parameter exists in AWS Parameter Store".to_string(),
                    url: URL.to_string(),
                }
            } else if err_str.contains("AccessDenied") || err_str.contains("UnauthorizedAccess") {
                FnoxError::ProviderAuthFailed {
                    provider: "AWS Parameter Store".to_string(),
                    details: err_str,
                   
new function · rust · L127-L133 (7 LOC)
src/providers/aws_ps.rs
    pub fn new(region: String, profile: Option<String>, prefix: Option<String>) -> Self {
        Self {
            region,
            profile,
            prefix,
        }
    }
get_parameter_name function · rust · L134-L140 (7 LOC)
src/providers/aws_ps.rs
    pub fn get_parameter_name(&self, key: &str) -> String {
        match &self.prefix {
            Some(prefix) => format!("{}{}", prefix, key),
            None => key.to_string(),
        }
    }
create_client function · rust · L143-L153 (11 LOC)
src/providers/aws_ps.rs
    async fn create_client(&self) -> Result<Client> {
        let mut builder = aws_config::defaults(BehaviorVersion::latest())
            .region(aws_sdk_ssm::config::Region::new(self.region.clone()));

        if let Some(profile) = &self.profile {
            builder = builder.profile_name(profile);
        }

        let config = builder.load().await;
        Ok(Client::new(&config))
    }
get_parameter_value function · rust · L156-L178 (23 LOC)
src/providers/aws_ps.rs
    async fn get_parameter_value(&self, parameter_name: &str) -> Result<String> {
        let client = self.create_client().await?;

        let result = client
            .get_parameter()
            .name(parameter_name)
            .with_decryption(true) // Automatically decrypt SecureString parameters
            .send()
            .await
            .map_err(|e| aws_ps_error_to_fnox(&e, parameter_name))?;

        // Get the parameter value
        result
            .parameter()
            .and_then(|p| p.value())
            .ok_or_else(|| FnoxError::ProviderInvalidResponse {
                provider: "AWS Parameter Store".to_string(),
                details: format!("Parameter '{}' has no value", parameter_name),
                hint: "The parameter exists but has no value set".to_string(),
                url: URL.to_string(),
            })
            .map(|s| s.to_string())
    }
Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
put_parameter function · rust · L289-L307 (19 LOC)
src/providers/aws_ps.rs
    pub async fn put_parameter(&self, parameter_name: &str, parameter_value: &str) -> Result<()> {
        let client = self.create_client().await?;

        client
            .put_parameter()
            .name(parameter_name)
            .value(parameter_value)
            .r#type(aws_sdk_ssm::types::ParameterType::SecureString)
            .overwrite(true) // Overwrite if exists
            .send()
            .await
            .map_err(|e| aws_ps_error_to_fnox(&e, parameter_name))?;

        tracing::debug!(
            "Stored parameter '{}' in AWS Parameter Store",
            parameter_name
        );
        Ok(())
    }
get_secret function · rust · L315-L325 (11 LOC)
src/providers/aws_ps.rs
    async fn get_secret(&self, value: &str) -> Result<String> {
        let parameter_name = self.get_parameter_name(value);
        tracing::debug!(
            "Getting parameter '{}' from AWS Parameter Store in region '{}'",
            parameter_name,
            self.region
        );

        self.get_parameter_value(&parameter_name).await
    }
test_connection function · rust · L376-L389 (14 LOC)
src/providers/aws_ps.rs
    async fn test_connection(&self) -> Result<()> {
        let client = self.create_client().await?;

        // Try to describe parameters to verify connection
        client
            .describe_parameters()
            .max_results(1)
            .send()
            .await
            .map_err(|e| aws_ps_error_to_fnox(&e, "connection-test"))?;

        Ok(())
    }
‹ prevpage 3 / 8next ›