v0.4.0: Geofence hardening, change detection, and the coverage push
Geofences that survive the dateline, notice change, a test suite that reaches the layers the old one never imported, and outages that say so instead of reading as good news.
Geofences (+2 tools = 122)
intel_aoi_changes- the geofence alerting primitive: what entered or left a user-defined AOI since the last sweep, per domain (earthquakes, military flights, ACLED events, wildfire clusters, news mentions). First sweep is an explicit baseline; a failed domain fetch goes todata_gapsand is excluded from the diff, so an outage never reads as "everything left the area". Sampled aviation is excluded by design.intel_aoi_update- rename and/or re-center/resize an AOI in place. A rename keeps change-detection history; a geometry change drops it.- Antimeridian fix: an AOI circle crossing the dateline (Bering Strait, Fiji) now queries both sides of lon 180 instead of silently losing one; a one-box failure surfaces as
partial coverage. - Lines are lines: pipelines and undersea cables match by great-circle segment distance (cross-track with endpoint clamping), so a midspan crossing your AOI is detected even when the endpoints are hundreds of km away.
Test suite and coverage
The 0.3.0 suite was green at 309 tests but covered 59% of statements; server.py, cli.py, collector.py, and most of the NLP analysis layer were never imported by any test. This release adds test waves for those layers: 597 non-smoke tests, 81% statement coverage, with a CI ratchet (--cov-fail-under=80) so the gains cannot silently erode.
Data honesty
Five verified bugs fixed, all in the fail-quietly family:
intel_world_briefandintel_fleet_reporteach read a field their producer never emits, yielding plausible zeros in every real run (silent-zero key mismatches).- A UNHCR outage read as zero refugees worldwide (#22); failed climate zones vanished without a marker (#23); "Resolved: Major outage" post-mortems counted as active critical incidents and dead status feeds masqueraded as healthy providers (#24). All three now carry explicit
error/degraded/unavailable_*markers.
Security
SECURITY.md states the threat model explicitly (prompted by the external report in #21): what the trust boundaries are, what hardening exists inside them, and what is out of scope for a single-user local OSINT tool. Cache databases are now created with owner-only permissions (0600).
Full detail in CHANGELOG.md. ROADMAP.md now carries a forward-looking plan (Phases 23-26).