Everything on, phase 2: circle posts for everyone, private posts on signed refetch, browsers past SecureMode

Circles (owner decision 2026-10-04: fix them for compatibility):
- Mastodon 4.7 and GoToSocial drop a post that names none of their accounts, and a circle post named only the circle
  and its /flock. OutboxPublisher.Publish now sends each member a copy that also names that member in `cc`, on the
  activity and on the object, and names no other member. The Create, every Update (edit, poll, quote approval, policy,
  through the new PublishUpdate) and the Delete (StatusService.Remove now uses Publish) all go that way.
- UpdateOf renders with the post's group, so an Update keeps a circle post's `audience` and a community post's `Page`
  and title.
- A reply to a circle post stays in the circle, whichever client wrote it.
- A circle post can no longer quote a post that needs permission: asking would show the circle post to its author.

Posts that are not public, on refetch (SignedFetchAuthorizer.MayRead):
- Followers-only, direct and circle posts are served to a signed request from someone they were for, or from the
  instance actor of a server where one of them lives. That is a follower or an addressed account, an addressed
  account, or a member. Everyone else still gets 404.
- Once deleted they answer those readers 410. Mastodon deletes its copy when a refetch answers 404.
- A circle refetch names the requesting member, or the members on the requesting server, as the delivered copy did.
- /grunts/create-{id} serves the same.
- /peasants/{name}/whispers/{id}, a DM's `context`, was never routed. It is now the conversation's posts, for its
  participants only.

SecureMode lets browsers through to the redirect to the public page, instead of answering them 401.

653 tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELjqpznMFMNrJoJUj6K5p2
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-04 03:01:14 +02:00
1 parent 5f56681c01
commit fcd35f5043
14 files changed
+339 -46

No files matched your search

+13 -3
View File
@@ -182,8 +182,17 @@ group www-data and reaches the private mongod; `sudo -u www-data` works too.
`ContentFormat` says what `Text` holds. Remote names are plain text.
8. **Circles federate to members only.** A circle is an undiscoverable Group actor that takes follow requests (the owner
approves); its posts are addressed to the circle and its `/flock`, delivered to members' personal inboxes, never
announced, and served only to a signed request from a member or a member's instance actor
(`SignedFetchAuthorizer`), 404 otherwise. Circles never appear in search, lookups, mentions or profile pages.
announced. Each member's copy also names that member in `cc` (`OutboxPublisher.Naming`, owner decision
2026-10-04), because Mastodon and GoToSocial keep a post only when it names one of their accounts; Create, every
Update and the Delete all go through `OutboxPublisher.Publish` for that. A reply to a circle post stays in the circle,
and a circle post never asks a non-member for a quote. Circles never appear in search, lookups, mentions or profile
pages.
**A post that is not public is served only to a signed request from someone it was for** (`SignedFetchAuthorizer.MayRead`):
a follower or an addressed account for followers-only, an addressed account for a DM, a member for a circle, or the
instance actor of a server where one of them lives; 404 to anyone else, 410 to them once it is deleted. A circle
refetch names the requesting member, or the members on the requesting server. A DM's `context`
(`/peasants/{name}/whispers/{id}`) lists the conversation's posts for its participants. Mastodon deletes its copy
when a refetch answers 404, which is why this matters.
**Communities** are FEP-1b12 groups: `GroupDistributor` announces the whole activity (plus the object for new posts,
for Mastodon), top-level posts are `Page`s with a `name`, posting follows `Group.PostingPolicy`.
Located posts (`LocalGeo`) are the only local-only posts.
@@ -419,7 +428,8 @@ tools/pasture/run.sh down # removes e
Its token comes from `rails runner` (no password grant). Without Elasticsearch its status search finds nothing, so
deliveries are checked through `/api/v1/accounts/:id/statuses` of the sender as Mastodon knows them, or
`Status.exists?` through `rails runner`. Its actors are numbered (`/ap/users/<id>`), so look URIs up rather than
build them. 49 checks; circle posts are an expected failure (see `docs/INTEROP.md`, Mastodon).
build them. Circle posts and a followers-only post survive its signed refetch (`ActivityPub::FetchRemoteStatusService`
through `rails runner`). Inbound Block is the one expected failure until P7.
- **Misskey (2026.10.0):** one container on the shared Postgres and Redis. A new Misskey federates with nobody
(`federation: none`) until `admin/update-meta` says `all`, which `misskey_up` does. Its API is `POST /api/<endpoint>`
with the token as `i` (`mk` in the scenario); `users/relation` answers a list, `users/notes` leaves replies out unless