Zusammenfassung
Wenn ein Beitrag die Genehmigungs-Warteschlange durchläuft, enthält ReviewableQueuedPost.payload["raw"] eine vollständige Kopie des eingereichten Inhalts. Nach der Genehmigung und anschließenden Löschung durch den Autor wird der öffentliche Beitrag durch den Platzhalter „(Beitrag vom Autor gelöscht)“ ersetzt, aber der Reviewable behält den ursprünglichen Inhalt so lange bei, wie die Beitragszeile existiert – was nach einer Autor-Löschung unbegrenzt ist – und stellt ihn weiterhin dem Personal unter /review bereit.
Es gibt keinen Weg, ihn zu bereinigen (scrub): Reviewable.scrubbable_types ist [ReviewableUser], daher deckt die in #36556 hinzugefügte Admin-Bereinigungsaktion („Moderatoren können jetzt eine ‚Bereinigen‘-Aktion verwenden, um die persönlichen Daten des Benutzers zu entfernen“) eingestufte Beiträge nicht ab. Die Payload wird nur entfernt, wenn jemand die Beitragszeile dauerhaft zerstört, was nicht das ist, was eine Autor-Löschung tut, und was die UI für den ersten Beitrag eines Themas nicht zulässt.
Reproduziert auf v2026.7.1. Der relevante Code ist auf main Stand 2026-09-25 unverändert.
Version
Discourse v2026.7.1 (self-hosted, lokale autorisierte Testinstanz). Nur Core – keine Plugin beteiligt.
Schritte zur Reproduktion
-
Als Admin die Beiträge eines normalen Benutzers zur Genehmigungspflicht machen, z. B.
approve post countauf 5 setzen undtrust_level_0ausapprove unless allowed groupsentfernen. -
Als dieser normale Benutzer ein Thema mit einem eindeutigen Marker im Inhalt erstellen. Die Antwort lautet
{"action": "enqueued"}. -
Als Personal genehmigen:
PUT /review/<reviewable_id>/perform/approve_post?version=0. Der Beitrag wird erstellt. -
Als Autor über die normale benutzersichtbare Aktion löschen –
DELETE /t/<topic_id>.jsonfür das Thema, dessen erster Beitrag dies ist. -
Als Personal
GET /review.json?status=allanfordern.
Erwartet
Sobald der Autor den Inhalt löscht, sollte die Moderationskopie desselben Textes dem Lebenszyklus des Inhalts folgen: Sie sollte verworfen, bereinigt oder zumindest von einem Admin bereinigt werden können, so wie ein abgelehnter ReviewableUser.
Tatsächlich
Schritt 5 liefert weiterhin den vollständigen ursprünglichen Inhalt. Gemessen bei der reproduzierten Ausführung:
| Beobachtung | Ergebnis |
|---|---|
posts-Zeile nach der Autor-Löschung |
user_deleted = t, raw = '(topic deleted by author)' |
reviewables.payload nach der Autor-Löschung |
{"raw":"Queued body DRLGQUEUEDfb08ab5b648f. padding …"} – unverändert |
Personal GET /review.json?status=all |
enthält den ursprünglichen Inhalt |
Reviewable.scrubbable_types |
["ReviewableUser"] |
Admin PUT /review/<id>/scrub.json |
HTTP 404 (kein bereinigungsfähiger Typ) |
| Nach der dauerhaften Zerstörung der Beitragszeile | Reviewable-Zeile ist weg (dependent: :destroy) |
Die letzte Zeile ist der einzige Weg, der sie aufräumt, und sie ist nicht über die Autor-Löschung erreichbar: Die Autor-Löschung markiert den Beitrag als user_deleted und verschiebt ihn nach delete_removed_posts_after Stunden in den Papierkorb. Eine im Papierkorb befindliche Beitragszeile existiert weiterhin, daher existiert die Payload weiterhin.
Ursprung
-
app/models/reviewable_queued_post.rbbaut und liestpayload['raw']; es wird kein Aufbewahrungszweck oder eine Lebensdauer dafür angegeben. -
lib/post_destroyer.rb:562resolve_reviewables_for_author_deletionberührt nurReviewable.where(target: @post, status: pending). Ein genehmigter eingestufter Beitrags-Reviewable wird nie überführt oder bereinigt. -
app/models/post.rb:71has_many :reviewables, as: :target, dependent: :destroy– wird bei der Zerstörung des Datensatzes ausgelöst, nicht bei der Soft-Löschung, die eine Autor-Löschung erzeugt. -
app/models/reviewable.rb:81scrubbable_typesgibt[ReviewableUser]zurück;app/controllers/reviewables_controller.rb:191erfordert zusätzlichstatus: rejected. -
Es gibt keine geplante Bereinigung für Reviewables.
app/jobs/scheduled/enthältclean_up_*/purge_*-Jobs für Entwürfe, E-Mail-Tokens, Exporte, Uploads, API-Schlüssel und mehr, aber nichts für Reviewables.
Auswirkung
Dies ist keine öffentliche Offenlegung – die Review-Warteschlange ist nur für Personal zugänglich, und ich behaupte das Gegenteil nicht. Es ist eine Lücke bei der Datenaufbewahrung: Text, den ein Benutzer aus dem Forum entfernt hat, verbleibt unbegrenzt im Moderationsspeicher, wird in der Review-Warteschlangen-UI angezeigt und kann durch keine Admin-Aktion entfernt werden, außer durch die dauerhafte Zerstörung der Beitragszeile.
Das ist aus demselben Grund wichtig, aus dem #36556 das Bereinigen für abgelehnte Benutzer hinzugefügt hat: Reviewable-Payloads können persönliche Daten enthalten, und eine Site, die einen Löschungsantrag erhält, hat keinen unterstützten Weg, eine eingestufte Beitrags-Payload zu bereinigen.
Vorschlag zur Behebung
Beides schließt die Lücke; beides zu tun ist besser:
-
resolve_reviewables_for_author_deletion(und den Papierkorb-Pfad) erweitern, umpayload['raw']bei Reviewables zu bereinigen, deren Zielbeitrag vom Autor gelöscht oder in den Papierkorb verschoben wurde. -
ReviewableQueuedPostzuReviewable.scrubbable_typeshinzufügen und die bestehende Admin-Bereinigungsaktion anwenden lassen, wenn der Zielbeitrag den Inhalt nicht mehr trägt, damit Betreiber ein unterstütztes Mittel für Payloads haben, die vor der Behebung erstellt wurden.
Ein Regressionstest sollte behaupten, dass nach dem Löschen eines genehmigten eingestuferten Beitrags durch den Autor die Reviewable-Payload den eingereichten Inhalt nicht mehr enthält.