Watch
0
0
Fork
You've already forked hyperhive
0

matrix-mcp: auto-join only on accounts that live on the swarm homeserver

This commit is contained in:
damocles 2026-11-07 13:54:56 +01:00 • committed by mara
commit 513530ae35

View file

@ -130,7 +130,7 @@ pub async fn sweep_invites<S: BuildHasher>(
// from the unread sweep's `<room>` key) so the two never collide; the
// harness coalesces the wake iff the summary is new or changed, so
// re-upserting an unchanged invite every tick is a cheap no-op.
let own_server = client.user_id().map(|u| u.server_name().to_owned());
let own_server = swarm_server(client);
for room in &current {
let room_id = room.room_id().to_owned();
let inviter = room
@ -139,8 +139,8 @@ pub async fn sweep_invites<S: BuildHasher>(
.ok()
.and_then(|d| d.inviter)
.map(|m| m.user_id().to_owned());
// An invite from the swarm's own homeserver is trusted: join it
// without waking the agent. A failed join falls through to the todo
// An invite from a user of the swarm's own homeserver, to an account
// that lives on it, is trusted: join it without waking the agent. A failed join falls through to the todo
// below, so the invite is never lost.
if is_local(own_server.as_deref(), inviter.as_deref()) {
match room.join().await {
@ -179,8 +179,25 @@ pub async fn sweep_invites<S: BuildHasher>(
}
}
/// Whether `inviter` is a user of the agent's own homeserver. No known
/// inviter or no known own server counts as external.
/// The swarm homeserver's server name when `client` is an account on it, else
/// `None`. The swarm homeserver is the daemon-wide `HIVE_MATRIX_URL`; a linked
/// account on another server (matrix.org, catgirl.cloud, ...) is not on it, so
/// its same-server inviters are strangers, not swarm members.
fn swarm_server(client: &Client) -> Option<matrix_sdk::ruma::OwnedServerName> {
let swarm = reqwest::Url::parse(&crate::paths::homeserver_url()?).ok()?;
same_homeserver(&swarm, &client.homeserver())
.then(|| client.user_id().map(|u| u.server_name().to_owned()))
.flatten()
}
/// Whether two homeserver URLs point at the same host and port.
fn same_homeserver(a: &reqwest::Url, b: &reqwest::Url) -> bool {
a.host_str() == b.host_str() && a.port_or_known_default() == b.port_or_known_default()
}
/// Whether `inviter` is a user of the swarm homeserver `own` (the account's
/// server when the account is on it, else `None`). No known inviter or no
/// swarm server counts as external.
fn is_local(own: Option<&ServerName>, inviter: Option<&UserId>) -> bool {
matches!((own, inviter), (Some(own), Some(u)) if u.server_name() == own)
}
@ -197,7 +214,7 @@ pub(crate) fn invite_key(room_id: &matrix_sdk::ruma::RoomId) -> String {
mod invite_tests {
use matrix_sdk::ruma::{server_name, user_id};
use super::is_local;
use super::{is_local, same_homeserver};
#[test]
fn only_an_inviter_on_the_own_homeserver_is_local() {
@ -216,4 +233,28 @@ mod invite_tests {
assert!(!is_local(Some(own), None));
assert!(!is_local(None, Some(user_id!("@mara:pr1ma.darkest.space"))));
}
#[test]
fn an_account_is_on_the_swarm_homeserver_only_by_host_and_port() {
let u = |s: &str| reqwest::Url::parse(s).expect("url");
let swarm = u("https://matrix.pr1ma.darkest.space");
assert!(same_homeserver(
&swarm,
&u("https://matrix.pr1ma.darkest.space/")
));
assert!(same_homeserver(
&swarm,
&u("https://matrix.pr1ma.darkest.space:443")
));
// A public server is a different host, and a different port is a
// different server.
assert!(!same_homeserver(&swarm, &u("https://catgirl.cloud")));
assert!(!same_homeserver(
&swarm,
&u("https://matrix.pr1ma.darkest.space:8448")
));
// An external account gets no swarm server, so even its own
// same-server inviter is not local.
assert!(!is_local(None, Some(user_id!("@x:catgirl.cloud"))));
}
}