From 9355f20616435f685831a63e6dfbdcca49c08a2b Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Tue, 30 Jun 2026 01:49:30 +0200 Subject: [PATCH] fix: send Undo(Block) on unblock_actor --- CHANGELOG.md | 8 ++++++++ Cargo.toml | 2 +- src/service/follow.rs | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efb6edd..4552d94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.4.1] — 2026-06-30 + +### Bug fixes + +- `unblock_actor` now sends an `Undo(Block)` activity to the remote actor's inbox before removing them from the local blocklist, making unblocking AP-compliant. + +--- + ## [0.4.0] — 2026-05-30 ### Breaking changes diff --git a/Cargo.toml b/Cargo.toml index a04aedd..cfbe0f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "k-ap" -version = "0.4.0" +version = "0.4.1" edition = "2024" description = "Generic ActivityPub protocol layer" license = "MIT" diff --git a/src/service/follow.rs b/src/service/follow.rs index ac2857e..d8d8933 100644 --- a/src/service/follow.rs +++ b/src/service/follow.rs @@ -328,7 +328,32 @@ impl ActivityPubService { let data = self.federation_config.to_request_data(); data.blocklist_repo .remove_blocked_actor(local_user_id, actor_url) + .await?; + let local_actor = get_local_actor(local_user_id, &data) .await + .map_err(|e| anyhow::anyhow!("{e}"))?; + if let Ok(Some(remote_actor)) = data.actor_repo.get_remote_actor(actor_url).await { + let block = crate::activities::BlockActivity { + id: activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?, + kind: Default::default(), + actor: ObjectId::from(local_actor.ap_id.clone()), + object: Url::parse(actor_url)?, + }; + let undo = UndoActivity { + id: activity_url(&self.base_url).map_err(|e| anyhow::anyhow!("{e}"))?, + kind: Default::default(), + actor: ObjectId::from(local_actor.ap_id.clone()), + object: serde_json::to_value(&block).map_err(|e| anyhow::anyhow!("{e}"))?, + }; + let inbox = Url::parse(&remote_actor.inbox_url)?; + let (json, sends, inboxes) = self + .prepare_broadcast(&data, &local_actor, vec![inbox], undo) + .await?; + self.dispatch_deliveries(&data, &local_actor, inboxes, sends, json) + .await?; + tracing::info!(actor = %actor_url, "sent Undo(Block)"); + } + Ok(()) } pub async fn get_blocked_actors(