1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! OS-keyring-backed implementation of `evault-core`'s
//! [`SecretStore`](evault_core::traits::SecretStore) trait.
//!
//! [`OsKeyringSecretStore`] delegates to the platform's native credential
//! store via the `keyring` crate:
//!
//! - **Windows**: Credential Manager (DPAPI).
//! - **macOS**: Keychain.
//! - **Linux/BSD**: D-Bus Secret Service (`gnome-keyring`, `KWallet`, …).
//!
//! Each variable's value is stored under the canonical service identifier
//! `"evault"` keyed by the variable's UUID. The mapping is one credential
//! per variable so platform tooling can audit individual secrets.
//!
//! # Error semantics
//!
//! Per the [`evault_core::traits::SecretStore`] contract:
//! - `get` returns `Ok(None)` when no credential exists for the supplied
//! id. Platform "item not found" codes are the only path to this
//! `None`; every other backend error propagates as
//! [`evault_core::error::SecretError::Backend`] or
//! [`evault_core::error::SecretError::Unavailable`].
//! - `delete` is idempotent: deleting an absent item is `Ok(())`.
//! - `put` always either writes or returns an error — it never silently
//! fails.
//!
//! # Operational notes
//!
//! - **Single backend per process.** `keyring 4.x` keeps a single
//! process-wide active backend (`use_native_store`, `use_named_store`,
//! `release_store`). This crate initialises it once via
//! [`std::sync::OnceLock`]. **Do not** call any of those keyring-crate
//! functions yourself in the same process — a host that swaps the
//! backend later may route subsequent operations to an in-memory
//! `sample` store that does not persist.
//! - **`Backend("ambiguous")` is a security signal.** Because every
//! variable lives at a fixed `("evault", <uuid>)` pair, an
//! ambiguity error means another application is writing to the same
//! namespace. Treat it as tampering, not as a routine backend error.
//! - **Init result is sticky.** If the first call fails (e.g. the user
//! hasn't started gnome-keyring yet), subsequent calls in the same
//! process see the cached failure. A CLI re-launch starts fresh; a
//! daemon would need a future "reset" hook.
//!
//! # Examples
//!
//! ```ignore
//! use evault_core::traits::SecretStore;
//! use evault_core::crypto::{ExposeSecret, SecretString};
//! use evault_core::model::VarId;
//! use evault_store_keyring::OsKeyringSecretStore;
//!
//! let store = OsKeyringSecretStore::new().expect("init keyring");
//! let id = VarId::new_v4();
//! store.put(id, SecretString::from(String::from("hunter2"))).unwrap();
//! let got = store.get(id).unwrap().expect("present");
//! assert_eq!(got.expose_secret(), "hunter2");
//! store.delete(id).unwrap();
//! ```
pub use OsKeyringSecretStore;