Add suspicious-signup sweep: suspend flagged signups with no activity

Watches every account flagged by IP-scrutiny or email-domain scrutiny at
signup and, once it goes live, records a baseline post/follow count. A
scheduled sweep (app/suspicious_sweep.py, run via cron on admin.yttrx.com)
suspends any watch past SUSPICIOUS_GRACE_HOURS with zero new posts and
zero new follows since that baseline; any activity clears the watch.

Works whether yttrx is open-registration or requires moderator approval,
since the watch starts at whichever event actually makes the account live
(account.created vs account.approved), same dual handling the welcome flow
already uses. Needs ABUSE_BOT_TOKEN re-minted with admin:read:accounts.
This commit is contained in:
2026-07-05 10:22:39 -07:00
parent 656eec09c0
commit 9924e06b5a
7 changed files with 637 additions and 4 deletions
+32
View File
@@ -145,3 +145,35 @@ CHECK_MAIL_HOLD_WELCOME=true
# 403s and is logged as an error, but nothing else in the bot is affected.
# Also gates the report-triggered suspend+block override in handle_report().
CHECK_MAIL_AUTO_DOMAIN_BLOCK=true
# --- Suspicious-signup sweep (app/suspicious_sweep.py, run on a schedule) ---
# Watches every account flagged by EITHER IP-scrutiny or email-domain
# scrutiny at signup. Once the account goes live (account.created if open/
# auto-approved, account.approved if this instance requires moderator
# approval — same dual handling the welcome flow already uses), a baseline
# post/follow count is recorded. A scheduled sweep (cron on admin.yttrx.com,
# `docker exec yttrx-welcomebot python -m app.suspicious_sweep`) then acts on
# any watch past SUSPICIOUS_GRACE_HOURS with zero new posts AND zero new
# follows since that baseline. Master switch:
SUSPICIOUS_SWEEP_ENABLED=true
# Hours of grace given to a flagged signup to show organic activity (a new
# post or a new follow) before it's considered dormant/bot-like.
SUSPICIOUS_GRACE_HOURS=24
# Moderation action taken on a flagged signup with no activity in the grace
# window: "suspend" (agreed default — a stronger signal than the report-
# driven abuse-bot's default "silence", since this is zero organic activity,
# not just reports) or "silence".
SUSPICIOUS_ACTION=suspend
# Rollout safety switch, same role as ABUSE_DRY_RUN — ships "false" (live)
# here by design; flip to "true" to pause without redeploying.
SUSPICIOUS_DRY_RUN=false
# Requires ABUSE_BOT_TOKEN to additionally carry the admin:read:accounts
# scope (fetches current post/follow counts + role/suspended state via
# GET /api/v1/admin/accounts/:id) — see CLAUDE.md's moderator-token-gotcha
# section. Without it the sweep 403s per-account (logged as an error, that
# account is retried next sweep) but nothing else in the bot is affected.
# Reuses ABUSE_SKIP_PRIVILEGED and ABUSE_ALLOWLIST above — no separate vars.