Internet shutdowns are not always BGP withdrawals. Iran has repeatedly run what Aryapour (2025) calls a stealth blackout: leave BGP routes up so the world doesn't see a country fall off the map, but throttle DNS / HTTP / HTTPS below usable thresholds. Looks like a country with normal connectivity on the BGP control plane; users inside can't load anything.

Voidly's forecast uses IODA BGP alerts as a feature. That means stealth blackouts are systematically under-predicted: the BGP data they rely on says everything's fine.

The detection heuristic

  1. Rule 1: IODA ping-slash24 critical alerts ≥ 5 in a country-day (active-probing disruption)
  2. Rule 2: IODA bgp critical alerts < ping-slash24 × 0.5 (BGP relatively stable)
  3. Rule 3: Strength boosted by OONI blocking / interference / middlebox-detection ≥ 0.4 mean value

What we found (30-day window)

Iran's pattern is textbook Aryapour: 2026-05-13 → 2026-05-18, six consecutive days with ping-slash24 critical alerts (84-221/day), BGP critical alerts at 0, and OONI blocking signal ~0.43-0.85 across 5-11 measurements per day.

The unexpected win: back-classification

Of the 458 candidates, 0 are novel — every single one is already in our incidents table. But they're all stored with mechanism = NULL, titled generically “Internet connectivity disruption in country X.”

The detector gives us a way to back-classify those opaque incidents as “stealth blackout / data-plane only” rather than treating them as ordinary outages. That's the unexpected research-grade win — not finding novel events, but characterizing the ones we already know about.

Top countries flagged

CountryCandidate days
VE Venezuela24
EG Egypt18
IN India15
IR Iran15
PA Panama12
TT Trinidad & Tobago12
SI Slovenia11
ZW Zimbabwe9
AO Angola8
BA Bosnia & Herzegovina8

Caveats — what the detector misses

Recommended new sensors (long-term)

What ships today

GET /v1/sentinel/stealth-blackouts returns the candidate list with reasoning, evidence permalinks, matched existing incident IDs, and the documented data gaps. Filter by country, label (candidate / strong_candidate / weak), since, limit.

Marked research_notice: not promoted to production in the response. Forecast feature integration deferred until the global-blip filter lands.

Files: scripts/stealth-blackout-detector.py (heuristic + candidate generator), scripts/patch-stealth-blackout-endpoint.py (atomic Flask route patcher).