Reports reach Lemmy's moderators, from an anonymous reporter

Lemmy takes a report only from a person or a service, about one post or comment, addressed to its community, and it
answered PrivaPub's Flag (the instance actor's, an Application, with no `to` and the account and posts as its object)
400. A report of a post or comment in a community on a server whose NodeInfo names Lemmy now leaves from
`privapub_reports`, a Service with its own key that names nobody: one Flag per post, `to` the community (its own
audience, else its thread's), with the persona's words, or the category, in `summary` and `content`, sent to the
community's inbox. This is the second exception to "a server's software is for display" (owner decision 2026-10-06,
`ReportService.ServiceReportTakers`). Every other server keeps the instance actor's report. An account alone is not
reported to Lemmy, which takes no such report, and `forwarded` now says whether anything left.

The reporter is read unsigned in SecureMode and answers WebFinger like the instance actor. Nobody follows or mentions
it, the Mastodon API has no account for it, and a migration reserves its name. Checked live: Lemmy 1.0 and 0.19 keep the
reports of a thread and of a comment, with alice's words, from "Reports from privapub.test", and none names her (69
checks). A sweep of every scenario with this and the next commit: 876 checks pass; Ghost's Network feed listed alice's
post too late once, and Ghost passes alone.

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-06 19:23:17 +02:00
1 parent 10ff4b3d2a
commit f66c280b0b
33 files changed
+561 -46

No files matched your search

+12
View File
@@ -52,6 +52,18 @@ privapub_token() {
"$here/../smoke/oauth.sh" "$P" "$ROOT_USER" "$ROOT_PASS" "$persona" "read write follow" | cut -d' ' -f1
}
# p_report <authorization header> <account id> <reason> <status id...>: a persona reports an account's posts and asks for
# the report to be forwarded; prints whether PrivaPub says it was (Mastodon's "forwarded")
p_report() {
local auth=$1 account=$2 reason=$3; shift 3
local ids=() id
for id in "$@"; do ids+=(-d "status_ids[]=$id"); done
curl -s -X POST -H "$auth" "$P/api/v1/reports" -d "account_id=$account" "${ids[@]}" --data-urlencode "comment=$reason" \
-d 'category=other' -d 'forward=true' | j "print(d['forwarded'])"
}
# the anonymous Service that carries PrivaPub's reports to the servers that take them only from a person or a service
P_REPORTER=https://privapub.test/peasants/privapub_reports
# stats_check <host> <software>: the admin statistics name the peer's software and count traffic both ways.
stats_check() {
local host=$1 software=$2 admin found
+16
View File
@@ -112,6 +112,22 @@ until_true 45 '[ "$(p_banned)" = "True" ]' && ok "the community's ban of alice_l
[ "$(p_reply "while banned")" = "422" ] && ok "a banned persona's reply in the community is refused" || ko "a banned persona's reply was taken"
lm POST community/ban_user "{\"community_id\":$cats_on_lm,\"person_id\":$alice_on_lm,\"ban\":false,\"reason\":\"pasture\"}" >/dev/null
until_true 45 '[ "$(p_banned)" = "False" ]' && ok "the community's unban reaches PrivaPub" || ko "the community's unban did not reach PrivaPub"
echo " reports"
# Lemmy takes a report only from a person or a service, about one post or comment, addressed to its community (owner
# decision 2026-10-06): alice's report of lemmyuser's thread and comment leaves from PrivaPub's reporter, one Flag each,
# and never names her. Lemmy sends nothing back; what it keeps is read from its database.
lm POST comment "{\"post_id\":$lm_cats_id,\"content\":\"a Lemmy comment to report\"}" >/dev/null
lm_comment_on_p() { curl -s -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p/context" | j "print(next((s['id'] for s in d['descendants'] if 'a Lemmy comment to report' in s['content']), ''))"; }
until_true 45 '[ -n "$(lm_comment_on_p)" ]' && ok "lemmyuser's comment to report reaches PrivaPub" || ko "lemmyuser's comment never reached PrivaPub"
lm_author_on_p=$(curl -s -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p" | j "print(d['account']['id'])")
reason="a pasture report $(date +%s)"
[ "$(p_report "$LAH" "$lm_author_on_p" "$reason" "$lm_cats_on_p" "$(lm_comment_on_p)")" = "True" ] \
&& ok "PrivaPub says alice's report was forwarded" || ko "PrivaPub did not forward alice's report"
lm_reports() { podman exec pasture-postgres psql -U pasture -d lemmy -tAc "select count(*) from $1 r join person p on p.id = r.creator_id where r.reason = '$reason' and p.ap_id = '$P_REPORTER'"; }
until_true 45 '[ "$(lm_reports post_report)" = "1" ]' && ok "Lemmy keeps the thread's report from PrivaPub's reporter, with alice's words" || ko "Lemmy kept no report of the thread"
until_true 45 '[ "$(lm_reports comment_report)" = "1" ]' && ok "Lemmy keeps the comment's report from PrivaPub's reporter, with alice's words" || ko "Lemmy kept no report of the comment"
[ "$(podman exec pasture-postgres psql -U pasture -d lemmy -tAc "select count(*) from post_report r join person p on p.id = r.creator_id where p.ap_id like '%alice_lemmy%'")" = "0" ] \
&& ok "no report on Lemmy names alice" || ko "a report on Lemmy names alice"
# the community relays it as Announce{Delete}, believed once Lemmy answers 410 for the post; Lemmy sends what it queued
# every 30 seconds
lm POST post/remove "{\"post_id\":$lm_cats_id,\"removed\":true,\"reason\":\"pasture\"}" >/dev/null
+14
View File
@@ -117,6 +117,20 @@ until_true 45 '[ "$(p_banned)" = "True" ]' && ok "the community's ban of alice_l
[ "$(p_reply "while banned")" = "422" ] && ok "a banned persona's reply in the community is refused" || ko "a banned persona's reply was taken"
lm POST community/ban_user "{\"community_id\":$cats_on_lm,\"person_id\":$alice_on_lm,\"ban\":false,\"reason\":\"pasture\"}" >/dev/null
until_true 45 '[ "$(p_banned)" = "False" ]' && ok "the community's unban reaches PrivaPub" || ko "the community's unban did not reach PrivaPub"
echo " reports"
# as on Lemmy 1.0: the report leaves from PrivaPub's reporter, one Flag for the thread and one for the comment
lm POST comment "{\"post_id\":$lm_cats_id,\"content\":\"a Lemmy 0.19 comment to report\"}" >/dev/null
lm_comment_on_p() { curl -s -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p/context" | j "print(next((s['id'] for s in d['descendants'] if 'a Lemmy 0.19 comment to report' in s['content']), ''))"; }
until_true 45 '[ -n "$(lm_comment_on_p)" ]' && ok "lemmyuser's comment to report reaches PrivaPub" || ko "lemmyuser's comment never reached PrivaPub"
lm_author_on_p=$(curl -s -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p" | j "print(d['account']['id'])")
reason="a pasture report $(date +%s)"
[ "$(p_report "$LAH" "$lm_author_on_p" "$reason" "$lm_cats_on_p" "$(lm_comment_on_p)")" = "True" ] \
&& ok "PrivaPub says alice's report was forwarded" || ko "PrivaPub did not forward alice's report"
lm_reports() { podman exec pasture-postgres psql -U pasture -d lemmy19 -tAc "select count(*) from $1 r join person p on p.id = r.creator_id where r.reason = '$reason' and p.actor_id = '$P_REPORTER'"; }
until_true 45 '[ "$(lm_reports post_report)" = "1" ]' && ok "Lemmy 0.19 keeps the thread's report from PrivaPub's reporter, with alice's words" || ko "Lemmy 0.19 kept no report of the thread"
until_true 45 '[ "$(lm_reports comment_report)" = "1" ]' && ok "Lemmy 0.19 keeps the comment's report from PrivaPub's reporter, with alice's words" || ko "Lemmy 0.19 kept no report of the comment"
[ "$(podman exec pasture-postgres psql -U pasture -d lemmy19 -tAc "select count(*) from post_report r join person p on p.id = r.creator_id where p.actor_id like '%alice_lemmy19%'")" = "0" ] \
&& ok "no report on Lemmy 0.19 names alice" || ko "a report on Lemmy 0.19 names alice"
lm POST post/remove "{\"post_id\":$lm_cats_id,\"removed\":true,\"reason\":\"pasture\"}" >/dev/null
until_true 45 '[ -z "$(p_home_has "$lm_cats_thread")" ]' && ok "a moderator's removal reaches PrivaPub" || ko "a moderator's removal did not reach PrivaPub"