Pasture: Pixelfed and WordPress join

Pixelfed 0.14.4 (FrankenPHP with Horizon and the scheduler, on the shared
Postgres and Redis) and WordPress 6 with ActivityPub 9.3.1 (on a new shared
MySQL, WP-Cron run by a sidecar) are peers now, each with its scenario:
Pixelfed 26 checks (photos both ways with alt text, its place arriving as
Rome with its coordinates, comments, likes, a boost, edits and deletes),
WordPress 17 (an Article with its title, our reply, like and boost kept as
comments of their kinds, its edit and removal). Pixelfed has a town driver
and a pair spec: 145 checks pass, 2 expected (G-0007).

What they showed: Pixelfed names our posts by their page (fixed in
26dac40); on PostgreSQL its migration making caption nullable never runs,
so every remote boost failed (the pasture applies it); it files a DM it
fetches as followers-only (G-0007, upstream); Passport refuses a token
whose user id equals its client's id. WordPress signs with RFC 9421
first, which PrivaPub now verifies (c5a69d2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-05 07:01:38 +02:00
1 parent c5a69d240a
commit 01e5aa4ddd
14 files changed
+601 -4

No files matched your search

+27 -1
View File
@@ -682,9 +682,30 @@ without a port, before it gives out its OAuth client.
- ~~**P2:** Pixelfed `location` → own `privapub.place`, display only and never re-federated~~ done:
`ObjectShapes.NotePlace` keeps a `Place` with coordinates (Pixelfed sends them as strings) in `Post.Place`, an edit
replaces it, and nothing renders it back out.
- **P2:** `commentsEnabled: false` disables replies.
- ~~**P2:** `commentsEnabled: false` disables replies~~ done (2026-10-05): the post is locked, as a community's lock
locks it, and our replies are refused.
- **P3:** ignore `Add{Story}` without an error; answer `FeatureRequest` with `Reject`.
**Pasture evidence (2026-10-05, Pixelfed 0.14.4, `tools/pasture/scenarios/pixelfed.sh`):** 26 checks pass. Follows
both ways; photos both ways with their alt text, Pixelfed's with its place (Rome, from its own list of cities) shown
with its coordinates and its picture served through our proxy; comments both ways; likes both ways, a boost and an
unlike; an edit and deletes both ways; statistics. The town's pair (`specs/pixelfed-pair.json`) passes 145 checks with
2 expected failures (G-0007). What it showed:
- **Pixelfed names our post by its page** (`/@name/<id>`, the post's `url`) in its Like, Announce and Undo, so its
likes were dropped as unknown objects until PrivaPub took a page address of its own posts for their id (26dac40).
- **A remote post is kept with its `url` as `uri`** and its id as `object_url`; anything read from its database must
match either.
- **On PostgreSQL every remote boost failed** (and every DM, by Pixelfed's own note): the migration meant to make
`caption` and `rendered` nullable there checks for a connection named `postgres`, while Laravel's is `pgsql`, so it
never runs. The pasture applies it; a Pixelfed on PostgreSQL in the wild still has the bug.
- **A delivered DM is handled as one, a fetched one is not** (G-0007): resolving a DM's address makes Pixelfed's instance
actor fetch it, which we allow since a recipient lives there, and `getScope` files it as followers-only, readable by
the sender's followers on Pixelfed.
- A top-level post without a picture is dropped as it arrives, and a reply is kept only under a post it holds. A Note
from an account nobody there follows is dropped too (`AP_INGEST_STORE_NOTES_WITHOUT_FOLLOWERS`).
- Passport refuses a token whose user id equals its client's id (it takes it for a client-credentials token), so the
pasture numbers its OAuth clients from a million.
### Long-form: WordPress plugin 9.3.1, Ghost 6, WriteFreely 0.17.2
FEP-b2b8 (draft) describes the shape: plain-text `name`, a `summary` teaser (≤500), full HTML `content`, `image`, and
@@ -700,6 +721,11 @@ a `preview` Note fallback.
any 4xx. Seen in the pasture (2026-10-05): until PrivaPub verified RFC 9421, its first delivery got 401 and was sent
again with draft-cavage, which it then kept using.
- It drops followers-only replies.
- **Pasture evidence (2026-10-05, WordPress 6 with ActivityPub 9.3.1, `tools/pasture/scenarios/wordpress.sh`):** 17
checks pass: alice follows an author and is kept as its follower; a published post arrives as an Article with its
title; her reply becomes a comment on the post, her like and boost comments of their kinds (`like`, `repost`); the
author's edit and the post's removal reach PrivaPub; statistics. It federates from WP-Cron, and sends its requests
through its own CA bundle (`wp-includes/certificates`).
- **Ghost 6** (its ActivityPub service is separate, built on Fedify):
- Article with `image` as a bare string and `preview`; members-only parts removed.
- It refetches every object signed, **never applies remote Updates**, and accepts only Note and Article.