Skip to main content

Abuse monitor — behavioural signals

For admins· 4 min read

How /admin/abuse-monitor surfaces paid-content read patterns, rate-limit hits, edge-proxy blocks, and top viewers — distinct from the user-filed flag queue.

/admin/abuse-monitor is the forensic trail of paid-content reads. Where the flag queue is user-filed (somebody reported an item), the abuse monitor is behavioural — the system noticed an access pattern that looks suspect, and you decide whether to action it.

Available to super + content tier admins. Other tiers don't see the entry in the side rail.

What it shows

The page is a stack of cards, each one a slice of the content_access_log over the recent past:

KPIs (top of page)

  • Recent rows — total reads in the snapshot window.
  • Recent blocks — reads the proxy rejected (paywall, rate-limit, forbidden, abuse-flag).
  • Top viewers · 24h — distinct users in the heaviest-readers list.

Edge proxy card

Health of the in-front rate-limit + paywall enforcement. Surfaces the active block rules + per-rule counters. Useful when investigating "why was this user blocked?" — the card lists which rule matched.

Active flags card

The shortlist the system has flagged for human review. Each row shows the user, the trigger (e.g. "200 paid items in 1 hour"), and two actions:

  • Dismiss — false positive. The flag closes; the user continues unaffected. Notes optional.
  • Suspend user — flips the user's status to suspended (kicks all sessions). Prompts for an optional reason that gets stored on the user row. Use sparingly — wrongly suspending a real teacher in the middle of class is a high-cost mistake.

Suspended users still appear here for context; you can later restore them from /admin/users.

Resolved flags card

Recent dismissals + suspensions for context. Useful when you want to see "did we already action a flag for this user?" before opening a new one.

Top viewers · 24h card

Heavy-readers leaderboard. A teacher prepping a unit reading 80 items is fine; an account reading 800 items via a script is not. Click through to the user row in /admin/users for context (school, signup date, role).

Fingerprints card

Distinct device fingerprints seen on a single user in 24h. A teacher swapping laptop ↔ phone is 2-3 fingerprints; a token being passed around a WhatsApp group is 50+. The card lists user + count + first/last seen.

Recent blocks card

Last N proxy rejections. Each row: user (or anon), URL, rule that matched, timestamp. Useful for triaging "the rate limit is biting legitimate users" — if you see a teacher's name 30 times in the rejection list, the rule may be too tight.

Live stream card

Tail of the most recent content reads. Show all toggle expands from the default head; otherwise the card stays compact. Read-only — for live forensic work while a flag investigation is in flight.

What the monitor does NOT do

  • No auto-suspension. Every action is human-mediated. The monitor surfaces signals; you decide.
  • No alerting (yet). The dashboard is pull-only — you have to open the page. Phase 5 will add Slack / SMS push for high-severity flags.
  • No content moderation. Items being read are not judged here — that's the flag queue. The monitor cares about read patterns, not read content.

Workflow

A typical session:

  1. Open /admin/abuse-monitor. KPIs at the top give you the shape of the window.
  2. Scan Active flags. Each one is a candidate decision.
  3. For each flag, click through to the user row in /admin/users (separate tab). Cross-reference:
    • When did they sign up? (Brand-new account + 500 reads = scraper.)
    • What school are they at? (Real school + matching teacher record = legitimate.)
    • What's their fingerprint count? (Cross-check the Fingerprints card.)
  4. Decide:
    • Legitimate → Dismiss with a note. Rule tuning isn't exposed in the UI — flag repeat false-positives to engineering.
    • Suspect but unsure → Dismiss for now, note the user ID, set a calendar reminder to re-check in 48h.
    • Clear abuse → Suspend with a reason. The user's sessions die immediately and they hit the suspended-account screen on next request.
  5. Hit Refresh to pull fresh data — auto-polling is off to avoid hammering the DB.

Common issues

  • Active flags list is empty but Top viewers shows a clear outlier. The rule that would flag them hasn't fired yet (threshold not hit, or rule disabled). The rule set isn't editable from the UI; raise it with engineering if a rule seems off.
  • Recent blocks is climbing fast. Either an attack in progress, or a recently-tightened rule is biting legitimate users. Cross-reference Recent blocks with Top viewers — if the same names show up in both, your rule is too tight.
  • Suspending the wrong user. Restore from /admin/users → [user] → Restore. The user has to sign in again. Add a note explaining the misfire so a peer admin understands.
  • Edge proxy card shows "Unhealthy". The rate-limit middleware is failing closed. Page on-call — paid content is unprotected until restored.

Related

Did this answer your question? If not, email us and we'll improve this page.