diff --git a/docs/superpowers/backlog.md b/docs/superpowers/backlog.md index 56fa88b0..cab0e142 100644 --- a/docs/superpowers/backlog.md +++ b/docs/superpowers/backlog.md @@ -37,6 +37,38 @@ Deferred items surfaced during design / planning / execution that we've decided --- +### BL-002 — Native provider integrations for alerting (Slack, Teams, PagerDuty with shipped templates) + +**Opened:** 2026-04-19 +**Surfaced by:** [Alerting design](specs/2026-04-19-alerting-design.md) — §2 Out of scope +**Tracking:** [gitea#138](https://gitea.siegeln.net/cameleer/cameleer-server/issues/138) +**Status:** Open + +**Context.** Alerting v1 ships with generic outbound webhooks + JMustache templates — users paste their Slack incoming webhook URL (or PagerDuty Events API key, or Teams connector URL) and write the body from scratch. A natural fast-follow is to elevate the most common providers to first-class connection types with tuned default templates, provider-specific config hints, and test actions that speak each provider's native format. + +**What's deferred.** +- `SLACK_INCOMING_WEBHOOK` connection type with Block Kit default body template and URL-shape validation. +- `PAGERDUTY_EVENTS_V2` with routing-key input (not URL) and default body tuned to the Events API v2 — including `dedup_key` tied to alert-instance id, severity mapping, and auto-resolve via `event_action: resolve` on alert RESOLVED. +- `MS_TEAMS_CONNECTOR` with adaptive-card/MessageCard default. +- Optional follow-ons: Discord, OpsGenie. + +**Acceptance criteria.** +- Decide on the first 2 providers based on usage data from alerting v1 (likely Slack + PagerDuty). +- Ship templates as versioned resources (`outbound-templates/slack-v1.mustache`) so they can iterate without breaking existing connections. +- Golden-file tests per provider type — payload matches current documented format. +- Provider-integration guide in docs. + +**Why we're not doing it now.** +- Generic webhook + Mustache covers every target today; not a blocker. +- Provider schemas drift (Slack deprecated old JSON once; Teams connectors are on a deprecation path as of late 2025); shipping baked-in templates is a maintenance commitment. +- Usage data will tell us which providers actually matter — shipping three speculatively is wasted work. + +**Links.** +- `cameleer-server-core/src/main/java/com/cameleer/server/core/outbound/` (v1 connection model — extend with `OutboundConnectionType` sealed hierarchy) +- Related (different concern): BL-001 / [gitea#137](https://gitea.siegeln.net/cameleer/cameleer-server/issues/137) + +--- + ## Closed _(nothing yet)_ diff --git a/docs/superpowers/specs/2026-04-19-alerting-design.md b/docs/superpowers/specs/2026-04-19-alerting-design.md index 8923c137..8cab2837 100644 --- a/docs/superpowers/specs/2026-04-19-alerting-design.md +++ b/docs/superpowers/specs/2026-04-19-alerting-design.md @@ -882,6 +882,41 @@ New sidebar/top-nav entry visible to `VIEWER+`. Authoring actions (`POST /rules` 4. **Notify** — title + message templates with *Preview* button; targets multi-select (users / groups / roles with typeahead); outbound connections multi-select filtered by current env + `allowed_environment_ids`. 5. **Review** — summary card, enabled toggle, save. +### Template editor — Mustache with variable auto-complete + +Every Mustache template-editable field — notification title, notification message, webhook URL, webhook header values, webhook body — uses a shared `` component with **variable auto-complete**. Users never have to guess what context variables are available. + +**Behavior.** +- Typing `{{` opens a dropdown of available variables at the caret position. +- Each suggestion shows the variable path (`alert.firedAt`), its type (`Instant`), a one-line description, and a sample rendered value from the canned context. +- Filtering narrows the list as the user keeps typing (`{{ale…` → filters to `alert.*`). +- `Enter` / `Tab` inserts the path and closes `}}` automatically. +- Arrow keys + `Esc` follow standard combobox semantics (ARIA-conformant). + +**Context-aware filtering.** The available variables depend on the rule's condition kind and scope. The editor is aware of both: +- Always shown: `env.*`, `rule.*`, `alert.*` +- `ROUTE_METRIC` with `route.id` set: adds `route.id`, `app.*` +- `EXCHANGE_MATCH`: adds `exchange.*`, `app.*`, `route.id` (if scoped) +- `AGENT_STATE`: adds `agent.*`, `app.*` +- `DEPLOYMENT_STATE`: adds `deployment.*`, `app.*` +- `LOG_PATTERN`: adds `log.*`, `app.*` +- `JVM_METRIC`: adds `metric.*`, `agent.*`, `app.*` + +Variables that *might not* populate (e.g., `alert.resolvedAt` while state is FIRING) are shown with a grey "may be null" badge — users still see them so they can defensively template. + +**Syntax checks inline.** +- Unclosed `{{` / unmatched `}}` flagged with a red underline + hover hint. +- Reference to an out-of-scope variable (e.g., `{{exchange.id}}` in a ROUTE_METRIC rule) flagged with an amber underline + hint ("not available for this rule kind — will render as literal"). +- Checks run client-side on every keystroke (debounced); server-side render preview is still authoritative (§8). + +**Shared implementation.** Same `` component is used in: +- Rule editor — Notify step (title, message) +- Rule editor — Webhook overrides (body override, header value overrides; URL not editable per rule, it's the connection's) +- Admin **Outbound Connections** editor — default body template, default header values, URL (URL gets a reduced context: only `env.*` since a connection URL is rule-agnostic) +- *Test render* inline preview — rendered output updates live as user types + +**Completion engine.** Specific library choice (CodeMirror 6 with a custom completion extension vs Monaco vs a lighter custom overlay on `