Watch
0
0
Fork
You've already forked hyperhive
0
Commit graph hyperhive/swarm-controller/src/forge/api.rs
Author SHA1 Message Date
atlas
f4f459f0b2 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.
2026-10-18 09:00:08 +02:00
atlas
6ba29c4d33 swarm-controller: re-read the forge token from the store when the forge rejects it
The controller read its forge token from the swarm secret store once, when
its client slot filled, and kept sending it until the daemon restarted. A
token the forge re-minted or revoked left every forge-backed path failing
with 401 until someone restarted the controller, and a restart drops the
runtime-only job graph.

Every forge request now goes through `forge::api::Api::call`. On a 401 it
asks a `StoredSecret` (the queue clients' debounced, single-flight re-read
with backoff) for a token to try instead, rebuilds the forgejo client with
it, and sends the request once more. A second 401, or a store still holding
the refused token, surfaces the error as before. Only 401 counts: unlike an
IdP, the forge answers 400 to a malformed request, and a re-read started by
one would put a real 401 that follows inside the backoff.

forgejo-api bakes the token into its own reqwest client's default headers
and takes no client or middleware from outside, so there is no single
request function to hook. Each `self.api.<endpoint>(..)` site becomes
`self.api.call(|api| api.<endpoint>(..).into_future())`; option structs a
site moved into the call are cloned, since the closure can run twice. The
`OnceLock<Arc<Client>>` slot and its `get()` callers are unchanged.

Refs #5017
2026-10-14 10:16:18 +02:00