Skip to main content

rtb_credentials/
bearing.rs

1//! [`CredentialBearing`] — the introspection seam used by
2//! `rtb-cli`'s `credentials` subtree to enumerate the
3//! [`CredentialRef`]s a downstream tool's config knows about.
4//!
5//! # Design rationale
6//!
7//! `credentials list / test / doctor` need to walk every credential
8//! a tool's typed config carries. Three options were considered in
9//! the v0.4 scope addendum (§4.1 / O1):
10//!
11//! - A `serde`-trait visitor that walks the deserialised `Config<C>`.
12//!   Heavyweight; needs custom plumbing.
13//! - A `schemars`-driven walk over `Config::schema()`. Brittle once
14//!   `$ref` resolution, `oneOf`/`anyOf` for `Option`, and JSON-pointer
15//!   ↔ Rust path mismatches enter the picture.
16//! - **An explicit trait downstream tools implement.** Five lines per
17//!   tool, no schema-walking, no edge cases. **Chosen.**
18//!
19//! A `#[derive(CredentialBearing)]` proc-macro is deferred to v0.5.
20
21use crate::reference::CredentialRef;
22
23/// Exposes the [`CredentialRef`]s in a downstream tool's config to
24/// `rtb-cli`'s `credentials` subtree.
25///
26/// Tools implement this on their typed `Config` struct (or any other
27/// type the `App` carries that owns its credentials):
28///
29/// ```rust
30/// use rtb_credentials::{CredentialBearing, CredentialRef};
31///
32/// struct MyConfig {
33///     anthropic: AnthropicSection,
34///     github: GithubSection,
35/// }
36/// struct AnthropicSection { api: CredentialRef }
37/// struct GithubSection   { token: CredentialRef }
38///
39/// impl CredentialBearing for MyConfig {
40///     fn credentials(&self) -> Vec<(&'static str, &CredentialRef)> {
41///         vec![
42///             ("anthropic", &self.anthropic.api),
43///             ("github",    &self.github.token),
44///         ]
45///     }
46/// }
47/// ```
48///
49/// The `&'static str` name is the human-friendly identifier surfaced
50/// by `credentials list` and accepted as the argument to
51/// `credentials add / remove / test`.
52pub trait CredentialBearing {
53    /// Yield `(name, &CredentialRef)` pairs for every credential
54    /// this value owns.
55    fn credentials(&self) -> Vec<(&'static str, &CredentialRef)>;
56}
57
58/// Blanket impl for `()` — tools that haven't typed their config
59/// yet still build. `credentials list` reports an empty set.
60impl CredentialBearing for () {
61    fn credentials(&self) -> Vec<(&'static str, &CredentialRef)> {
62        Vec::new()
63    }
64}