Inspiration
Before the US military jams GPS over American airspace, the FAA publishes a warning. One recent advisory for White Sands Missile Range reads:
NAV GPS MAY NOT BE AVBL WI A 366NM RADIUS CENTERED AT 333638N1063320W
A 366-nautical-mile circle. Most of New Mexico, west Texas, and slices of Arizona and Colorado.
That is a forecast. What made me build this is that nobody ever checks it.
FAA files obtained by IEEE Spectrum describe what happens when these tests bite: an airliner descending into El Paso losing GPS and landing without instrument guidance on a runway with "a high CFIT threat due to the climbing terrain"; a controller in Idaho writing that "loss of life can happen because [ATC] and a flight crew believe their equipment are working as intended, but are in fact leading them into the side of the mountain"; a jet near Reno drifting 16 km off course toward opposing traffic. One day near Los Angeles, 21 aircraft — including a medevac helicopter.
And the official record of all this is built from voluntary pilot reports: roughly 90 incidents in eight years. A single air traffic facility logged 173 in six months. The picture the FAA works from is an order of magnitude short of reality, and for a period the agency actively discouraged pilots from reporting unless they needed controller help.
Meanwhile the advisories are known to be over-broad. RTCA's task-group cochair put it plainly: "They say the sky is falling over large areas… and it's not realistic. There are mountains and all kinds of things that would prevent GPS interference from making it 500 nautical miles." So pilots learn to discount the circle — and then get caught by the times it is real.
There is a measurement-shaped hole here, and aircraft are already broadcasting the answer.
What it does
Aeroscan measures the published claim against what actually happened.
Every ADS-B transmission carries NIC and NACp — the aircraft's own statement of how far it trusts the position it is reporting. When a jet at cruise broadcasts zero, its GPS has stopped being trustworthy, and it is telling anyone who listens. No pilot has to file anything.
So Aeroscan:
- Parses the FAA's own advisory PDFs — the centre coordinate, the radius published for each altitude band, and the test windows.
- Samples the sky across and deliberately past that circle — seven overlapping queries. If you only look inside the published area you can never discover anything outside it, which is the finding that would matter most.
- Reports three things: how far degraded aircraft actually reach against the published radius, anything beyond the published boundary, and how many aircraft were affected.
- Rules out the natural cause first. GPS does not only degrade from jamming — a geomagnetic storm drives ionospheric scintillation that produces the same signature over a whole continent. Aeroscan checks live NOAA space weather on every case before it will call anything interference.
- Issues a signed case file — a PDF carrying a SHA-256 digest computed over the case. Re-hash it and one altered field breaks the match.
How we built it
Live ADS-B from community aggregators with multi-source failover and a last-good cache. Six deterministic detectors — degraded integrity, baro/geometric altitude desync, impossible position jumps, stale position, holding, emergency squawks — filtered to enroute ADS-B jets, because low integrity on a light aircraft on final is ordinary and at cruise it is not.
No model sits in the decision path. Detection is deterministic code: the same inputs always produce the same finding, and it can be replayed. A language model narrates and answers questions about a case; it cannot create, suppress or alter one. That is what makes a finding defensible rather than merely plausible.
Corroboration comes from NOAA SWPC (planetary Kp index and live alerts, no key required) and the FAA NOTAM API. Documents are rendered through the Nutrient DWS Processor API. Python/Starlette on Azure Container Apps, dashboard on Static Web Apps.
Challenges we ran into
The first version solved nothing. It detected GPS interference — over military test ranges, where the interference is published a day in advance. That is not a finding, it is reading a NOTAM slowly. The whole product had to be reframed from detecting a phenomenon to measuring a published claim.
I throttled my own feed. Measuring a 366 nm footprint costs nine upstream queries; refreshing all four advisories every poll cycle came to thirty six on top of the region polls. The aggregator answered 429, its cooldown exhausted every fallback, and the live map went to zero aircraft. My first fix reduced how often measurements ran — wrong variable. The limit is on bursts: nine queries 1.2 s apart is ~49/min instantaneously however modest the hourly average looks. Spreading the samples to seven seconds apart and warming one advisory every fifth cycle took sustained load from ~22/min to under 5.
A blind spot that looked like a clean result. An early run reported "no integrity loss across 1,209 aircraft" — except only 43% of them came from a source that publishes integrity fields at all. The rest could not have appeared degraded. Counting them as clear manufactured confidence out of a hole in the data. Aeroscan now reports integrity coverage on every measurement and downgrades its own confidence when coverage is poor.
Accomplishments that we're proud of
The system refuses to overclaim, in three specific ways:
- It will not quote a ratio from fewer than three degraded aircraft. A confident number off a thin sample is precisely the failure this exists to argue against.
- It counts only aircraft whose source reports integrity, and says what fraction that was.
- It states on every page that absence of observed degradation is not proof the test was inactive.
An early validation run was the moment it felt real: pointed at US cargo hubs and the two published GPS test ranges simultaneously, the detectors fired hard over White Sands (12 of 138 aircraft) and the Nevada Test and Training Range (11 of 278) — and stayed completely silent over Memphis (195 aircraft) and Ontario (466). Signal where interference is documented, nothing where it isn't. Real carriers were affected: SWA181, AAL1219, JBU1123, FFT9330.
What we learned
That the interesting question is rarely "can we detect this". It was already detectable. The interesting question was what does nobody check — and the answer was sitting on the other side of a published PDF.
Also, concretely: rate limits are enforced on bursts and not averages; a monitoring tool that shows an empty screen is worse than useless because silence reads as all-clear; and a null result with stated confidence is more trustworthy than an alarm without one.
What's next for Aeroscan
Advisory window tracking — parsing the published test times so the system measures automatically while a window is open and retains the result, instead of depending on someone watching at the right moment. Beyond aviation, the same measurement applies to any published safety claim with observable consequences.
Built With
- ads-b
- agentcore
- amazon-web-services
- azure-container-apps
- azure-static-web-apps
- bedrock
- cloudflare
- docker
- faa-notam-api
- httpx
- javascript
- noaa-swpc
- nutrient-dws
- pypdf
- python
- sha-256
- starlette
- strands-agents
- uvicorn

Log in or sign up for Devpost to join the conversation.