From 1949fce620a4d8f6ae9aa88412f5dbf4b7b0f089 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Thu, 28 May 2026 00:30:58 +0200 Subject: [PATCH] fix: accept follow for migrated actor URLs via UUID lookup --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/activities.rs | 18 +++++++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cccbb67..e80a474 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "k-ap" -version = "0.1.6" +version = "0.1.7" dependencies = [ "activitypub_federation", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 45a4c1b..324b3de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "k-ap" -version = "0.1.7" +version = "0.1.8" edition = "2024" description = "Generic ActivityPub protocol layer" license = "MIT" diff --git a/src/activities.rs b/src/activities.rs index 88e2e2f..7ba8246 100644 --- a/src/activities.rs +++ b/src/activities.rs @@ -65,12 +65,20 @@ impl Activity for FollowActivity { ))); } }; - if target_domain != data.domain { - return Err(Error::bad_request(anyhow::anyhow!( - "follow target is not a local actor" - ))); + if target_domain == data.domain { + return Ok(()); } - Ok(()) + // Domain mismatch — still accept if the UUID resolves to a local user. + // This handles domain migrations where remote servers have cached the old actor URL. + if let Some(uuid) = crate::urls::extract_user_id_from_url(target_url) { + if data.user_repo.find_by_id(uuid).await.ok().flatten().is_some() { + tracing::debug!(target = %target_url, local_domain = %data.domain, "accepting follow for migrated actor URL"); + return Ok(()); + } + } + Err(Error::bad_request(anyhow::anyhow!( + "follow target is not a local actor" + ))) } async fn receive(self, data: &Data) -> Result<(), Self::Error> {