2 Commits

Author SHA1 Message Date
62c9bf2e4e fix: add missing RemoteActor fields in get_blocked_actors fallback 2026-05-29 04:04:08 +02:00
485c407edb feat(RemoteActor): add bio, banner_url, followers_url, following_url, also_known_as fields
Bump to 0.3.1. These fields are available on DbActor at follow/ingest
time but were discarded when constructing RemoteActor. Now populated
in from_json and follow(), so consuming repos can store and return
rich actor profiles without extra queries.
2026-05-29 04:03:23 +02:00
6 changed files with 50 additions and 7 deletions

View File

@@ -1,6 +1,24 @@
# Changelog # Changelog
## [0.3.0] — unreleased ## [0.3.1] — 2026-05-29
### Breaking changes
**`RemoteActor` has five new required fields** — struct literals must include them:
| Field | Type | Description |
|-------|------|-------------|
| `bio` | `Option<String>` | Actor biography/summary |
| `banner_url` | `Option<String>` | Banner/header image URL |
| `followers_url` | `Option<String>` | AP followers collection URL |
| `following_url` | `Option<String>` | AP following collection URL |
| `also_known_as` | `Vec<String>` | Account aliases (for Move verification) |
These are populated automatically when k-ap fetches a remote actor (via `from_json`) and when the local `follow()` method constructs a `RemoteActor` from the fetched `DbActor`. Consuming applications only need to add the new fields to their `upsert_remote_actor` / `get_remote_actor` SQL and any custom `RemoteActor` construction sites.
---
## [0.3.0] — 2026-05-28
### Breaking changes ### Breaking changes

2
Cargo.lock generated
View File

@@ -1368,7 +1368,7 @@ dependencies = [
[[package]] [[package]]
name = "k-ap" name = "k-ap"
version = "0.3.0" version = "0.3.1"
dependencies = [ dependencies = [
"activitypub_federation", "activitypub_federation",
"anyhow", "anyhow",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "k-ap" name = "k-ap"
version = "0.3.0" version = "0.3.1"
edition = "2024" edition = "2024"
description = "Generic ActivityPub protocol layer" description = "Generic ActivityPub protocol layer"
license = "MIT" license = "MIT"

View File

@@ -355,6 +355,11 @@ impl Object for DbActor {
display_name: json.name.clone(), display_name: json.name.clone(),
avatar_url: json.icon.as_ref().map(|i| i.url.to_string()), avatar_url: json.icon.as_ref().map(|i| i.url.to_string()),
outbox_url: json.outbox.as_ref().map(|u| u.to_string()), outbox_url: json.outbox.as_ref().map(|u| u.to_string()),
bio: json.summary.clone(),
banner_url: json.image.as_ref().map(|i| i.url.to_string()),
followers_url: json.followers.as_ref().map(|u| u.to_string()),
following_url: json.following.as_ref().map(|u| u.to_string()),
also_known_as: json.also_known_as.clone(),
}; };
data.actor_repo.upsert_remote_actor(actor).await?; data.actor_repo.upsert_remote_actor(actor).await?;

View File

@@ -30,6 +30,11 @@ pub struct RemoteActor {
pub display_name: Option<String>, pub display_name: Option<String>,
pub avatar_url: Option<String>, pub avatar_url: Option<String>,
pub outbox_url: Option<String>, pub outbox_url: Option<String>,
pub bio: Option<String>,
pub banner_url: Option<String>,
pub followers_url: Option<String>,
pub following_url: Option<String>,
pub also_known_as: Vec<String>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@@ -37,9 +37,14 @@ impl ActivityPubService {
.shared_inbox_url .shared_inbox_url
.as_ref() .as_ref()
.map(|u| u.to_string()), .map(|u| u.to_string()),
display_name: Some(remote_actor.username.clone()), display_name: remote_actor.display_name.clone().or_else(|| Some(remote_actor.username.clone())),
avatar_url: remote_actor.avatar_url.as_ref().map(|u| u.to_string()), avatar_url: remote_actor.avatar_url.as_ref().map(|u| u.to_string()),
outbox_url: Some(remote_actor.outbox_url.to_string()), outbox_url: Some(remote_actor.outbox_url.to_string()),
bio: remote_actor.bio.clone(),
banner_url: remote_actor.banner_url.as_ref().map(|u| u.to_string()),
followers_url: Some(remote_actor.followers_url.to_string()),
following_url: Some(remote_actor.following_url.to_string()),
also_known_as: remote_actor.also_known_as.clone(),
}; };
// Save BEFORE delivering — prevents lost state on process restart. // Save BEFORE delivering — prevents lost state on process restart.
data.follow_repo data.follow_repo
@@ -343,6 +348,11 @@ impl ActivityPubService {
display_name: None, display_name: None,
avatar_url: None, avatar_url: None,
outbox_url: None, outbox_url: None,
bio: None,
banner_url: None,
followers_url: None,
following_url: None,
also_known_as: vec![],
}, },
}; };
actors.push(actor); actors.push(actor);
@@ -382,9 +392,14 @@ impl ActivityPubService {
handle: format!("{}@{}", target.username, data.domain), handle: format!("{}@{}", target.username, data.domain),
inbox_url: format!("{}/inbox", target_actor_url), inbox_url: format!("{}/inbox", target_actor_url),
shared_inbox_url: None, shared_inbox_url: None,
display_name: Some(target.username), display_name: target.display_name.or(Some(target.username)),
avatar_url: None, avatar_url: target.avatar_url.as_ref().map(|u| u.to_string()),
outbox_url: None, outbox_url: Some(format!("{}/outbox", target_actor_url)),
bio: target.bio,
banner_url: target.banner_url.as_ref().map(|u| u.to_string()),
followers_url: Some(format!("{}/followers", target_actor_url)),
following_url: Some(format!("{}/following", target_actor_url)),
also_known_as: target.also_known_as,
}; };
data.follow_repo data.follow_repo
.add_following(local_user_id, target_as_remote, &follow_id) .add_following(local_user_id, target_as_remote, &follow_id)