v1.2.0 Phase C1: email channel, NWS CAP fallback, pipeline drill #101

Merged
claude-bot merged 1 commit from feat/v1.2.0-phaseC1-email-cap-drill into main 2026-07-18 21:37:45 +00:00
Contributor

Three v1.2.0 feature issues.

#80 — Email / SMTP channel

New ChannelType.email (migration 0021, ALTER TYPE ADD VALUE, mirroring the webex one) + an SMTP notifier built through the shared formatter, sending via stdlib smtplib offloaded with asyncio.to_thread (no event-loop block). SMTP failures are classified into the Transient/Permanent DeliveryError taxonomy so the outbox retries them correctly. Recipients are redacted for non-managers; EmailConfig validation + a channels-UI recipients field. Global SMTP_* settings.

#78 — NWS CAP fallback

When the primary /alerts/active JSON fetch exhausts its retries, fall back to the api.weather.gov CAP ATOM feed (stdlib ElementTree) so a JSON-path failure doesn't blind the poller. Best-effort: any CAP error falls through to None, preserving the existing skip-cycle-on-outage contract. Gated by NWS_CAP_FALLBACK_ENABLED (default on).

⚠️ The independent alerts.weather.gov CAP host was retired, so this shares api.weather.gov with the primary — it guards JSON-path failures, not a full host outage. True host-independence would need a third-party CAP mirror (didn't assume one).

#86 — Pipeline drill

Admin-only POST /api/diagnostics/pipeline-drill injects a synthetic "Pipeline Drill (TEST)" alert through the real matching → dedup → dispatch → outbox path for end-to-end verification, with a dry_run mode. CSRF-protected, short-expiry, clearly-marked TEST event.

Testing

Full suite green on the dev server: 617 passed (28 new tests); migration 0021 applies cleanly through to head on real Postgres.

Closes #80, #78, #86

🤖 Generated with Claude Code

Three v1.2.0 feature issues. ## #80 — Email / SMTP channel New `ChannelType.email` (migration `0021`, `ALTER TYPE ADD VALUE`, mirroring the webex one) + an SMTP notifier built through the shared formatter, sending via stdlib `smtplib` offloaded with `asyncio.to_thread` (no event-loop block). SMTP failures are classified into the `Transient`/`Permanent` `DeliveryError` taxonomy so the outbox retries them correctly. Recipients are redacted for non-managers; `EmailConfig` validation + a channels-UI recipients field. Global `SMTP_*` settings. ## #78 — NWS CAP fallback When the primary `/alerts/active` JSON fetch exhausts its retries, fall back to the `api.weather.gov` CAP ATOM feed (stdlib ElementTree) so a JSON-path failure doesn't blind the poller. Best-effort: any CAP error falls through to `None`, preserving the existing skip-cycle-on-outage contract. Gated by `NWS_CAP_FALLBACK_ENABLED` (default on). > ⚠️ The independent `alerts.weather.gov` CAP host was **retired**, so this shares `api.weather.gov` with the primary — it guards JSON-path failures, not a full host outage. True host-independence would need a third-party CAP mirror (didn't assume one). ## #86 — Pipeline drill Admin-only `POST /api/diagnostics/pipeline-drill` injects a synthetic "Pipeline Drill (TEST)" alert through the real matching → dedup → dispatch → outbox path for end-to-end verification, with a `dry_run` mode. CSRF-protected, short-expiry, clearly-marked TEST event. ## Testing Full suite green on the dev server: **617 passed** (28 new tests); migration `0021` applies cleanly through to head on real Postgres. Closes #80, #78, #86 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add email/SMTP channel, NWS CAP fallback, and pipeline drill
All checks were successful
CI / test (pull_request) Successful in 4m16s
4a4bc015d0
Email channel (#80): new ChannelType.email (migration 0021, ALTER TYPE ADD VALUE)
and an SMTP notifier built through the shared formatter, sending via stdlib
smtplib offloaded with asyncio.to_thread. Classifies SMTP failures into the
Transient/Permanent DeliveryError taxonomy so the outbox retries them correctly;
recipient addresses are redacted for non-managers. EmailConfig validation + a
channels-UI recipients field. Global SMTP_* settings.

NWS CAP fallback (#78): when the primary /alerts/active JSON fetch exhausts its
retries, fall back to the api.weather.gov CAP ATOM feed (parsed with stdlib
ElementTree) so a JSON-path failure doesn't blind the poller. Best-effort: any
CAP error falls through to None, preserving the skip-the-cycle-on-outage
contract. Gated by NWS_CAP_FALLBACK_ENABLED (default on). (Note: the independent
alerts.weather.gov host was retired, so this shares api.weather.gov with the
primary — it guards JSON-path failures, not a full host outage.)

Pipeline drill (#86): admin-only POST /api/diagnostics/pipeline-drill injects a
synthetic "Pipeline Drill (TEST)" alert through the real matching/dedup/dispatch/
outbox path for end-to-end verification, with a dry_run mode.

Full suite green on the dev server: 617 passed; migration 0021 applies cleanly.

Closes #80, #78, #86

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude-bot deleted branch feat/v1.2.0-phaseC1-email-cap-drill 2026-07-18 21:37:46 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot!101
No description provided.