Native provider integrations for alerting (Slack, Teams, PagerDuty with shipped templates) #138

Open
opened 2026-04-19 15:08:38 +02:00 by claude · 0 comments
Owner

Context

Alerting v1 ships with outbound webhooks + JMustache templates and a "plain URL" flow — users paste their Slack incoming webhook URL (or PagerDuty Events API key, or Teams connector URL) and either use the default JSON envelope or write their own Mustache body. This works, but forces users to know each provider's expected payload format.

A natural fast-follow: elevate the most common providers to first-class "connection types" that ship with tuned default templates and provider-specific config hints.

What this would add

First-class connection types

Extend the OutboundConnection.auth_kind / type model to include provider-typed connections:

  • SLACK_INCOMING_WEBHOOK — URL shape validated (https://hooks.slack.com/...); default body template uses Slack Block Kit for severity coloring and alert metadata
  • PAGERDUTY_EVENTS_V2 — routing key instead of URL; default body shaped to PagerDuty Events API v2 (dedup_key tied to alert instance id; severity mapping: CRITICAL → critical, WARNING → warning, INFO → info; auto-resolve on RESOLVED)
  • MS_TEAMS_CONNECTOR — default body uses Teams MessageCard / adaptive card format
  • DISCORD_WEBHOOK — optional; cheap to add once the pattern exists
  • OPSGENIE_REST — optional

UI

  • Admin picks the connection type at create-time; the form swaps to the provider-specific fields
  • Default templates are shipped as read-only baselines; users can still override per rule
  • Test action uses the provider's real webhook format (we know the schema)

Backend

  • New sealed OutboundConnectionType hierarchy in core/outbound/
  • Each type owns: URL validator, default body template resource, severity mapping, auto-resolve semantics (PagerDuty has explicit event_action: resolve, Slack doesn't — resolve just sends another message)
  • Dispatch path already rendered payloads at first attempt (Section 4 / 8 of alerting spec); this just changes what defaults flow in

Why we're not doing it in v1

  • Generic webhook + Mustache covers every target today; not a blocker
  • Provider schemas drift (Slack deprecated the old JSON format once, Teams connectors are on a deprecation path as of late 2025); shipping baked-in templates means we take on a maintenance commitment
  • Usage data will tell us which providers actually matter. Shipping three and finding nobody uses Discord is wasted effort
  • Post-v1 user feedback may also reveal a different axis (e.g., "we need it to create a Linear ticket") that's more valuable than another chat-tool integration

Acceptance criteria

  • Decide on the first 2 providers based on usage data from alerting v1 (likely Slack + PagerDuty)
  • Ship shipped templates behind versioned resources (outbound-templates/slack-v1.mustache) so we can iterate without breaking existing connections
  • Test coverage: golden-file tests per provider type asserting the rendered payload matches the provider's current documented format
  • Docs: a provider-integration guide showing each type's capabilities and defaults
  • Alerting design spec: docs/superpowers/specs/2026-04-19-alerting-design.md (see §2 Out of scope, §6 Outbound connections, §8 Notification dispatch)
  • Related (different concern): gitea#137 (managed CA bundles)
  • Local backlog: docs/superpowers/backlog.md → BL-002
## Context Alerting v1 ships with outbound webhooks + JMustache templates and a "plain URL" flow — users paste their Slack incoming webhook URL (or PagerDuty Events API key, or Teams connector URL) and either use the default JSON envelope or write their own Mustache body. This works, but forces users to know each provider's expected payload format. A natural fast-follow: elevate the most common providers to first-class "connection types" that ship with tuned default templates and provider-specific config hints. ## What this would add ### First-class connection types Extend the `OutboundConnection.auth_kind` / type model to include provider-typed connections: - `SLACK_INCOMING_WEBHOOK` — URL shape validated (`https://hooks.slack.com/...`); default body template uses Slack Block Kit for severity coloring and alert metadata - `PAGERDUTY_EVENTS_V2` — routing key instead of URL; default body shaped to PagerDuty Events API v2 (`dedup_key` tied to alert instance id; severity mapping: CRITICAL → `critical`, WARNING → `warning`, INFO → `info`; auto-resolve on RESOLVED) - `MS_TEAMS_CONNECTOR` — default body uses Teams MessageCard / adaptive card format - `DISCORD_WEBHOOK` — optional; cheap to add once the pattern exists - `OPSGENIE_REST` — optional ### UI - Admin picks the connection type at create-time; the form swaps to the provider-specific fields - Default templates are shipped as read-only baselines; users can still override per rule - Test action uses the provider's real webhook format (we know the schema) ### Backend - New sealed `OutboundConnectionType` hierarchy in `core/outbound/` - Each type owns: URL validator, default body template resource, severity mapping, auto-resolve semantics (PagerDuty has explicit `event_action: resolve`, Slack doesn't — resolve just sends another message) - Dispatch path already rendered payloads at first attempt (Section 4 / 8 of alerting spec); this just changes what defaults flow in ## Why we're not doing it in v1 - Generic webhook + Mustache covers every target today; not a blocker - Provider schemas drift (Slack deprecated the old JSON format once, Teams connectors are on a deprecation path as of late 2025); shipping baked-in templates means we take on a maintenance commitment - Usage data will tell us which providers actually matter. Shipping three and finding nobody uses Discord is wasted effort - Post-v1 user feedback may also reveal a different axis (e.g., "we need it to create a Linear ticket") that's more valuable than another chat-tool integration ## Acceptance criteria - Decide on the first 2 providers based on usage data from alerting v1 (likely Slack + PagerDuty) - Ship shipped templates behind versioned resources (`outbound-templates/slack-v1.mustache`) so we can iterate without breaking existing connections - Test coverage: golden-file tests per provider type asserting the rendered payload matches the provider's current documented format - Docs: a provider-integration guide showing each type's capabilities and defaults ## Links - Alerting design spec: `docs/superpowers/specs/2026-04-19-alerting-design.md` (see §2 Out of scope, §6 Outbound connections, §8 Notification dispatch) - Related (different concern): gitea#137 (managed CA bundles) - Local backlog: `docs/superpowers/backlog.md` → BL-002
Sign in to join this conversation.