← back to jdx__fnox

Function bodies 391 total

All specs Real LLM only Function bodies
search_by_title function · rust · L193-L228 (36 LOC)
src/providers/passwordstate.rs
    async fn search_by_title(&self, title: &str) -> Result<PasswordEntry> {
        let client = self.create_client()?;

        // URL encode the title for the query parameter
        let encoded_title = urlencoding::encode(title);
        let url = format!(
            "{}/api/searchpasswords/{}?Title={}",
            self.base_url, self.password_list_id, encoded_title
        );

        tracing::debug!("Searching for password by title: {}", url);

        let response = client
            .get(&url)
            .header("APIKey", &self.api_key)
            .send()
            .await
            .map_err(|e| FnoxError::ProviderApiError {
                provider: "Passwordstate".to_string(),
                details: format!("HTTP request failed: {}", e),
                hint: "Check network connectivity to the Passwordstate server".to_string(),
                url: "https://fnox.jdx.dev/providers/overview".to_string(),
            })?;

        if !response.status().is_success() {
  
get_secret function · rust · L273-L286 (14 LOC)
src/providers/passwordstate.rs
    async fn get_secret(&self, value: &str) -> Result<String> {
        tracing::debug!("Getting secret '{}' from Passwordstate", value);

        let (identifier, field, is_id) = self.parse_reference(value)?;

        let entry = if is_id {
            self.get_by_id(&identifier).await?
        } else {
            self.search_by_title(&identifier).await?
        };

        Self::extract_field(&entry, &field)
    }
test_connection function · rust · L308-L339 (32 LOC)
src/providers/passwordstate.rs
    async fn test_connection(&self) -> Result<()> {
        let client = self.create_client()?;

        // Try to access the password list to verify connection and authentication
        let url = format!("{}/api/passwords/{}", self.base_url, self.password_list_id);

        tracing::debug!("Testing Passwordstate connection: {}", url);

        let response = client
            .get(&url)
            .header("APIKey", &self.api_key)
            .send()
            .await
            .map_err(|e| FnoxError::ProviderApiError {
                provider: "Passwordstate".to_string(),
                details: format!("Failed to connect to '{}': {}", self.base_url, e),
                hint: "Check network connectivity to the Passwordstate server".to_string(),
                url: "https://fnox.jdx.dev/providers/overview".to_string(),
            })?;

        if !response.status().is_success() {
            let status = response.status();
            if status.as_u16() == 401 || status.as_u
new function · rust · L14-L24 (11 LOC)
src/providers/password_store.rs
    pub fn new(
        prefix: Option<String>,
        store_dir: Option<String>,
        gpg_opts: Option<String>,
    ) -> Self {
        Self {
            prefix,
            store_dir,
            gpg_opts,
        }
    }
build_secret_path function · rust · L27-L32 (6 LOC)
src/providers/password_store.rs
    fn build_secret_path(&self, key: &str) -> String {
        match &self.prefix {
            Some(prefix) => format!("{prefix}{key}"),
            None => key.to_string(),
        }
    }
configure_command_env function · rust · L35-L49 (15 LOC)
src/providers/password_store.rs
    fn configure_command_env(&self, cmd: &mut Command) {
        // Set custom PASSWORD_STORE_DIR if configured
        let env_store_dir = password_store_dir();
        let store_dir = self.store_dir.as_deref().or(env_store_dir.as_deref());
        if let Some(store_dir) = store_dir {
            cmd.env("PASSWORD_STORE_DIR", store_dir);
        }

        // Set custom GPG options if configured
        let env_gpg_opts = password_store_gpg_opts();
        let gpg_opts = self.gpg_opts.as_deref().or(env_gpg_opts.as_deref());
        if let Some(gpg_opts) = gpg_opts {
            cmd.env("PASSWORD_STORE_GPG_OPTS", gpg_opts);
        }
    }
execute_pass_command function · rust · L52-L118 (67 LOC)
src/providers/password_store.rs
    fn execute_pass_command(&self, args: &[&str]) -> Result<String> {
        tracing::debug!("Executing pass command with args: {args:?}");

        let mut cmd = Command::new("pass");
        self.configure_command_env(&mut cmd);

        cmd.args(args);
        cmd.stdin(std::process::Stdio::null());
        cmd.stdout(std::process::Stdio::piped());
        cmd.stderr(std::process::Stdio::piped());

        let output = cmd.output().map_err(|e| {
            if e.kind() == std::io::ErrorKind::NotFound {
                FnoxError::ProviderCliNotFound {
                    provider: "password-store".to_string(),
                    cli: "pass".to_string(),
                    install_hint: "brew install pass".to_string(),
                    url: "https://fnox.jdx.dev/providers/password-store".to_string(),
                }
            } else {
                FnoxError::ProviderCliFailed {
                    provider: "password-store".to_string(),
                    details: e.to_s
Want this analysis on your repo? https://repobility.com/scan/
get_secret function · rust · L125-L133 (9 LOC)
src/providers/password_store.rs
    async fn get_secret(&self, value: &str) -> Result<String> {
        let secret_path = self.build_secret_path(value);

        tracing::debug!("Getting secret '{secret_path}' from password-store");

        // Use `pass show` to retrieve the secret
        self.execute_pass_command(&["show", &secret_path])
    }
test_connection function · rust · L217-L226 (10 LOC)
src/providers/password_store.rs
    async fn test_connection(&self) -> Result<()> {
        tracing::debug!("Testing connection to password-store");

        // Try to list passwords to verify pass is working
        self.execute_pass_command(&["ls"])?;

        tracing::debug!("password-store connection test successful");
        Ok(())
    }
env_dependencies function · rust · L228-L236 (9 LOC)
src/providers/password_store.rs
pub fn env_dependencies() -> &'static [&'static str] {
    &[
        "PASSWORD_STORE_DIR",
        "FNOX_PASSWORD_STORE_DIR",
        "PASSWORD_STORE_GPG_OPTS",
        "FNOX_PASSWORD_STORE_GPG_OPTS",
    ]
}
password_store_dir function · rust · L237-L242 (6 LOC)
src/providers/password_store.rs
fn password_store_dir() -> Option<String> {
    std::env::var("FNOX_PASSWORD_STORE_DIR")
        .or_else(|_| std::env::var("PASSWORD_STORE_DIR"))
        .ok()
}
password_store_gpg_opts function · rust · L243-L248 (6 LOC)
src/providers/password_store.rs
fn password_store_gpg_opts() -> Option<String> {
    std::env::var("FNOX_PASSWORD_STORE_GPG_OPTS")
        .or_else(|_| std::env::var("PASSWORD_STORE_GPG_OPTS"))
        .ok()
}
new function · rust · L29-L34 (6 LOC)
src/providers/resolver.rs
    pub fn new() -> Self {
        Self {
            provider_stack: HashSet::new(),
            resolution_path: Vec::new(),
        }
    }
resolve_provider_config function · rust · L79-L88 (10 LOC)
src/providers/resolver.rs
pub async fn resolve_provider_config(
    config: &Config,
    profile: &str,
    provider_name: &str,
    provider_config: &ProviderConfig,
) -> Result<ResolvedProviderConfig> {
    let mut ctx = ResolutionContext::new();
    resolve_provider_config_with_context(config, profile, provider_name, provider_config, &mut ctx)
        .await
}
resolve_provider_config_with_context function · rust · L91-L126 (36 LOC)
src/providers/resolver.rs
pub fn resolve_provider_config_with_context<'a>(
    config: &'a Config,
    profile: &'a str,
    provider_name: &'a str,
    provider_config: &'a ProviderConfig,
    ctx: &'a mut ResolutionContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<ResolvedProviderConfig>> + Send + 'a>>
{
    Box::pin(async move {
        // Check for circular dependency
        if ctx.is_resolving(provider_name) {
            return Err(FnoxError::ProviderConfigCycle {
                provider: provider_name.to_string(),
                cycle: format!("{} -> {}", ctx.path_string(), provider_name),
            });
        }

        // Push onto resolution stack
        ctx.push(provider_name);

        // Resolve using generated match (capturing result to ensure cleanup on error)
        let result = super::generated::providers_resolver::resolve_provider_config_match(
            config,
            profile,
            provider_name,
            provider_config,
            ctx,
       
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
resolve_required function · rust · L129-L145 (17 LOC)
src/providers/resolver.rs
pub fn resolve_required<'a>(
    config: &'a Config,
    profile: &'a str,
    provider_name: &'a str,
    _field_name: &'a str,
    value: &'a StringOrSecretRef,
    ctx: &'a mut ResolutionContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String>> + Send + 'a>> {
    Box::pin(async move {
        match value {
            StringOrSecretRef::Literal(s) => Ok(s.clone()),
            StringOrSecretRef::SecretRef { secret } => {
                resolve_secret_ref(config, profile, provider_name, secret, ctx).await
            }
        }
    })
}
resolve_option function · rust · L148-L166 (19 LOC)
src/providers/resolver.rs
pub fn resolve_option<'a>(
    config: &'a Config,
    profile: &'a str,
    provider_name: &'a str,
    value: &'a OptionStringOrSecretRef,
    ctx: &'a mut ResolutionContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<String>>> + Send + 'a>> {
    Box::pin(async move {
        match value.as_ref() {
            None => Ok(None),
            Some(StringOrSecretRef::Literal(s)) => Ok(Some(s.clone())),
            Some(StringOrSecretRef::SecretRef { secret }) => {
                let resolved =
                    resolve_secret_ref(config, profile, provider_name, secret, ctx).await?;
                Ok(Some(resolved))
            }
        }
    })
}
resolve_secret_ref function · rust · L173-L237 (65 LOC)
src/providers/resolver.rs
fn resolve_secret_ref<'a>(
    config: &'a Config,
    profile: &'a str,
    provider_name: &'a str,
    secret_name: &'a str,
    ctx: &'a mut ResolutionContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String>> + Send + 'a>> {
    Box::pin(async move {
        // First, try to find the secret in config
        let secrets = config.get_secrets(profile).unwrap_or_default();

        if let Some(secret_config) = secrets.get(secret_name) {
            // Secret found in config - resolve it
            if let Some(secret_provider_name) = secret_config.provider()
                && let Some(provider_value) = secret_config.value()
            {
                // This secret uses a provider - need to resolve that provider first
                let providers = config.get_providers(profile);
                if let Some(secret_provider_config) = providers.get(secret_provider_name) {
                    // Recursively resolve the provider's config
                    let r
test_resolution_context_cycle_detection function · rust · L244-L263 (20 LOC)
src/providers/resolver.rs
    fn test_resolution_context_cycle_detection() {
        let mut ctx = ResolutionContext::new();

        assert!(!ctx.is_resolving("provider_a"));

        ctx.push("provider_a");
        assert!(ctx.is_resolving("provider_a"));
        assert!(!ctx.is_resolving("provider_b"));

        ctx.push("provider_b");
        assert!(ctx.is_resolving("provider_a"));
        assert!(ctx.is_resolving("provider_b"));

        ctx.pop();
        assert!(ctx.is_resolving("provider_a"));
        assert!(!ctx.is_resolving("provider_b"));

        ctx.pop();
        assert!(!ctx.is_resolving("provider_a"));
    }
test_resolution_path function · rust · L266-L274 (9 LOC)
src/providers/resolver.rs
    fn test_resolution_path() {
        let mut ctx = ResolutionContext::new();

        ctx.push("a");
        ctx.push("b");
        ctx.push("c");

        assert_eq!(ctx.path_string(), "a -> b -> c");
    }
json_schema function · rust · L38-L58 (21 LOC)
src/providers/secret_ref.rs
    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
        // Get the string schema
        let string_schema = generator.subschema_for::<String>();

        // Create the oneOf schema: string or { secret: string }
        json_schema!({
            "description": "Either a literal string or a reference to a secret",
            "oneOf": [
                string_schema,
                {
                    "type": "object",
                    "properties": {
                        "secret": { "type": "string" }
                    },
                    "required": ["secret"],
                    "additionalProperties": false
                }
            ]
        })
    }
secret_name function · rust · L70-L75 (6 LOC)
src/providers/secret_ref.rs
    pub fn secret_name(&self) -> Option<&str> {
        match self {
            Self::SecretRef { secret } => Some(secret),
            Self::Literal(_) => None,
        }
    }
as_literal function · rust · L78-L83 (6 LOC)
src/providers/secret_ref.rs
    pub fn as_literal(&self) -> Option<&str> {
        match self {
            Self::Literal(s) => Some(s),
            Self::SecretRef { .. } => None,
        }
    }
All rows above produced by Repobility · https://repobility.com
deserialize function · rust · L87-L102 (16 LOC)
src/providers/secret_ref.rs
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(untagged)]
        enum Helper {
            Literal(String),
            SecretRef { secret: String },
        }

        match Helper::deserialize(deserializer)? {
            Helper::Literal(s) => Ok(StringOrSecretRef::Literal(s)),
            Helper::SecretRef { secret } => Ok(StringOrSecretRef::SecretRef { secret }),
        }
    }
serialize function · rust · L106-L119 (14 LOC)
src/providers/secret_ref.rs
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Self::Literal(s) => s.serialize(serializer),
            Self::SecretRef { secret } => {
                use serde::ser::SerializeMap;
                let mut map = serializer.serialize_map(Some(1))?;
                map.serialize_entry("secret", secret)?;
                map.end()
            }
        }
    }
secret_name function · rust · L179-L184 (6 LOC)
src/providers/secret_ref.rs
    pub fn secret_name(&self) -> Option<&str> {
        match &self.0 {
            Some(StringOrSecretRef::SecretRef { secret }) => Some(secret),
            _ => None,
        }
    }
deserialize function · rust · L194-L200 (7 LOC)
src/providers/secret_ref.rs
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let opt: Option<StringOrSecretRef> = Option::deserialize(deserializer)?;
        Ok(OptionStringOrSecretRef(opt))
    }
serialize function · rust · L204-L212 (9 LOC)
src/providers/secret_ref.rs
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match &self.0 {
            Some(v) => v.serialize(serializer),
            None => serializer.serialize_none(),
        }
    }
test_string_or_secret_ref_literal_deser function · rust · L238-L249 (12 LOC)
src/providers/secret_ref.rs
    fn test_string_or_secret_ref_literal_deser() {
        let toml_str = r#"field = "literal-value""#;
        #[derive(Deserialize)]
        struct Test {
            field: StringOrSecretRef,
        }
        let parsed: Test = toml_edit::de::from_str(toml_str).unwrap();
        assert_eq!(
            parsed.field,
            StringOrSecretRef::Literal("literal-value".to_string())
        );
    }
test_string_or_secret_ref_secret_ref_deser function · rust · L252-L265 (14 LOC)
src/providers/secret_ref.rs
    fn test_string_or_secret_ref_secret_ref_deser() {
        let toml_str = r#"field = { secret = "MY_SECRET" }"#;
        #[derive(Deserialize)]
        struct Test {
            field: StringOrSecretRef,
        }
        let parsed: Test = toml_edit::de::from_str(toml_str).unwrap();
        assert_eq!(
            parsed.field,
            StringOrSecretRef::SecretRef {
                secret: "MY_SECRET".to_string()
            }
        );
    }
test_string_or_secret_ref_literal_ser function · rust · L268-L278 (11 LOC)
src/providers/secret_ref.rs
    fn test_string_or_secret_ref_literal_ser() {
        #[derive(Serialize)]
        struct Test {
            field: StringOrSecretRef,
        }
        let value = Test {
            field: StringOrSecretRef::Literal("test".to_string()),
        };
        let serialized = toml_edit::ser::to_string(&value).unwrap();
        assert_eq!(serialized.trim(), r#"field = "test""#);
    }
Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
test_string_or_secret_ref_secret_ref_ser function · rust · L281-L294 (14 LOC)
src/providers/secret_ref.rs
    fn test_string_or_secret_ref_secret_ref_ser() {
        #[derive(Serialize)]
        struct Test {
            field: StringOrSecretRef,
        }
        let value = Test {
            field: StringOrSecretRef::SecretRef {
                secret: "MY_SECRET".to_string(),
            },
        };
        let serialized = toml_edit::ser::to_string(&value).unwrap();
        assert!(serialized.contains("secret"));
        assert!(serialized.contains("MY_SECRET"));
    }
test_option_string_or_secret_ref_none function · rust · L297-L306 (10 LOC)
src/providers/secret_ref.rs
    fn test_option_string_or_secret_ref_none() {
        let toml_str = r#""#;
        #[derive(Deserialize)]
        struct Test {
            #[serde(default)]
            field: OptionStringOrSecretRef,
        }
        let parsed: Test = toml_edit::de::from_str(toml_str).unwrap();
        assert!(parsed.field.is_none());
    }
test_option_string_or_secret_ref_literal function · rust · L309-L319 (11 LOC)
src/providers/secret_ref.rs
    fn test_option_string_or_secret_ref_literal() {
        let toml_str = r#"field = "value""#;
        #[derive(Deserialize)]
        struct Test {
            #[serde(default)]
            field: OptionStringOrSecretRef,
        }
        let parsed: Test = toml_edit::de::from_str(toml_str).unwrap();
        assert!(parsed.field.is_some());
        assert_eq!(parsed.field.as_literal(), Some("value"));
    }
test_option_string_or_secret_ref_secret function · rust · L322-L333 (12 LOC)
src/providers/secret_ref.rs
    fn test_option_string_or_secret_ref_secret() {
        let toml_str = r#"field = { secret = "SECRET_NAME" }"#;
        #[derive(Deserialize)]
        struct Test {
            #[serde(default)]
            field: OptionStringOrSecretRef,
        }
        let parsed: Test = toml_edit::de::from_str(toml_str).unwrap();
        assert!(parsed.field.is_some());
        assert!(parsed.field.has_secret_ref());
        assert_eq!(parsed.field.secret_name(), Some("SECRET_NAME"));
    }
test_helpers function · rust · L336-L348 (13 LOC)
src/providers/secret_ref.rs
    fn test_helpers() {
        let literal = StringOrSecretRef::Literal("test".to_string());
        assert!(!literal.is_secret_ref());
        assert_eq!(literal.as_literal(), Some("test"));
        assert_eq!(literal.secret_name(), None);

        let secret = StringOrSecretRef::SecretRef {
            secret: "SECRET".to_string(),
        };
        assert!(secret.is_secret_ref());
        assert_eq!(secret.as_literal(), None);
        assert_eq!(secret.secret_name(), Some("SECRET"));
    }
new function · rust · L14-L26 (13 LOC)
src/providers/vault.rs
    pub fn new(
        address: String,
        path: Option<String>,
        token: Option<String>,
        namespace: Option<String>,
    ) -> Self {
        Self {
            address,
            path,
            token,
            namespace,
        }
    }
get_secret_path function · rust · L27-L33 (7 LOC)
src/providers/vault.rs
    fn get_secret_path(&self, key: &str) -> String {
        match &self.path {
            Some(path) => format!("{}/{}", path.trim_end_matches('/'), key),
            None => format!("secret/{}", key),
        }
    }
execute_vault_command function · rust · L36-L121 (86 LOC)
src/providers/vault.rs
    fn execute_vault_command(&self, args: &[&str]) -> Result<String> {
        tracing::debug!("Executing vault command with args: {:?}", args);

        let mut cmd = Command::new("vault");

        // Set VAULT_ADDR from provider config
        cmd.env("VAULT_ADDR", &self.address);

        // Set VAULT_NAMESPACE if provided
        if let Some(namespace) = &self.namespace {
            tracing::debug!("Setting VAULT_NAMESPACE to '{}'", namespace);
            cmd.env("VAULT_NAMESPACE", namespace);
        }

        // Set VAULT_TOKEN from provider config or environment
        let env_token = vault_token();
        let token = self.token.as_ref().or(env_token.as_ref()).ok_or_else(|| {
            FnoxError::ProviderAuthFailed {
                provider: "HashiCorp Vault".to_string(),
                details: "VAULT_TOKEN not set".to_string(),
                hint: "Set VAULT_TOKEN in provider config or environment".to_string(),
                url: "https://fnox.jdx.dev/providers/v
Want this analysis on your repo? https://repobility.com/scan/
test_connection function · rust · L165-L174 (10 LOC)
src/providers/vault.rs
    async fn test_connection(&self) -> Result<()> {
        tracing::debug!("Testing connection to Vault at {}", self.address);

        // Try to get Vault status
        let args = vec!["status"];
        self.execute_vault_command(&args)?;

        Ok(())
    }
put_secret function · rust · L175-L191 (17 LOC)
src/providers/vault.rs
    async fn put_secret(&self, key: &str, value: &str) -> Result<String> {
        let secret_path = self.get_secret_path(key);

        tracing::debug!("Writing secret '{}' to HashiCorp Vault", secret_path);

        // Use vault kv put command: vault kv put <path> value=<value>
        let value_arg = format!("value={}", value);
        let args = vec!["kv", "put", &secret_path, &value_arg];

        self.execute_vault_command(&args)?;

        tracing::debug!("Successfully wrote secret '{}' to Vault", secret_path);

        // Return the key name to store in config
        Ok(key.to_string())
    }
vault_token function · rust · L197-L202 (6 LOC)
src/providers/vault.rs
fn vault_token() -> Option<String> {
    env::var("FNOX_VAULT_TOKEN")
        .or_else(|_| env::var("VAULT_TOKEN"))
        .ok()
}
extract_json_path function · rust · L15-L31 (17 LOC)
src/secret_resolver.rs
fn extract_json_path(json_str: &str, path: &str) -> Result<String> {
    let value: serde_json::Value = serde_json::from_str(json_str)
        .map_err(|e| FnoxError::Config(format!("Failed to parse JSON secret: {}", e)))?;

    let mut current = &value;
    for part in split_key_path(path) {
        current = current.get(&part).ok_or_else(|| {
            FnoxError::Config(format!("JSON path '{}' not found in secret", path))
        })?;
    }

    match current {
        serde_json::Value::String(s) => Ok(s.clone()),
        serde_json::Value::Null => Ok("null".to_string()),
        other => Ok(other.to_string()), // Numbers, bools, arrays, objects
    }
}
split_key_path function · rust · L39-L62 (24 LOC)
src/secret_resolver.rs
fn split_key_path(key: &str) -> Vec<String> {
    let mut parts = Vec::new();
    let mut current = String::new();
    let mut chars = key.chars();

    while let Some(c) = chars.next() {
        if c == '\\' {
            // Escape the next character.
            if let Some(next_char) = chars.next() {
                current.push(next_char);
            } else {
                // A trailing backslash is treated as a literal backslash.
                current.push('\\');
            }
        } else if c == '.' {
            parts.push(std::mem::take(&mut current));
        } else {
            current.push(c);
        }
    }

    parts.push(current);
    parts
}
apply_post_processing function · rust · L66-L75 (10 LOC)
src/secret_resolver.rs
fn apply_post_processing(value: String, secret_config: &SecretConfig) -> Result<String> {
    if let Some(ref json_path) = secret_config.json_path {
        if json_path.is_empty() {
            return Err(FnoxError::Config("json_path must not be empty".to_string()));
        }
        extract_json_path(&value, json_path)
    } else {
        Ok(value)
    }
}
create_provider_not_configured_error function · rust · L78-L110 (33 LOC)
src/secret_resolver.rs
fn create_provider_not_configured_error(
    provider_name: &str,
    profile: &str,
    secret_config: &SecretConfig,
    config: &Config,
) -> FnoxError {
    // Find similar provider names for suggestion
    let providers = config.get_providers(profile);
    let available_providers: Vec<_> = providers.keys().map(|s| s.as_str()).collect();
    let similar = find_similar(provider_name, available_providers);
    let suggestion = format_suggestions(&similar);

    // Try to create a source-aware error if we have both source path and span
    if let (Some(path), Some(span)) = (&secret_config.source_path, secret_config.provider_span())
        && let Some(src) = source_registry::get_named_source(path)
    {
        return FnoxError::ProviderNotConfiguredWithSource {
            provider: provider_name.to_string(),
            profile: profile.to_string(),
            suggestion,
            src,
            span: SourceSpan::new(span.start.into(), span.end - span.start),
        };
    }
resolve_if_missing_behavior function · rust · L119-L161 (43 LOC)
src/secret_resolver.rs
pub fn resolve_if_missing_behavior(secret_config: &SecretConfig, config: &Config) -> IfMissing {
    Settings::try_get()
        .ok()
        .and_then(|s| {
            // CLI flag or FNOX_IF_MISSING env var (highest priority)
            s.if_missing
                .as_ref()
                .map(|value| match value.to_lowercase().as_str() {
                    "error" => IfMissing::Error,
                    "warn" => IfMissing::Warn,
                    "ignore" => IfMissing::Ignore,
                    _ => {
                        eprintln!(
                            "Warning: Invalid if_missing value '{}', using 'warn'",
                            value
                        );
                        IfMissing::Warn
                    }
                })
        })
        .or(secret_config.if_missing)
        .or(config.if_missing)
        .or_else(|| {
            // FNOX_IF_MISSING_DEFAULT fallback before hard-coded default
            Settings::try_get().ok().and_t
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
handle_provider_error function · rust · L165-L193 (29 LOC)
src/secret_resolver.rs
pub fn handle_provider_error(
    key: &str,
    error: FnoxError,
    if_missing: IfMissing,
    use_tracing: bool,
) -> Option<FnoxError> {
    match if_missing {
        IfMissing::Error => {
            if use_tracing {
                tracing::error!("Error resolving secret '{}': {}", key, error);
            } else {
                eprintln!("Error resolving secret '{}': {}", key, error);
            }
            Some(error)
        }
        IfMissing::Warn => {
            if use_tracing {
                tracing::warn!("Error resolving secret '{}': {}", key, error);
            } else {
                eprintln!("Warning: Error resolving secret '{}': {}", key, error);
            }
            None
        }
        IfMissing::Ignore => {
            // Silently skip
            None
        }
    }
}
resolve_secret function · rust · L202-L233 (32 LOC)
src/secret_resolver.rs
pub async fn resolve_secret(
    config: &Config,
    profile: &str,
    key: &str,
    secret_config: &SecretConfig,
) -> Result<Option<String>> {
    // Try to get a value from any source (provider, default, or env var)
    let value_to_process =
        // Priority 1: Provider (if specified and has a value)
        if let Some(value) = try_resolve_from_provider(config, profile, secret_config).await? {
            Some(value)
        // Priority 2: Default value
        } else if let Some(default) = &secret_config.default {
            tracing::debug!("Using default value for secret '{}'", key);
            Some(default.clone())
        // Priority 3: Environment variable
        } else if let Ok(env_value) = env::var(key) {
            tracing::debug!("Found secret '{}' in current environment", key);
            Some(env_value)
        } else {
            None
        };

    // Apply post-processing to whatever value we found (e.g., JSON path extraction)
    if let Some(value) = v
try_resolve_from_provider function · rust · L234-L272 (39 LOC)
src/secret_resolver.rs
async fn try_resolve_from_provider(
    config: &Config,
    profile: &str,
    secret_config: &SecretConfig,
) -> Result<Option<String>> {
    // Only try provider if we have a value to pass to it
    let Some(provider_value) = secret_config.value() else {
        return Ok(None);
    };

    // Determine which provider to use
    let provider_name = if let Some(provider_name) = secret_config.provider() {
        // Explicit provider specified
        provider_name.to_string()
    } else if let Some(default_provider) = config.get_default_provider(profile)? {
        // Use default provider
        default_provider
    } else {
        // No provider configured, can't resolve
        return Ok(None);
    };

    // Get the provider config
    let providers = config.get_providers(profile);
    let provider_config = providers.get(&provider_name).ok_or_else(|| {
        create_provider_not_configured_error(&provider_name, profile, secret_config, config)
    })?;

    // Try to resolve th
‹ prevpage 6 / 8next ›