Skip to content

feat: add content reporting escalation workflow to ModerationModule#917

Open
Xaxxoo wants to merge 1 commit into
rinafcode:mainfrom
Xaxxoo:feat/876-report-escalation-workflow
Open

feat: add content reporting escalation workflow to ModerationModule#917
Xaxxoo wants to merge 1 commit into
rinafcode:mainfrom
Xaxxoo:feat/876-report-escalation-workflow

Conversation

@Xaxxoo

@Xaxxoo Xaxxoo commented Jun 27, 2026

Copy link
Copy Markdown

Closes #876

Summary

Adds automatic report assignment and SLA-based escalation so reports are never left unattended in PENDING status indefinitely.

Modified files:

File Change
src/moderation/reports/content-report.entity.ts Add assignedModerator (ManyToOne), assignedModeratorId (indexed FK), escalatedAt (timestamp)
src/moderation/reports/content-reporting.service.ts Call assignReport() immediately after a report is queued
src/moderation/moderation.module.ts Register ReportAssignmentService, import User entity and NotificationsModule

New files:

File Purpose
src/moderation/assignment/report-assignment.service.ts Core assignment + escalation logic
src/moderation/assignment/report-assignment.service.spec.ts 11 unit tests

How it works:

  1. When a report is created, ContentReportingService calls ReportAssignmentService.assignReport().
  2. assignReport() loads the active moderator pool (users with the moderator role, sorted by ID for determinism) and picks the next one via a round-robin cursor. The report is moved to UNDER_REVIEW and the moderator receives an IN_APP notification.
  3. A @Cron(EVERY_5_MINUTES) task (escalateOverdueReports) scans for PENDING/UNDER_REVIEW reports whose createdAt exceeds MODERATION_SLA_HOURS (default 24 h, configurable via env) and that have not yet been escalated (escalatedAt IS NULL).
  4. escalateReport() reassigns to a randomly-chosen admin, sets escalatedAt, and sends an URGENT priority notification.
  5. Notification failures are always caught and logged — they never interrupt assignment or escalation.

Test plan

  • assignReport assigns to the first moderator in the pool
  • Assignment notification is sent to the moderator
  • Round-robin distributes successive reports across all moderators
  • No moderators → report returned unassigned without error
  • escalateReport sets assignedModeratorId to an admin and sets escalatedAt
  • Escalation notification is sent with URGENT priority
  • No admins → report returned unchanged without error
  • escalateOverdueReports escalates overdue reports returned by the repo
  • escalateOverdueReports is a no-op when no overdue reports exist
  • Notification failure during assignment does not throw
  • Notification failure during escalation does not throw
  • All 11 unit tests pass (npm test)

…inafcode#876)

Ensure reports are never left unattended in PENDING status by introducing
automatic assignment and SLA-based escalation.

Changes:
- ContentReport entity: add assignedModerator (ManyToOne User),
  assignedModeratorId (indexed FK), and escalatedAt (timestamp) fields
- ReportAssignmentService (src/moderation/assignment/report-assignment.service.ts):
    * assignReport() — round-robin assigns new reports across the active
      moderator pool and sends an IN_APP notification to the assignee
    * escalateReport() — re-assigns to a random admin, sets escalatedAt, and
      sends an URGENT IN_APP notification
    * escalateOverdueReports() — @Cron every 5 min; finds PENDING/UNDER_REVIEW
      reports older than MODERATION_SLA_HOURS (default 24 h) without escalatedAt
      and escalates them
    * Notification failures are swallowed so they never block assignment
- ContentReportingService: calls assignReport() after a report is queued
- ModerationModule: registers ReportAssignmentService, imports User entity and
  NotificationsModule
- 11 unit tests covering round-robin distribution, escalation, overdue sweep,
  empty moderator/admin pools, and notification failure isolation
@drips-wave

drips-wave Bot commented Jun 27, 2026

Copy link
Copy Markdown

@Xaxxoo Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Great job so far

There’s just one blocker — the workflow is failing. Could you take a look and fix it so all checks pass?

Happy to review again once that’s done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add content reporting escalation workflow to ModerationModule

2 participants