Skip to main content

zeph_vault/
env.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Environment-variable vault backend.
5//!
6//! [`EnvVaultProvider`] reads secrets directly from process environment variables.
7//! Designed for quick local development and CI environments.
8
9use std::future::Future;
10use std::pin::Pin;
11
12use zeph_common::secret::VaultError;
13
14use crate::VaultProvider;
15
16/// Vault backend that reads secrets from environment variables.
17///
18/// This backend is designed for quick local development and CI environments where injecting
19/// environment variables is convenient. In production, prefer [`crate::AgeVaultProvider`].
20///
21/// [`get_secret`][VaultProvider::get_secret] reads any environment variable by name.
22/// [`list_keys`][VaultProvider::list_keys] returns only variables whose names start with
23/// `ZEPH_SECRET_`, preventing accidental exposure of unrelated process environment.
24///
25/// # Examples
26///
27/// ```no_run
28/// use zeph_vault::{EnvVaultProvider, VaultProvider as _};
29///
30/// # async fn example() {
31/// let vault = EnvVaultProvider;
32/// // Returns None for variables that are not set.
33/// let result = vault.get_secret("ZEPH_TEST_NONEXISTENT_99999").await.unwrap();
34/// assert!(result.is_none());
35/// # }
36/// ```
37pub struct EnvVaultProvider;
38
39impl VaultProvider for EnvVaultProvider {
40    fn get_secret(
41        &self,
42        key: &str,
43    ) -> Pin<Box<dyn Future<Output = Result<Option<String>, VaultError>> + Send + '_>> {
44        let key = key.to_owned();
45        Box::pin(async move { Ok(std::env::var(&key).ok()) })
46    }
47
48    fn list_keys(&self) -> Vec<String> {
49        let mut keys: Vec<String> = std::env::vars()
50            .filter(|(k, _)| k.starts_with("ZEPH_SECRET_"))
51            .map(|(k, _)| k)
52            .collect();
53        keys.sort_unstable();
54        keys
55    }
56}