Watch
0
0
Fork
You've already forked hyperhive
0

move stored_secret from swarm-queue-client to swarm-secret-client

The module is a rename (97% similar); everything else in the diff follows
from the move:

- stored_secret.rs: private `chain()` helper, the 8-line copy of the queue
  crate's `chain` the module called as `crate::chain`; the queue crate's
  public `chain` stays.
- stored_secret.rs: `Duration::from_mins(5)` in `MAX_REREAD_DELAY` is
  unchanged moved code, not a new use.
- swarm-secret-client Cargo.toml: gains futures-util, tokio and tracing as
  dependencies and tokio `test-util` plus tracing-subscriber as dev
  dependencies; the module and its tests use them.
- swarm-queue-client Cargo.toml: drops futures-util and the tracing-subscriber
  dev dependency, which only the moved module used; its tokio dev comment is
  reworded to the tests that remain.
- Cargo.lock: the same dependency moves, nothing else.
- swarm-queue-client lib.rs: imports `swarm_secret_client::stored_secret`,
  and its tests use a small local `Store` in place of the moved module's
  test-only `Fake`, which is no longer reachable.
- callers (hive-c0re, swarm-builder, swarm-ci-metrics, swarm-claude-login,
  swarm-controller, swarm-nats-auth, swarm-review-classifier): import path
  only; no re-export is left behind.
This commit is contained in:
atlas 2026-10-18 06:04:23 +02:00
commit f4f459f0b2
16 changed files with 83 additions and 33 deletions

View file

@ -31,6 +31,8 @@
use std::path::PathBuf;
use swarm_secret_client::stored_secret::{self, StoredSecret};
/// Everything that can go wrong reaching the swarm queue.
///
/// `thiserror` and not `anyhow` because this is a library: a caller gets a
@ -480,8 +482,6 @@ pub mod subagent_term;
/// same shapes.
pub mod review_classifier;
pub mod stored_secret;
mod startup_read;
pub use startup_read::read_with_startup_retry;
@ -588,13 +588,13 @@ pub enum ClientSecret {
File(PathBuf),
/// The plaintext, held only in this process's memory and read again
/// when the token endpoint refuses it.
Stored(stored_secret::StoredSecret),
Stored(StoredSecret),
}
impl ClientSecret {
/// The secret to read again after `error`: a held one the token endpoint
/// refused as a credential ([`stored_secret::is_credential_refusal`]).
fn refused(&self, error: &Error) -> Option<&stored_secret::StoredSecret> {
fn refused(&self, error: &Error) -> Option<&StoredSecret> {
match (self, error) {
(Self::Stored(stored), Error::TokenRefused { status, .. })
if stored_secret::is_credential_refusal(*status) =>
@ -1096,6 +1096,34 @@ mod tests {
use super::*;
/// A store holding `secret`, counting how often it is read.
struct Store {
secret: &'static str,
reads: Arc<AtomicUsize>,
}
impl Store {
fn holding(secret: &'static str) -> Self {
Self {
secret,
reads: Arc::default(),
}
}
/// `client_id`'s secret, `initial` in use, re-read from this store.
fn secret(&self, client_id: &str, initial: &str) -> StoredSecret {
let (secret, reads) = (self.secret, Arc::clone(&self.reads));
StoredSecret::new(client_id, initial.to_owned(), move || {
reads.fetch_add(1, Ordering::SeqCst);
async move { Ok(secret.to_owned()) }
})
}
fn reads(&self) -> usize {
self.reads.load(Ordering::SeqCst)
}
}
/// The names the publishers, the relays and the queue's grant all spell.
#[test]
fn term_and_agent_state_subjects_are_the_agreed_names() {
@ -1126,7 +1154,7 @@ mod tests {
async fn a_debug_print_of_a_config_does_not_carry_a_held_secret() {
let cfg = QueueConfig {
client_secret: ClientSecret::Stored(
stored_secret::tests::Fake::holding("new").secret("hive-alpha", "s3cret"),
Store::holding("new").secret("hive-alpha", "s3cret"),
),
..token_cfg()
};
@ -1180,7 +1208,7 @@ mod tests {
#[tokio::test]
async fn a_refused_secret_is_re_read_and_the_mint_retried_with_the_new_one() {
let calls = Arc::new(AtomicUsize::new(0));
let store = stored_secret::tests::Fake::holding("secret-b");
let store = Store::holding("secret-b");
let cfg = QueueConfig {
token_endpoint: stub_idp("secret-b", Arc::clone(&calls)).await,
client_secret: ClientSecret::Stored(store.secret("hive-alpha", "secret-a")),
@ -1200,7 +1228,7 @@ mod tests {
#[tokio::test]
async fn a_permanently_refused_secret_is_not_re_read_on_every_mint() {
let calls = Arc::new(AtomicUsize::new(0));
let store = stored_secret::tests::Fake::holding("secret-a");
let store = Store::holding("secret-a");
let cfg = QueueConfig {
token_endpoint: stub_idp("secret-b", Arc::clone(&calls)).await,
client_secret: ClientSecret::Stored(store.secret("hive-alpha", "secret-a")),
@ -1238,7 +1266,7 @@ mod tests {
let url = format!("http://{}/token", listener.local_addr().expect("addr"));
tokio::spawn(async move { axum::serve(listener, app).await });
let store = stored_secret::tests::Fake::holding("secret-b");
let store = Store::holding("secret-b");
let cfg = QueueConfig {
token_endpoint: url,
client_secret: ClientSecret::Stored(store.secret("hive-alpha", "secret-a")),
@ -1261,7 +1289,7 @@ mod tests {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn the_blocking_mint_re_reads_a_refused_secret() {
let calls = Arc::new(AtomicUsize::new(0));
let store = stored_secret::tests::Fake::holding("secret-b");
let store = Store::holding("secret-b");
let cfg = QueueConfig {
token_endpoint: stub_idp("secret-b", Arc::clone(&calls)).await,
client_secret: ClientSecret::Stored(store.secret("hive-alpha", "secret-a")),