Skip to main content

aa_core/storage/
credential_store.rs

1//! [`CredentialStore`] — storage for named secret material.
2
3use super::Result;
4use async_trait::async_trait;
5
6/// Stores and retrieves named secret material as opaque bytes.
7///
8/// Keys are caller-defined names (for example `"openai/api_key"`); values are
9/// opaque byte strings so the contract stays agnostic to the secret's encoding.
10/// Backends are expected to encrypt at rest; this trait only defines the access
11/// contract, not the protection mechanism.
12///
13/// # Example
14///
15/// ```
16/// use aa_core::storage::{CredentialStore, Result, StorageError};
17/// use async_trait::async_trait;
18///
19/// /// A store that holds no secrets.
20/// struct EmptyCredentialStore;
21///
22/// #[async_trait]
23/// impl CredentialStore for EmptyCredentialStore {
24///     async fn get_secret(&self, key: &str) -> Result<Vec<u8>> {
25///         Err(StorageError::NotFound(key.to_owned()))
26///     }
27///
28///     async fn put_secret(&self, _key: &str, _value: Vec<u8>) -> Result<()> {
29///         Ok(())
30///     }
31///
32///     async fn delete_secret(&self, _key: &str) -> Result<()> {
33///         Ok(())
34///     }
35/// }
36/// ```
37#[async_trait]
38pub trait CredentialStore: Send + Sync {
39    /// Return the secret bytes stored under `key`.
40    ///
41    /// Returns [`StorageError::NotFound`](super::StorageError::NotFound) when no
42    /// secret exists for the key.
43    async fn get_secret(&self, key: &str) -> Result<Vec<u8>>;
44
45    /// Store `value` under `key`, overwriting any existing secret.
46    async fn put_secret(&self, key: &str, value: Vec<u8>) -> Result<()>;
47
48    /// Delete the secret stored under `key`.
49    ///
50    /// Idempotent: deleting an absent key succeeds.
51    async fn delete_secret(&self, key: &str) -> Result<()>;
52}