systemprompt_config/bootstrap/secrets/
provider.rs1use std::future::Future;
12
13use systemprompt_manifest::secrets::Secrets;
14
15use super::SecretsBootstrapError;
16
17pub trait SecretsProvider {
18 fn fetch(&self) -> impl Future<Output = Result<SecretsDocument, SecretsBootstrapError>> + Send;
19
20 fn describe(&self) -> String;
21}
22
23#[derive(Debug, Clone, Default)]
24pub struct SecretsDocument(serde_json::Map<String, serde_json::Value>);
26
27impl SecretsDocument {
28 #[must_use]
29 pub const fn new(fields: serde_json::Map<String, serde_json::Value>) -> Self {
31 Self(fields)
32 }
33
34 pub fn merge_field(&mut self, key: impl Into<String>, value: serde_json::Value) {
36 self.0.insert(key.into(), value);
37 }
38
39 #[must_use]
40 pub fn key_names(&self) -> Vec<String> {
41 let mut names: Vec<String> = self.0.keys().cloned().collect();
42 names.sort_unstable();
43 names
44 }
45
46 #[must_use]
47 pub fn is_empty(&self) -> bool {
48 self.0.is_empty()
49 }
50
51 pub fn into_secrets(self) -> Result<Secrets, SecretsBootstrapError> {
52 let body = serde_json::to_string(&serde_json::Value::Object(self.0))
53 .map_err(SecretsBootstrapError::DocumentEncode)?;
54 Secrets::parse(&body).map_err(SecretsBootstrapError::InvalidSecretsFile)
55 }
56}