central/sql/migrations
Matt Johnson 04c1d07b3f feat(3-K.5): operator-settable EnrichmentConfig (config plumbing)
Bridge PR for v0.5.0. PR J wired the supervisor with a hardcoded
EnrichmentConfig() default; PR K added real backends to the registry but
left no operator path to select one. K.5 closes that gap by mirroring the
config.adapters storage + LISTEN/NOTIFY hot-reload pattern.

config.enrichment (migration 024): single-row table (id BOOLEAN PK CHECK
(id = true), mirroring config.system). Columns enricher_class, backend_class,
backend_settings JSONB, cache_ttl_s, updated_at. Reuses the existing
config.set_updated_at + config.notify_config_change triggers (the NOTIFY
function's ELSE branch emits 'enrichment:' for this keyless single-row table).
Seeds framework DEFAULTS ONLY — GeocoderEnricher + NoOpBackend, empty
backend_settings, 24h TTL. NO URLs/IPs/auth in the seed; a fresh deploy runs
NoOp out of the box. Idempotent (CREATE IF NOT EXISTS / DROP TRIGGER IF
EXISTS / INSERT ON CONFLICT DO NOTHING).

Supervisor:
- Reads config.enrichment at startup (start() -> config_source
  .get_enrichment_config()), overriding the constructor default.
- Hot-reloads via _on_config_change(table == "enrichment"): re-reads the row,
  rebuilds the enricher set, and invalidates the enrichment cache when the
  enricher/backend/settings changed (a new backend must not keep serving the
  old backend's cached bundles until TTL). TTL-only changes retain the cache.
- build_enrichers now takes an explicit EnrichmentCache (the supervisor owns
  it so it can invalidate); cache no longer built inside build_enrichers.

ConfigStore / ConfigSource: get_enrichment_config() (falls back to defaults if
the row is somehow absent) + upsert_enrichment_config(). Mirrors the adapter
accessors.

cache.py: EnrichmentCache.invalidate(enricher_name=None) — DELETE all or
enricher-scoped; returns rows deleted.

GUI /enrichment: GET renders the EnrichmentConfig form via the generic
describe_fields machinery (no enrichment-specific Jinja); POST validates via
Pydantic, writes config.enrichment, and lets the NOTIFY trigger propagate the
hot-reload. New enrichment.html + a nav link. backend_settings (a dict field)
needed a generic "json" widget in describe_fields + the template — usable by
any dict-typed settings field, not enrichment-specific.

Necessary deviation (surfaced): PR K shipped a deployment-specific default
DEFAULT_BASE_URL = "http://192.168.1.130:8440" in navi.py. Bar (b) forbids
deployer IPs in src, and operator-settable base_url is exactly K.5's purpose,
so the default is changed to http://localhost:8440 (matching Photon/Nominatim
defaults). The live integration smoke (tests/, env-gated, skipped) now reads
the endpoint from NAVI_BASE_URL — no IP anywhere in src.

Tests (test_enrichment_config_plumbing.py, 10): ConfigStore read / default
fallback / upsert-passes-dict; cache invalidate all + scoped; supervisor builds
NaviBackend from config; hot-reload rebuilds + invalidates on backend change;
no-invalidate on TTL-only change; describe_fields json widget; /enrichment GET
render. test_firms updated for the build_enrichers signature change.

Hot-reload mechanism mirrored: Postgres LISTEN/NOTIFY on channel
'config_changed' (payload 'table:key'), same path adapters/streams use; the
supervisor's existing _on_config_change dispatch gains an "enrichment" branch.

Verification: full pytest 535 passed, 1 skipped (was 525; +10). Migration
applied cleanly on the live prod schema; SELECT * FROM config.enrichment
returns the NoOp default row. grep subject_for_event/_ADAPTER_REGISTRY and
grep 100.64.0./192.168.1. in src both empty.

Does NOT activate NaviBackend (ships NoOp default; operator action) and does
NOT declare enrichment_locations on other adapters (PR L scope).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:52:22 +00:00
..
001_create_config_schema.sql chore: normalize line endings to LF 2026-05-16 22:26:12 +00:00
002_add_updated_at_trigger_and_index.sql
003_add_streams_table.sql chore: normalize line endings to LF 2026-05-16 22:26:12 +00:00
004_nws_states_to_bbox.sql chore: normalize line endings to LF 2026-05-16 22:26:12 +00:00
005_add_firms_adapter.sql feat(schema): add FIRMS adapter and CENTRAL_FIRE stream 2026-05-16 19:58:20 +00:00
006_add_usgs_quake_adapter.sql feat(schema): add USGS quake adapter and CENTRAL_QUAKE stream 2026-05-16 20:51:28 +00:00
007_add_config_system.sql feat(gui): add auth core, setup gate, and first-run operator creation 2026-05-17 05:30:49 +00:00
008_add_operators.sql feat(gui): add auth core, setup gate, and first-run operator creation 2026-05-17 05:30:49 +00:00
009_add_sessions.sql feat(gui): add auth core, setup gate, and first-run operator creation 2026-05-17 05:30:49 +00:00
010_add_audit_log.sql feat(gui): add auth core, setup gate, and first-run operator creation 2026-05-17 05:30:49 +00:00
011_events_add_adapter_column.sql feat(schema): add adapter column to events, drop source 2026-05-17 16:09:59 +00:00
013_add_session_csrf_token.sql feat(gui): implement first-run setup wizard (1b-8) (#24) 2026-05-17 22:06:22 -06:00
014_events_time_id_index.sql feat(api): add paginated events feed JSON endpoint (#25) 2026-05-17 22:31:00 -06:00
015_add_adapters_last_error.sql refactor(gui): clean up flagged issues before merge 2026-05-18 23:55:34 +00:00
016_add_wfigs_adapters.sql feat(2-B): add NIFC WFIGS adapters for incidents and perimeters 2026-05-19 02:47:26 +00:00
017_add_inciweb_adapter.sql feat(2-C): add NIFC InciWeb wildfire narrative adapter 2026-05-19 03:19:25 +00:00
018_add_swpc_adapters.sql feat(2-D): add NOAA SWPC space weather adapters (alerts, kindex, protons) 2026-05-19 05:55:29 +00:00
019_add_central_space_stream.sql feat(2-D): add NOAA SWPC space weather adapters (alerts, kindex, protons) 2026-05-19 05:55:29 +00:00
020_add_gdacs_adapter.sql feat(2-E): GDACS disaster adapter 2026-05-19 06:58:52 +00:00
021_add_central_disaster_stream.sql feat(2-E): GDACS disaster adapter 2026-05-19 06:58:52 +00:00
022_add_eonet_adapter.sql feat(2-F): NASA EONET disaster adapter 2026-05-19 15:35:25 +00:00
023_add_nwis_adapter_and_hydro_stream.sql feat(2-G): USGS NWIS adapter (OGC API) + CENTRAL_HYDRO stream 2026-05-19 16:50:21 +00:00
024_add_config_enrichment.sql feat(3-K.5): operator-settable EnrichmentConfig (config plumbing) 2026-05-20 18:52:22 +00:00