Skip to main content

lightshuttle_secrets/source/
mod.rs

1//! Secret source trait and built-in implementations.
2
3mod env_file;
4
5pub use env_file::EnvFileSource;
6
7use std::collections::HashMap;
8
9use crate::error::SecretError;
10
11/// A source of key-value secret pairs.
12///
13/// Implementations may read from a file, the system environment, a remote vault,
14/// or any other backing store. Each call to [`load`] returns a fresh snapshot.
15/// Sources are expected to be cheap to call repeatedly; consumers may invoke
16/// [`load`] multiple times without penalty.
17///
18/// This trait is used by higher layers (e.g. `lightshuttle-manifest`) to populate
19/// interpolation contexts. Built-in implementations include [`EnvFileSource`].
20///
21/// # Implementing a custom source
22///
23/// ```
24/// use lightshuttle_secrets::SecretSource;
25/// use std::collections::HashMap;
26/// use std::sync::Arc;
27///
28/// struct MyVaultSource {
29///     url: String,
30/// }
31///
32/// impl SecretSource for MyVaultSource {
33///     fn load(&self) -> Result<HashMap<String, String>, lightshuttle_secrets::SecretError> {
34///         // Fetch from a remote vault (hypothetical)
35///         Ok([("API_TOKEN".to_string(), "vault-secret".to_string())].into())
36///     }
37///
38///     fn source_name(&self) -> &str {
39///         "MyVault"
40///     }
41/// }
42/// ```
43///
44/// [`load`]: SecretSource::load
45/// [`EnvFileSource`]: crate::EnvFileSource
46pub trait SecretSource: Send + Sync {
47    /// Load all secrets from this source.
48    ///
49    /// Returns a map of variable names to their string values. The map may be empty
50    /// if the source contains no entries. Errors (via [`SecretError`]) indicate that
51    /// the source exists but is invalid or inaccessible.
52    ///
53    /// Callers may invoke this method multiple times and expect idempotent results
54    /// (assuming the source does not change between calls).
55    fn load(&self) -> Result<HashMap<String, String>, SecretError>;
56
57    /// Human-readable name used in error messages and diagnostics.
58    ///
59    /// For example: `.env`, `vault://prod`, `environment`, or a file path.
60    /// This name should be short and suitable for logging.
61    fn source_name(&self) -> &str;
62}