feat: add Fediverse field to actor profile and fix Update compaction

Always include a "Fediverse" PropertyValue attachment in the actor
with the canonical @handle@domain address. This ensures 2+ attachments
when combined with user-defined fields, preventing Fedify's JSON-LD
compaction from collapsing single-element arrays to plain objects
(which Mastodon's update_account_fields silently rejects).

Also fixes the root cause of profile fields not appearing on Mastodon
for existing followers: Update(Person) activities were being sent with
compacted attachment objects that Mastodon ignored.
This commit is contained in:
Ricardo
2026-02-24 12:07:50 +01:00
parent df5ccc397e
commit 963dcc3014
2 changed files with 21 additions and 1 deletions
+20
View File
@@ -721,6 +721,20 @@ export async function buildPersonActor(
personOptions.assertionMethods = keyPairs.map((k) => k.multikey); personOptions.assertionMethods = keyPairs.map((k) => k.multikey);
} }
// Build profile field attachments (PropertyValue).
// Always include a "Fediverse" field with the actor's handle — this serves
// two purposes: (1) shows the canonical fediverse address on the profile,
// and (2) ensures 2+ attachments when combined with user-defined fields,
// preventing Fedify's JSON-LD compaction from collapsing single-element
// arrays to plain objects (which Mastodon's update_account_fields rejects).
const actorUrl = ctx.getActorUri(identifier)?.href;
const fediverseField = actorUrl
? new PropertyValue({
name: "Fediverse",
value: `<a href="${actorUrl}" rel="me">@${identifier}@${new URL(actorUrl).hostname}</a>`,
})
: null;
if (profile.attachments?.length > 0) { if (profile.attachments?.length > 0) {
personOptions.attachments = profile.attachments.map( personOptions.attachments = profile.attachments.map(
(att) => (att) =>
@@ -729,6 +743,12 @@ export async function buildPersonActor(
value: formatAttachmentValue(att.value), value: formatAttachmentValue(att.value),
}), }),
); );
// Append fediverse field if not already present in user-defined fields
if (fediverseField && !profile.attachments.some((a) => a.name === "Fediverse")) {
personOptions.attachments.push(fediverseField);
}
} else if (fediverseField) {
personOptions.attachments = [fediverseField];
} }
if (profile.alsoKnownAs?.length > 0) { if (profile.alsoKnownAs?.length > 0) {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "2.0.21", "version": "2.0.22",
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
"keywords": [ "keywords": [
"indiekit", "indiekit",