Function bodies 391 total
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_unew 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_sWant 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 rtest_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/vWant 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_tWant 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) = vtry_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