From ad8d353f9a761395d26afd1e6edb4a40d615dd3b Mon Sep 17 00:00:00 2001 From: thepra Date: Sun, 4 Oct 2026 04:16:16 +0200 Subject: [PATCH] docs: FEDERATION.md tested against six peers with signed fetches, the shipped FEPs; v1.19.1 and v1.20.0 in ROADMAP - FEDERATION.md: - It said only GoToSocial was tested live. It now lists all six pasture peers, run with signed fetches required as production runs, and what is checked both ways. - FEP-044f, FEP-9967, FEP-c0e0 and FEP-5feb moved from planned to supported. - indexable and discoverable are described as the settings they are. - ROADMAP: v1.19.1 deployed and verified, v1.20.0 (phase 4). - Pasture, Akkoma: its like and boost count gets two minutes. In the final clean pass, all six peers with SecureMode on gave 245 passed, 1 failed, 4 expected. The failure was this count, which Akkoma's job queue was slow to update under the load of six peers; two reruns gave 44/44. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01ELjqpznMFMNrJoJUj6K5p2 --- FEDERATION.md | 50 +++++++++++++++++++++---------- docs/ROADMAP.md | 20 +++++++++---- tools/pasture/scenarios/akkoma.sh | 3 +- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/FEDERATION.md b/FEDERATION.md index 4cb600f..7f3ce44 100644 --- a/FEDERATION.md +++ b/FEDERATION.md @@ -12,17 +12,29 @@ PrivaPub is an ActivityPub server written in C#. This document follows ## Tested against -- **GoToSocial 0.22.1, end to end.** It runs in a private network on the workstation (`tools/pasture/`) and is driven - through its own client API. Checked both ways: - - follows, including to a locked account; - - public posts with a content warning; - - replies with notifications; - - likes and boosts; - - direct messages; - - edits and deletes; - - unfollow. -- **Mastodon, Misskey, Lemmy and PeerTube, by unit tests only.** The tests feed the parser documents written in each - server's shape. No live exchange with any of them has run yet. +End to end, in a private network on the workstation (`tools/pasture/`), each peer driven through its own client API +and every run starting clean, with signed fetches required (as privapub.thepra.dev runs): +- **GoToSocial 0.22.1** +- **Mastodon 4.7.3** +- **Misskey 2026.10** +- **Sharkey 2025.4.7** +- **Akkoma 3.20.1** +- **Lemmy 1.0.0-beta.2** + +Checked both ways, where the peer has the feature: +- follows, locked accounts included; +- every visibility, content warnings, replies and their notifications; +- likes, boosts and emoji reactions with their undos; +- direct messages; +- polls; +- quotes; +- images with alt text; +- edits with history and deletes; +- communities and circles; +- blocks and unfollows. + +`docs/INTEROP.md` has each peer's evidence and what is still expected to fail. PeerTube, PieFed, Mbin and the others are +covered by unit tests written in their documents' shape. ## Supported FEPs @@ -30,11 +42,16 @@ PrivaPub is an ActivityPub server written in C#. This document follows - [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md) - [FEP-2c59: Discovery of a WebFinger address from an ActivityPub actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/2c59/fep-2c59.md) - [FEP-1b12: Group federation](https://codeberg.org/fediverse/fep/src/branch/main/fep/1b12/fep-1b12.md) (communities; see "Groups") +- [FEP-044f: Consent-respecting quote posts](https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md) + (`QuoteAuthorization` at `/parrot-licences/{id}`; checked with Mastodon both ways) +- [FEP-9967: Polls](https://codeberg.org/fediverse/fep/src/branch/main/fep/9967/fep-9967.md) +- [FEP-c0e0: Emoji reactions](https://codeberg.org/fediverse/fep/src/branch/main/fep/c0e0/fep-c0e0.md) (`EmojiReact`, and Misskey's + `Like` with content) +- [FEP-5feb: Search indexing consent](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md) (`indexable`) -Planned (see `docs/ROADMAP.md`, phases P5 to P8, and the per-platform notes in `docs/INTEROP.md`): FEP-044f (quotes), -FEP-9967 (polls), FEP-c0e0 (emoji reactions), FEP-9098 (custom emoji), FEP-7888 and FEP-f228 (threads), FEP-7628 (Move), -FEP-8fcf (followers synchronisation), FEP-5feb (`indexable`), FEP-8967 (link attachments), FEP-521a and FEP-8b32 (keys -and integrity proofs), FEP-ae0c (relays). +Planned (see `docs/ROADMAP.md`, phases P7 and P8, and the per-platform notes in `docs/INTEROP.md`): FEP-9098 (custom +emoji), FEP-7888 and FEP-f228 (threads), FEP-7628 (Move), FEP-8fcf (followers synchronisation), FEP-8967 (link +attachments), FEP-521a and FEP-8b32 (keys and integrity proofs), FEP-ae0c (relays). ## Actors @@ -58,7 +75,8 @@ The names are the project's own and are stable; resolve actors through WebFinger - The key is `{actor}#main-key`, RSA 2048, served as SPKI PEM with `owner` set to the actor. - `published` on an actor is a whole day, chosen at random up to two weeks before the account was made, so two - personas made on the same day do not share a date. `indexable` is `false`. + personas made on the same day do not share a date. `indexable` is `false` unless the persona turns it on, and + `discoverable` is `true` unless it turns that off (the deploy's own persona, @thepra, is undiscoverable). - The instance actor is `/peasants/privapub` (type `Application`). It signs every fetch PrivaPub makes, so no avatar's key is used to read another server's content. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 8ee6bdc..87e169e 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -35,11 +35,21 @@ Written 2026-10-01 from the original 2023 code, the decePubClient UI, a federati - v1.18.0, deployed and verified 2026-10-04: geolocation that updates itself (DB-IP Lite 2026-10 loaded), the deploy signing in as @thepra (undiscoverable), the crawler on (1010 servers known within the hour), sign-up by invitation with one registrations switch; - - v1.19.0, 2026-10-04: circle posts reach Mastodon and GoToSocial members (each copy names and mentions its member), - followers-only, direct and circle posts served to signed refetches from those they were for, SecureMode on (all six - pasture peers pass under it), and account privacy (sign-in and recovery say nothing, recovery codes hashed for an - hour, a recovered password ends every session, a deleted root's personas and groups are deleted everywhere); - - still to come: one answer everywhere (the mismatch sweep). + - v1.19.1, deployed and verified 2026-10-04 (v1.19.0's deploy stopped at a flaky test, fixed in v1.19.1): + - circle posts reach Mastodon and GoToSocial members, each copy naming and mentioning its member; + - followers-only, direct and circle posts are served to signed refetches from those they were for; + - SecureMode is on: a persona answers 401 unsigned, a browser is redirected, and all six pasture peers pass; + - account privacy: sign-in and recovery say nothing, recovery codes are hashed for an hour, a recovered password + ends every session, and a deleted root's personas and groups are deleted everywhere; + - v1.20.0, 2026-10-04: one answer everywhere: + - one counting rule for posts and users; + - gone accounts out of every count; + - replies_count only for public replies; + - search anyone may use; + - the instance API advertising what is enforced; + - Mastodon routes that answer, grouped notifications; + - community announce ids that resolve, a hashtag page; + - remote accounts' real counts. - [ ] P7 Threads, communities, moderation, the social graph - [ ] P8 Signatures, discovery, the long tail diff --git a/tools/pasture/scenarios/akkoma.sh b/tools/pasture/scenarios/akkoma.sh index 8b7dabd..573bc67 100644 --- a/tools/pasture/scenarios/akkoma.sh +++ b/tools/pasture/scenarios/akkoma.sh @@ -57,7 +57,8 @@ until_true 30 '[ "$(acurl -H "$KH" "$AK/api/v1/statuses/$a_post_id/context" | j echo " likes, boosts and reactions" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$a_post_on_p/favourite" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$a_post_on_p/reblog" -until_true 30 '[ "$(acurl -H "$KH" "$AK/api/v1/statuses/$a_post_id" | j "print(d[\"favourites_count\"], d[\"reblogs_count\"])")" = "1 1" ]' && ok "alice_akkoma's like and boost count on Akkoma" || ko "like or boost not counted on Akkoma" +# Akkoma counts them from its own job queue, which can lag behind under the load of a six-peer run: two minutes +until_true 60 '[ "$(acurl -H "$KH" "$AK/api/v1/statuses/$a_post_id" | j "print(d[\"favourites_count\"], d[\"reblogs_count\"])")" = "1 1" ]' && ok "alice_akkoma's like and boost count on Akkoma" || ko "like or boost not counted on Akkoma" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$a_post_on_p/unfavourite" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$a_post_on_p/unreblog" until_true 30 '[ "$(acurl -H "$KH" "$AK/api/v1/statuses/$a_post_id" | j "print(d[\"favourites_count\"], d[\"reblogs_count\"])")" = "0 0" ]' && ok "alice_akkoma's unlike and unboost reach Akkoma" || ko "undo of like or boost not applied on Akkoma"