Resumen
Cuando una publicación pasa por la cola de aprobación, ReviewableQueuedPost.payload["raw"] contiene una copia completa del cuerpo enviado. Después de que la publicación se aprueba y luego es eliminada por su autor, la publicación pública se reemplaza por el marcador “(publicación eliminada por el autor)”, pero el objeto revisable (reviewable) conserva el cuerpo original durante todo el tiempo que exista la fila de la publicación —lo cual, tras una eliminación por el autor, es indefinidamente— y sigue sirviéndolo al personal en /review.
No existe un proceso de depuración (scrub) para ello: Reviewable.scrubbable_types es [ReviewableUser], por lo que la acción de depuración de administrador añadida en #36556 (“los moderadores ahora pueden usar una acción de ‘Depurar’ para eliminar los datos personales del usuario”) no cubre las publicaciones en cola. El payload solo se elimina si alguien destruye permanentemente el registro de la publicación, lo cual no es lo que hace la eliminación por el autor y lo que la interfaz de usuario no permite para la primera publicación de un tema.
Reproducido en v2026.7.1. El código relevante no ha cambiado en main a fecha del 25 de septiembre de 2026.
Versión
Discourse v2026.7.1 (autoalojado, instancia de prueba autorizada local). Solo núcleo — no se involucra ningún plugin.
Pasos para reproducir
-
Como administrador, haga que las publicaciones de un usuario normal requieran aprobación, por ejemplo, establezca
approve post counten 5 y quitetrust_level_0deapprove unless allowed groups. -
Como ese usuario normal, cree un tema con un marcador único en el cuerpo. La respuesta vuelve como
{"action": "enqueued"}. -
Como personal, apruébelo:
PUT /review/<reviewable_id>/perform/approve_post?version=0. Se crea la publicación. -
Como autor, elimínela a través de la acción normal orientada al usuario —
DELETE /t/<topic_id>.jsonpara el tema del cual esta es la primera publicación. -
Como personal, solicite
GET /review.json?status=all.
Esperado
Una vez que el autor elimina el contenido, la copia de moderación del mismo texto debería seguir el ciclo de vida del contenido: debería ser descartada, depurada o, al menos, ser depurable por un administrador de la misma manera que un ReviewableUser rechazado.
Realidad
El paso 5 aún devuelve el cuerpo original completo. Medido en la ejecución reproducida:
| Observación | Resultado |
|---|---|
Fila de posts tras la eliminación del autor |
user_deleted = t, raw = '(tema eliminado por el autor)' |
reviewables.payload tras la eliminación del autor |
{"raw":"Cuerpo en cola DRLGQUEUEDfb08ab5b648f. relleno …"} — sin cambios |
GET /review.json?status=all del personal |
contiene el cuerpo original |
Reviewable.scrubbable_types |
["ReviewableUser"] |
PUT /review/<id>/scrub.json del administrador |
HTTP 404 (no es un tipo depurable) |
| Después de que el registro de la publicación se destruya permanentemente | la fila del reviewable desaparece (dependent: :destroy) |
La última fila es el único camino que lo limpia, y no es alcanzable desde la eliminación del autor: la eliminación del autor marca la publicación como user_deleted y, después de las horas de delete_removed_posts_after, la envía a la papelera. Una fila de publicación en la papelera sigue existiendo, por lo que el payload sigue existiendo.
De dónde proviene esto
-
app/models/reviewable_queued_post.rbconstruye y leepayload['raw']; nada establece un propósito o tiempo de retención para ello. -
lib/post_destroyer.rb:562resolve_reviewables_for_author_deletionsolo tocaReviewable.where(target: @post, status: pending). Un reviewable de publicación en cola aprobado nunca se transiciona ni se depura. -
app/models/post.rb:71has_many :reviewables, as: :target, dependent: :destroy— se dispara en la destrucción del registro, no en la eliminación blanda que produce la eliminación por el autor. -
app/models/reviewable.rb:81scrubbable_typesdevuelve[ReviewableUser];app/controllers/reviewables_controller.rb:191adicionalmente requierestatus: rejected. -
No hay una limpieza programada para los reviewables.
app/jobs/scheduled/contiene trabajosclean_up_*/purge_*para borradores, tokens de correo, exportaciones, cargas, claves de API y más, pero nada para reviewables.
Impacto
Esto no es una divulgación pública — la cola de revisión es solo para el personal, y no afirmo lo contrario. Es una brecha de retención de datos: el texto que un usuario eliminó del foro permanece en el almacén de moderación indefinidamente, se muestra en la interfaz de usuario de la cola de revisión y ninguna acción de administrador puede eliminarlo sin destruir permanentemente el registro de la publicación.
Eso importa por la misma razón por la que #36556 añadió la depuración para usuarios rechazados: los payloads de reviewables pueden contener datos personales, y un sitio que recibe una solicitud de borrado no tiene una forma soportada de limpiar un payload de publicación en cola.
Solución sugerida
Cualquiera de estas lo cierra; hacer ambas es mejor:
-
Extender
resolve_reviewables_for_author_deletion(y el camino de la papelera) para depurarpayload['raw']en reviewables cuya publicación objetivo haya sido eliminada por el autor o enviada a la papelera. -
Añadir
ReviewableQueuedPostaReviewable.scrubbable_typesy permitir que la acción de depuración de administrador existente se aplique cuando la publicación objetivo ya no contenga el contenido, para que los operadores tengan un remedio soportado para payloads creados antes de la corrección.
Una especificación de regresión debería afirmar que después de que un autor elimine una publicación en cola aprobada, el payload del reviewable ya no contiene el cuerpo enviado.