Watch
0
0
Fork
You've already forked hyperhive
0

keep the matrix appservice registration in bao, with the host file as the last copy

This commit is contained in:
atlas 2026-10-27 13:52:17 +01:00
commit d5c5862654

View file

@ -129,6 +129,44 @@ pub fn swarm_appservice_token_path() -> Result<String, Error> {
Ok(format!("{prefix}/matrix/appservice-token"))
}
/// The path holding the swarm appservice's registration: the `as_token` and
/// `hs_token` the homeserver loads.
///
/// The store is the source of truth for both tokens. The matrix container keeps a
/// copy on disk that the homeserver starts from, and derives
/// [`swarm_appservice_token_path`] from the `as_token` here for
/// `swarm-controller`. It sits beside that path, under the one kind no hive's
/// policy reads, for the same reason.
///
/// # Errors
/// Never in practice: the name segment is a constant. The `Result` is
/// [`principal_prefix`]'s.
pub fn swarm_appservice_registration_path() -> Result<String, Error> {
let prefix = principal_prefix(Kind::Controller, CONTROLLER)?;
Ok(format!("{prefix}/matrix/appservice-registration"))
}
/// What [`swarm_appservice_registration_path`] holds. The registration's
/// namespaces are configuration rendered by nix, not part of it.
///
/// No `Debug` derive: both fields authenticate to the homeserver.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Registration {
/// The token the appservice presents to the homeserver.
pub as_token: String,
/// The token the homeserver presents to the appservice.
pub hs_token: String,
}
impl std::fmt::Debug for Registration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Registration")
.field("as_token", &"<redacted>")
.field("hs_token", &"<redacted>")
.finish()
}
}
/// What an account's path holds: the token, plus the homeserver it belongs to.
///
/// The homeserver rides with the token because the agent's daemon learns both
@ -266,6 +304,28 @@ mod tests {
);
}
#[test]
fn the_swarm_appservice_registration_lands_beside_its_token() {
assert_eq!(
swarm_appservice_registration_path().expect("a constant segment"),
"swarm/controller/swarm-controller/matrix/appservice-registration"
);
}
#[test]
fn a_registration_debug_prints_no_token() {
let r = Registration {
as_token: "as-secret".to_owned(),
hs_token: "hs-secret".to_owned(),
};
let shown = format!("{r:?}");
assert!(
!shown.contains("as-secret") && !shown.contains("hs-secret"),
"{shown}"
);
assert!(shown.contains("Registration"), "{shown}");
}
#[test]
fn no_hive_policy_reaches_the_swarm_appservice_token() {
// 🩸 The swarm's sender is a homeserver admin, so its token must not
@ -280,8 +340,12 @@ mod tests {
.filter_map(|p| p.strip_suffix("*\" {"))
.collect();
let reads = |path: &str| granted.iter().any(|g| path.starts_with(g));
let path = swarm_appservice_token_path().expect("a constant segment");
assert!(!reads(&path), "{path} is readable under {granted:?}");
for path in [
swarm_appservice_token_path().expect("a constant segment"),
swarm_appservice_registration_path().expect("a constant segment"),
] {
assert!(!reads(&path), "{path} is readable under {granted:?}");
}
// The control: an agent's account path IS under a hive stanza, so the
// assertion above can fail at all.
let agent = account_path("atlas", "main").expect("legal");