@django I see this in my logs:
{"@context":["https://www.w3.org/ns/activitystreams",{"FeatureRequest":"https://w3id.org/fep/7aa9#FeatureRequest","QuoteRequest":"toot:QuoteRequest","blurhash":"toot:blurhash","toot":"http://joinmastodon.org/ns#"}],"actor":"https://mediaformat.org/author/dev/","cc":["https://mediaformat.org/wp-json/activitypub/1.0/actors/2/followers"],"id":"https://mediaformat.org/?post_type=ap_outbox&p=10998","mediaType":"text/html","object":"https://cosocial.ca/users/evan/statuses/116817212125348410","published":"2026-06-27T01:59:31.432Z","tag":[],"to":["https://www.w3.org/ns/activitystreams#Public",null],"type":"Like"}The value of to property is not valid (contains null):
"to":["https://www.w3.org/ns/activitystreams#Public",null],absolute or relative identifiers
I think all identifiers should be absolute URIs. If we are talking about actor and collection IDs, ActivityPub requires them to be "publicly dereferencable URIs": https://www.w3.org/TR/activitypub/#obj-id
Relative identifiers are theoretical artifacts of JSON-LD processing that won't be understood by most ActivityPub implementations. The only exception is as:Public, short for https://www.w3.org/ns/activitystreams#Public, but even those are not universally supported.
-----
In the section "Privacy level", the FEP still refers to levels by name (followers and everyone): https://codeberg.org/petitminion/fep/src/commit/95fd73232dd1d8f95e6731ccb4ebbc79c5a2e330/fep/be68/fep-be68.md#privacy-level
@shlee @tchambers That is exactly what we're doing!
```
"interactionPolicy": {
"canFeature": {
"automaticApproval": [],
"manualApproval": [
"https://www.w3.org/ns/activitystreams#Public"
]
}
}
```
This may limit interoperability because audience is supposed to contain IDs (either actor IDs or collection IDs). I think many servers don't even check audience, and rely only on to and cc.
Here's how these special strings could be translated into IDs for to / cc:
- me: current actor ID.
- instance: special collection ID, similar to https://www.w3.org/ns/activitystreams#Public. Prior art: Akkoma uses https://server.example/#Public for local-only posts.
- followers: actor's followers collection ID.
- everyone: https://www.w3.org/ns/activitystreams#Public
For anyone backing up a pleroma instance DB, if you're using an sql backup (all variants of pg_dump) - YA DON'T HAVE A WORKABLE RESTORE WITHOUT SOME MASSAGING! You MUST have indexes pre-created to load data. Post creation of indexes effectively won't work...unless your DB is small.
Soooo I think I know what causes the restores to basically never complete, maybe...I'm near the limits of my psql debugging capability because I've never hit this so I actually don't exactly know how to see what the CREATE INDEX is actively doing... But tl;dr; 1.8T rows. One Point Eight TRILLION rows. But...HOW?!
The dump+load upgrade method I tend to use causes this. In the default mode it creates the schema (sequences setup, all the functions, that sort of thing, BUT NO INDEXES), loads the data, then creates the indexes.
The index it's never finishing creating is calling this function:
CREATE OR REPLACE FUNCTION public.activity_visibility(actor character varying, recipients character varying[], data jsonb) RETURNS character varying LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE SECURITY DEFINER AS $function$ DECLARE fa varchar; public varchar := 'https://www.w3.org/ns/activitystreams#Public'; BEGIN SELECT COALESCE(users.follower_address, '') into fa from public.users where users.ap_id = actor; IF data->'to' ? public THEN RETURN 'public'; ELSIF data->'cc' ? public THEN RETURN 'unlisted'; ELSIF ARRAY[fa] && recipients THEN RETURN 'private'; ELSIF not(ARRAY[fa, public] && recipients) THEN RETURN 'direct'; ELSE RETURN 'unknown'; END IF; END; $function$Well. users is ~500k rows, and this function would be called for the ~3.7M activities rows....at a point in time where users has no indexes! So each invocation of activity_visibility would scan ~500k rows, times 3.7M rows in activities, and .... that's ~1.8T rows.
Why did I footgun myself like this when pg_upgrade exists? Well, binary incompatibilities, index collation differences, in the past causing Major Heartburn. I'm not going to dive into how it might be possible to fix the dump+load procedure, since, well, yeah. But for anyone backing up a pleroma DB be warned. Either take a binary copy (f/ex pg_basebackup) or dump schema and data seperately so you can load the data with indexes. Or find another workaround!
cc @feld
GNU social JP is a social network, courtesy of GNU social JP管理人. It runs on GNU social, version 2.0.2-dev, available under the GNU Affero General Public License.
All GNU social JP content and data are available under the Creative Commons Attribution 3.0 license.