Notification module
Webhook-based notifications for system events.
Overview
Section titled “Overview”- Pattern matching on event codes
- Rate limiting (debounce and cooldown)
- Jinja2 templating
Configuration
Section titled “Configuration”notifications: - name: slack-critical url: https://hooks.slack.com/... patterns: - "V500*" # All 500-level events - "A*" # All audit events cooldown: 300Pattern Matching
Section titled “Pattern Matching”Glob-style patterns on event/error class codes:
| Pattern | Matches |
|---|---|
V500* | All V-prefixed 500-level events |
A* | All audit events |
H* | All health events |
X400* | All 400-level errors |
* | Everything |
Rate limiting
Section titled “Rate limiting”| Setting | Description |
|---|---|
debounce | Wait N after the first event before sending (batches rapid-fire events) |
cooldown | After sending, ignore the same event class for N |
Duration format: 30s, 5m, 1h, 1d.
Retry behavior
Section titled “Retry behavior”| Setting | Default | Description |
|---|---|---|
retries | 3 | Max retry attempts on failure |
timeout | 10s | HTTP request timeout |
Retry sequence: 1s → 2s → 4s (exponential backoff, ×2 multiplier).
Templates
Section titled “Templates”Templates use native Jinja2 syntax ({{ var }}, {% if %}, etc.).
The notification engine passes template strings straight to Jinja2
with no pre-processing:
| Variable | Description |
|---|---|
{{ event.code }} | Event class name (e.g., V500100) |
{{ event.message }} | Rendered event message |
{{ event.payload }} | Original event kwargs |
{{ context.tenant }} | Tenant name |
{{ context.stack }} | Stack name (may be null) |
{{ context.environment }} | Environment name (may be null) |
{{ timestamp }} | ISO 8601 UTC timestamp |
Standard Jinja2 filters available: default, to_json, to_yaml,
upper, lower, quote, basename.
Default templates ship for Slack, Discord, Teams, Telegram, PagerDuty, Pushover, and ntfy; everything else uses the generic JSON body.
Full example
Section titled “Full example”# config.yaml (any scope)notifications: - name: slack-critical url: !ref+vault://notifications/slack-webhook on: - "V500*" - "X500*" - "H500*" debounce: "30s" cooldown: "5m" retries: 3 timeout: "10s" body: | text: "{{ event.message }}" blocks: - type: section text: type: mrkdwn text: | *Event:* `{{ event.code }}` *Tenant:* {{ context.tenant }} *Stack:* {{ context.stack | default('N/A') }} *Time:* {{ timestamp }}Providers
Section titled “Providers”All providers use HTTP webhooks - no external packages required.
| Provider | URL Pattern | Auto-Detection |
|---|---|---|
| Slack | hooks.slack.com | ✅ |
| Discord | discord.com/api/webhooks | ✅ |
| Microsoft Teams | webhook.office.com | ✅ |
| Telegram | api.telegram.org | ✅ |
| PagerDuty | events.pagerduty.com | ✅ |
| Pushover | api.pushover.net | ✅ |
| ntfy | ntfy in URL | ✅ |
| Email (SMTP) | N/A (use email: config) | N/A |
| Generic | Any other URL | Default |
Email Configuration
Section titled “Email Configuration”notifications: - name: email-critical url: "" # Not used for email on: ["V500*"] email: host: smtp.example.com port: 587 tls: true username: user@example.com password: ref+vault://smtp_password from: alerts@example.com to: - admin@example.com - ops@example.com subject: "[SHC] {{ event.code }}: {{ event.message }}"See Also
Section titled “See Also”shc@docs:~$