fix(ap): protocol compliance — actor verification, on_unlike, Move, bto/bcc
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m31s
test / unit (pull_request) Successful in 16m12s
test / integration (pull_request) Failing after 16m53s

- Add verify() to Accept/Reject (actor must match Follow target)
- Add verify() to Create/Update (actor must match attributedTo)
- Add verify() to Delete (actor domain must match object domain)
- Fix UpdateActivity passing wrapper id instead of object id to on_update
- Implement on_unlike (was no-op stub) — publishes LikeRemoved event
- BlockActivity now removes remote actor as follower, not just following
- Add MoveActivity (account migration) to InboxActivities enum
- Add bto/bcc fields to CreateActivity for blind DM support
- http_signature_compat(true) restricted to debug mode only
- Announce of non-local object logs debug instead of silent drop
- postgres-federation: get_followers/get_following_page/count_following
  now consistently filter by status='accepted'
This commit is contained in:
2026-05-15 12:52:37 +02:00
parent 314dad5451
commit 711b3ec63b
6 changed files with 166 additions and 8 deletions

View File

@@ -261,7 +261,44 @@ impl ApObjectHandler for ThoughtsObjectHandler {
Ok(())
}
async fn on_unlike(&self, _object_url: &url::Url, _actor_url: &url::Url) -> anyhow::Result<()> {
async fn on_unlike(&self, object_url: &url::Url, actor_url: &url::Url) -> anyhow::Result<()> {
let thought_uuid = object_url
.path()
.strip_prefix(THOUGHTS_PATH_PREFIX)
.and_then(|s| s.split('/').next())
.and_then(|s| uuid::Uuid::parse_str(s).ok());
let thought_uuid = match thought_uuid {
Some(u) => u,
None => {
tracing::debug!(object = %object_url, "on_unlike: not a local thought URL, skipping");
return Ok(());
}
};
let actor_user_id = self
.repo
.find_remote_actor_id(actor_url)
.await
.map_err(|e| anyhow!("{e}"))?;
let actor_user_id = match actor_user_id {
Some(id) => id,
None => {
tracing::debug!(actor = %actor_url, "on_unlike: remote actor not interned, skipping");
return Ok(());
}
};
if let Some(ep) = &self.event_publisher {
ep.publish(&domain::events::DomainEvent::LikeRemoved {
user_id: actor_user_id,
thought_id: domain::value_objects::ThoughtId::from_uuid(thought_uuid),
})
.await
.map_err(|e| anyhow!("{e}"))?;
}
Ok(())
}