mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-08-26 17:31:34 +00:00
feat(dashboard): bring ipaws adapter + emergency family to full GUI parity (#158)
The IPAWS civil-alert adapter shipped backend-complete but frontend-partial: it rendered only in the generic adapter-config page and the Advanced (raw) Data Feeds tab, and the `emergency` family was absent from the curated Data Feeds panel, the family-settings toggles, and the MeshCore routing matrix. Adapter (ipaws), benchmarked against firms/nws: - Environment.tsx: add `ipaws` to AdapterKey union, EnvConfig interface, META (native-only, keyless), a new `emergency` FAMILIES group, PANEL_META_KEY (LLM toggle), and a hand-written renderSettings panel exposing base_url, user_agent, tick_seconds, state_fips, same_codes, exclude_weather, status_actual_only — with coverage-scope handling like the other adapters. - Environment.tsx: IPAWS_DEFAULT backfill so pre-ipaws GET payloads don't crash. - Dashboard.tsx: SOURCE_ICONS entry (Siren/IPAWS) so ipaws events aren't a slug. - ActivityLog.tsx: TABLE_LABELS + CATEGORIES + text-hint so ipaws_alerts rows show labeled "Emergency" and honor the category filter. - dispatcher.py: _SOURCE_TO_TABLE fallback ipaws -> ipaws_alerts so region-routed emergency sends land labeled in the audit feed (not NULL). Family (emergency), benchmarked against fire: - Notifications.tsx: add `emergency` to TOGGLE_FAMILY_META (Siren icon). This cascades to Family Settings, the Meshtastic delivery matrix, and the MeshCore routing matrix (the last was hardcoded to the static list and previously omitted emergency entirely). Backend VALID_TOGGLES/gating/categories were already complete — no backend family change needed. Tests: update the _SOURCE_TO_TABLE exact-match guard and add an ipaws audit-row parity test. Full suite 2407 passed / 6 pre-existing unrelated failures. Co-authored-by: Matt Johnson <mj@k7zvx.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c04daa6e4d
commit
e244405230
8 changed files with 207 additions and 82 deletions
|
|
@ -554,8 +554,50 @@ def test_source_to_table_fallback_stamps_audit_row(db_path):
|
|||
assert row["source_event_pk"] is None, "pk should be NULL for fallback path"
|
||||
|
||||
|
||||
def test_source_to_table_fallback_stamps_ipaws_audit_row(db_path):
|
||||
"""Parity guard for the IPAWS civil-alert adapter: a native ipaws event
|
||||
with no _broadcast_audit must stamp source_event_table='ipaws_alerts' so
|
||||
emergency sends show labeled (not NULL/unlabeled) in the Activity Log.
|
||||
"""
|
||||
from unittest.mock import MagicMock
|
||||
from meshai.notifications.events import make_event
|
||||
from meshai.notifications.pipeline.dispatcher import Dispatcher
|
||||
from meshai.persistence import get_db
|
||||
|
||||
cfg = _build_config(cold_start_grace=0)
|
||||
factory, _ = _mk_channel_factory()
|
||||
d = Dispatcher(cfg, factory)
|
||||
|
||||
ev = make_event(
|
||||
source="ipaws",
|
||||
category="emergency_evacuation",
|
||||
severity="immediate",
|
||||
region="US-ID",
|
||||
title="🚨 Evacuation Immediate",
|
||||
lat=43.6, lon=-116.2,
|
||||
)
|
||||
|
||||
rule = MagicMock()
|
||||
rule.broadcast_channel = 1
|
||||
rule.delivery_types = ["mesh_broadcast"]
|
||||
|
||||
payload = MagicMock()
|
||||
payload.message = "🚨 Evacuation Immediate — test"
|
||||
|
||||
d._post_broadcast_commit(ev, payload, rule, "mesh_broadcast", success=True)
|
||||
|
||||
conn = get_db()
|
||||
row = conn.execute(
|
||||
"SELECT source_event_table FROM mesh_broadcasts_out ORDER BY id DESC LIMIT 1"
|
||||
).fetchone()
|
||||
assert row is not None, "No audit row was written"
|
||||
assert row["source_event_table"] == "ipaws_alerts", (
|
||||
f"Expected 'ipaws_alerts', got {row['source_event_table']!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_source_to_table_fallback_all_native_sources(db_path):
|
||||
"""Verify _SOURCE_TO_TABLE covers all five native adapter sources."""
|
||||
"""Verify _SOURCE_TO_TABLE covers all native adapter sources."""
|
||||
from meshai.notifications.pipeline.dispatcher import Dispatcher
|
||||
expected = {
|
||||
"nws": "nws_alerts",
|
||||
|
|
@ -563,6 +605,7 @@ def test_source_to_table_fallback_all_native_sources(db_path):
|
|||
"wzdx": "traffic_events",
|
||||
"traffic": "traffic_events",
|
||||
"511": "traffic_events",
|
||||
"ipaws": "ipaws_alerts",
|
||||
}
|
||||
cfg = _build_config()
|
||||
factory, _ = _mk_channel_factory()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue