swarm-controller: add configured default matrix homeserver URL

Adds services.hyperhive.deploy.swarm-controller.matrixHomeserverUrl,
threaded to the daemon as SWARM_CONTROLLER_MATRIX_HOMESERVER_URL, and a
Rust helper (homeserver_or_configured_default) that lets a caller-supplied
homeserver keep overriding it. Config plumbing only: put_matrix_account
does not call the helper yet, so this is a no-op for every current caller.

Refs #4345
This commit is contained in:
atlas 2026-09-16 14:42:38 +02:00
commit c894192e4f
3 changed files with 95 additions and 2 deletions

View file

@ -1621,6 +1621,17 @@ async fn main() -> Result<()> {
}
};
// Diagnostic only — `put_matrix_account` does not call this yet (see its
// own doc comment), so this cannot change any request's outcome. Logged
// so an operator can tell the config landed before the slice that
// consults it does.
if matrix_account::homeserver_or_configured_default(None).is_none() {
tracing::debug!(
"{}; matrix-account requests still need their own homeserver",
matrix_account::DEFAULT_HOMESERVER_ENV
);
}
let config_prs = forge_client.clone().map(config_pr::spawn);
let state_forge = keep_forge_for_state(forge_client, webhook_secret.clone());

View file

@ -35,6 +35,23 @@ fn default_mode() -> String {
"token".to_owned()
}
/// Env var the controller's NixOS module sets from
/// `services.hyperhive.deploy.swarm-controller.matrixHomeserverUrl` — the
/// swarm-wide default `PutMatrixAccountRequest::homeserver` falls back to
/// when a caller omits one.
///
/// Not yet consulted by [`put_matrix_account`]: `homeserver_or_configured_default`
/// below exists for a later slice of hyperhive#4345 to call; this one only
/// wires the config through.
pub(crate) const DEFAULT_HOMESERVER_ENV: &str = "SWARM_CONTROLLER_MATRIX_HOMESERVER_URL";
/// `caller`'s own homeserver, or [`DEFAULT_HOMESERVER_ENV`] when the caller
/// left it unset. `caller` always wins — this only fills a gap it left,
/// never replaces a value it gave.
pub(crate) fn homeserver_or_configured_default(caller: Option<String>) -> Option<String> {
caller.or_else(|| std::env::var(DEFAULT_HOMESERVER_ENV).ok())
}
/// The credential to store for one agent's external matrix account.
///
/// No `Debug` derive — matching `hive-c0re::dashboard::matrix_accounts`'s
@ -339,8 +356,8 @@ async fn matrix_password_login(
#[cfg(test)]
mod tests {
use super::{
PutMatrixAccountRequest, is_reserved_account, password_fields, resolve_credential,
token_credential,
DEFAULT_HOMESERVER_ENV, PutMatrixAccountRequest, homeserver_or_configured_default,
is_reserved_account, password_fields, resolve_credential, token_credential,
};
fn request(mode: &str) -> PutMatrixAccountRequest {
@ -353,6 +370,43 @@ mod tests {
}
}
/// SAFETY: single-threaded mutation of a process env var no other test
/// in this crate reads; restored (removed) before returning.
#[test]
fn caller_supplied_homeserver_wins_even_with_a_default_configured() {
unsafe {
std::env::set_var(DEFAULT_HOMESERVER_ENV, "https://default.example.org");
}
let result =
homeserver_or_configured_default(Some("https://caller.example.org".to_owned()));
unsafe {
std::env::remove_var(DEFAULT_HOMESERVER_ENV);
}
assert_eq!(result.as_deref(), Some("https://caller.example.org"));
}
/// SAFETY: same as above.
#[test]
fn falls_back_to_the_configured_default_when_the_caller_omits_one() {
unsafe {
std::env::set_var(DEFAULT_HOMESERVER_ENV, "https://default.example.org");
}
let result = homeserver_or_configured_default(None);
unsafe {
std::env::remove_var(DEFAULT_HOMESERVER_ENV);
}
assert_eq!(result.as_deref(), Some("https://default.example.org"));
}
/// SAFETY: same as above.
#[test]
fn none_when_neither_caller_nor_default_is_set() {
unsafe {
std::env::remove_var(DEFAULT_HOMESERVER_ENV);
}
assert_eq!(homeserver_or_configured_default(None), None);
}
#[test]
fn main_is_reserved_but_nothing_else_is() {
assert!(is_reserved_account("main"));