systemprompt_models/profile/
secrets.rs1use serde::{Deserialize, Serialize};
13
14use super::ProfileError;
15use super::vault::VaultSecretsConfig;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
18#[serde(rename_all = "lowercase")]
19pub enum SecretsSource {
20 File,
21 Env,
22 Vault,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
26#[serde(deny_unknown_fields)]
27pub struct SecretsConfig {
28 pub source: SecretsSource,
29
30 #[serde(default)]
31 pub validation: SecretsValidationMode,
32
33 #[serde(default)]
34 pub secrets_path: Option<String>,
35
36 #[serde(default)]
37 pub vault: Option<VaultSecretsConfig>,
38}
39
40impl SecretsConfig {
41 pub fn validate(&self) -> Result<(), ProfileError> {
42 match self.source {
43 SecretsSource::File | SecretsSource::Env => {
44 if matches!(self.source, SecretsSource::File)
45 && self.secrets_path.as_deref().is_none_or(str::is_empty)
46 {
47 return Err(ProfileError::SecretsPathRequired {
48 secrets_source: self.source_name(),
49 });
50 }
51 if self.vault.is_some() {
52 return Err(ProfileError::VaultBlockUnexpected {
53 secrets_source: self.source_name(),
54 });
55 }
56 },
57 SecretsSource::Vault => {
58 if self.vault.is_none() {
59 return Err(ProfileError::VaultBlockRequired);
60 }
61 },
62 }
63 Ok(())
64 }
65
66 pub fn secrets_path(&self) -> Result<&str, ProfileError> {
67 self.secrets_path
68 .as_deref()
69 .filter(|p| !p.is_empty())
70 .ok_or_else(|| ProfileError::SecretsPathRequired {
71 secrets_source: self.source_name(),
72 })
73 }
74
75 #[must_use]
76 pub const fn source_name(&self) -> &'static str {
77 match self.source {
78 SecretsSource::File => "file",
79 SecretsSource::Env => "env",
80 SecretsSource::Vault => "vault",
81 }
82 }
83}
84
85#[derive(
86 Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, schemars::JsonSchema,
87)]
88#[serde(rename_all = "lowercase")]
89pub enum SecretsValidationMode {
90 Strict,
91
92 #[default]
93 Warn,
94
95 Skip,
96}