Remove Django comments (#1130) — phase 1: code removal + queue-safety scrub - #1217
Remove Django comments (#1130) — phase 1: code removal + queue-safety scrub#1217rdhyee wants to merge 7 commits into
Conversation
Per Eric's decision (2026-04-23, re-confirmed 2026-08-03): comments are a spam magnet with low-value content; remove rather than maintain. Removing before the Django 5.2 upgrade also eliminates the django_comments.0004 index migration from the 5.2 path. - settings/urls: drop django_comments from INSTALLED_APPS and URL conf - work page: remove Comments tab (tab numbering 1/3/4 preserved so CSS/JS class bindings are untouched; inbound ?tab=2 links degrade to tab 1) - home page: remove comments from the activity feed (pledges/wishes stay) - explore sidebar: remove Latest Comments link; delete /comments/ page - notifications: remove comment_was_posted handler + 3 comment notice types; delete their templates; strip ?tab=2 CTAs from remaining notices - migration 0030: delete the 3 NoticeType rows (ORM cascade), then DROP the django_comments / django_comment_flags tables (data intentionally dropped per issue; pre-deploy RDS snapshot is the recovery path) - tests: remove Comment fixtures from merge test and booktests helper - requirements: drop django-contrib-comments==2.0.0 (deploy with run_pip=true) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
- migration 0030: delete pending NoticeQueueBatch rows carrying comment labels BEFORE deleting NoticeTypes — engine.send_all() only tolerates missing users; a missing NoticeType raises past the batch delete and permanently wedges the notification queue. Byte-scan match (single-label batches) instead of unpickling, since the pickles embed Comment instances. - migration 0030: delete stale django_comments ContentType rows (cascades to auth_permission); document required deploy order (code + full restart via deploy.yml BEFORE migrate — playbook never migrates, so the safe order is the natural one) - notice_settings.html: remove now-empty Comment Notifications section - Pipfile: drop django-contrib-comments - _template_map.txt: drop deleted comment templates Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
…5 order (#1130) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
…p PR Codex R2 (HIGH): documentation alone cannot enforce restart-before-migrate on every deploy path (setup-*.yml runs migrate as a task while apache/celery restarts are deferred handlers). Shipping the destructive migration as its own release, deployed after this comment-free code release, makes the ordering structural instead of procedural. Phase 1 (this PR) carries no migrations; the orphaned tables and notice types are inert meanwhile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
…1130) R3 HIGH: phase 1 alone could wedge the notification queue — pending NoticeQueueBatch rows embed pickled Comment instances that the comment-free code can neither unpickle (app gone from INSTALLED_APPS) nor render (templates deleted), and send_all() blocks on the first failing batch. Migration 0030 (non-destructive, safe under any deploy ordering) scrubs those batches with the restricted-unpickler label inspection; phase 2 re-runs the same scrub to catch any batch created in the migrate-to-restart ingress window. R3 MEDIUM: notice-settings page no longer renders the wishlist_comment / wishlist_official_comment toggles that linger in the DB until phase 2. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
The migrate-to-restart window can still admit one poisoned comment batch (old code accepts comment POSTs until restart). New management command scrub_comment_notice_batches runs as the final phase-1 deploy step, after the restart, when ingress has structurally ended — making the scrub definitive. A wedge in the seconds before it runs is transient: failed batches are not consumed, so deleting the poison batch lets the next send_all() drain the queue. Migration 0030 header documents the sequence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
|
[Codex via CC] Codex (gpt-5.4) review — 5 rounds, final verdict: LGTM (2026-08-06) Round 1 (NOT-LGTM): 2 HIGH — (a) dropping tables in the same deploy as the code swap creates a 500 window for old in-memory workers (and celery isn't restarted by every path); (b) pending Round 2 (NOT-LGTM): documentation alone can't enforce restart-before-migrate on every deploy path (full provision runs Round 3 (NOT-LGTM): phase 1 alone could still wedge the queue — existing comment batches become unprocessable the moment the app leaves Round 4 (NOT-LGTM): the migrate→restart ingress window can still admit one poisoned batch → post-restart Round 5: LGTM — "The R4 HIGH is closed. The post-restart command runs after comment ingress has permanently ended, removes any interphase straggler, and leaves no mechanism for re-poisoning the queue. No new findings." Codex additionally verified the restricted unpickler across pickle protocols 0–5 (precise label detection, no payload-text false positives) and the phase-2 cascade/FK-drop ordering. Scrub logic was also verified empirically against synthetic fixtures (comment batch embedding an unimportable class; label-in-prose false-positive case; protocol-0 pickle) — 4/4 as expected. Still pending before the 🤖 Posted by Claude Code on Raymond's behalf |
…ledge_b2u Integration deploy to test surfaced conflicting core migration leaves: PR #1213 (retire-pledge-b2u-1195) already carries 0030_retire_pledge_b2u. Since #1213-before-#1130 is the agreed merge order, encode it structurally: this branch's scrub is now core.0031 depending on core.0030_retire_pledge_b2u (phase 2 becomes core.0032). Consequence: #1217 must merge AFTER #1213 — migrate fails loudly (NodeNotFoundError) if mis-sequenced. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W
|
[CC] Test-box validation complete (2026-08-06, both phases rehearsed end-to-end on test.unglue.it at integration SHA Phase 1 (this PR):
Phase 2 (#1218) rehearsed in its intended order (restart first, then migrate):
Applying 🤖 Posted by Claude Code on Raymond's behalf |
Removes Django comments functionality per #1130 — Eric-approved (2026-04-23, re-confirmed 2026-08-03): comments are a spam magnet with low-value content, and removing the app before the Django 5.2 upgrade eliminates the
django_comments.0004index migration from the 5.2 path entirely.Phase 1 of 2 — code removal + one non-destructive migration
This PR removes every runtime reference to
django_comments; the DB tables and notice-type rows stay behind, orphaned and unreferenced. A follow-up migration-only PR (phase 2,comments-drop-migration-1130) deletes the notice types and drops the tables — it merges only after this release is deployed and all processes restarted, which makes the destructive step safe under every deploy path (no restart/migrate ordering to get wrong; Codex R2 finding).The one migration here (
core.0031_scrub_comment_notice_batches) deletes pending notification-queue batches that carry comment notices. It must ship with this release (Codex R3 HIGH): those batches embed pickledCommentinstances that the comment-free code can neither unpickle nor render, andnotification.engine.send_all()blocks on the first failing batch — one stale spam-comment notification would wedge the entire queue. The scrub is non-destructive and safe under any deploy ordering (old code is indifferent to deleted pending batches); phase 2 re-runs it to catch anything created in the migrate→restart window.⛔ Merge order
Merge after #1213. This branch's migration
core.0031depends on #1213'score.0030_retire_pledge_b2u— the agreed sequencing (#1213 → #1130 → 5.2) is encoded structurally, andmigratefails loudly (NodeNotFoundError) if mis-ordered.What's removed
django_commentsout ofINSTALLED_APPS;/comments/URL includes (both the django_comments URLs and the site's latest-comments page)tabs4.jsand the CSS bind by fixed class names (tabs2,#tabs-2), and empty jQuery selections no-op, so no JS/CSS churn. Inbound?tab=2links (old notification emails) degrade to the Description tab via the view's whitelist.comment_was_postedhandler and the 3 comment notice types (comment_on_commented,wishlist_comment,wishlist_official_comment); their template dirs deleted;?tab=2CTAs stripped from surviving notices; the now-empty "Comment Notifications" section removed from settingsbibmodels) and comment re-pointing in work-merge (bookloader)booktestshelper;django-contrib-commentsout ofrequirements.txtandPipfile(16 template files deleted; ~470 lines net removed)Deploy sequence (per box; test first, then prod)
core.0031scrub)deploy.ymlrestart onto the same SHA — comment ingress ends here, permanentlymanage.py scrub_comment_notice_batches— definitive post-restart scrub (a poisoned batch created in the step-1→2 window would otherwise wedge the notification queue; failed batches aren't consumed, so this also un-wedges)run_pip=truenot strictly required (dependency removed, not added — pip won't uninstall; the package sits inert in existing venvs until a rebuild).Review
Codex review: 5 rounds (R1: 2 HIGH — deploy-window table drops, notification-queue wedge via stale pickled batches; R2: two-phase split adopted, scrub precision upgraded to label-slot inspection; R3: scrub moved into phase 1 + interphase settings filter; R4: post-restart scrub command closes the ingress race; R5: final). Scrub logic verified against synthetic pickle fixtures (unimportable embedded class, label-in-prose false-positive case, protocol 0).
🤖 Generated with Claude Code
https://claude.ai/code/session_01DD8dp3nkAyH2KeZymEgW5W