Incident Response Notifications (ISO-05)
Incident Response Notifications
ISO 27001 Control: ISO-05
Automated Slack alerts and an on-call runbook for critical system failures.
⚠️ Status: This feature is defined in PR #39. The source branch was deleted before merging and the code is not yet on
main. This page documents the intended behaviour once the PR is re-submitted and merged.
Overview
When the nightly sanctions sync, monthly billing cycle, health check, or payment processing encounters a critical failure, the platform sends an automated alert to a configured Slack channel. All alert paths are fire-and-forget and fail open — if Slack is not configured, no product functionality is affected.
Alert Sources
| Alert | Trigger | Severity | Cooldown |
|---|---|---|---|
| Nightly Sanctions Sync Failed | nightly-sync.yml — if: failure() | P0 — Critical | None (per-run) |
| Monthly Billing Failed | monthly-billing.yml — if: failure() | P1 — Critical | None (per-run) |
| Health Check Degraded | GET /api/health returns degraded | P1 — High | 15 minutes |
| Health Check Unhealthy | GET /api/health returns unhealthy | P0 — Critical | 15 minutes |
| Payment Processing Failed | alertPaymentFailure() in billing routes | P1 — High | None |
Configuration
1. Create a Slack Incoming Webhook
- Go to https://api.slack.com/messaging/webhooks
- Click Create your Slack app and follow the setup flow
- Under Incoming Webhooks, activate the feature and add a new webhook to your alerts channel
- Copy the webhook URL (format:
https://hooks.slack.com/services/...)
2. Set the environment variable
GitHub repository secrets (for workflow alerts):
Settings → Secrets and variables → Actions → New repository secret
Name: SLACK_ALERT_WEBHOOK_URL
Value: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
Vercel environment variables (for runtime alerts from /api/health and payment routes):
Vercel Dashboard → Project → Settings → Environment Variables
SLACK_ALERT_WEBHOOK_URL = https://hooks.slack.com/services/YOUR/WEBHOOK/URL
Add to .env.local for local development (optional):
# Incident Response Notifications — ISO 27001 ISO-05
SLACK_ALERT_WEBHOOK_URL= # Slack Incoming Webhook URL
Alert Payload
All alerts use Slack Block Kit formatting. A typical alert includes:
- Header — alert name with
:rotating_light:indicator - Severity — P0/P1 label
- Context fields — source list, trigger type, dry-run mode, timestamp (UTC)
- Impact statement — plain-language description of the business and regulatory impact
- Action button — direct link to the failed GitHub Actions run
- Runbook link — link to
RUNBOOK.mdfor escalation procedures
Runtime Alert Utility (src/lib/alert.ts)
For application code, import the pre-built helpers:
import {
alertSanctionsSyncFailure,
alertPaymentFailure,
alertHealthDegradation,
sendCriticalAlert,
} from '@/lib/alert';
alertHealthDegradation(status, checks)
Call from GET /api/health when the response status is degraded or unhealthy. A 15-minute cooldown is enforced internally — repeated calls within the window are silently suppressed to prevent alert storms from uptime monitors polling at high frequency.
alertSanctionsSyncFailure(source, error)
Call from sanctions import API routes when a sync operation fails at runtime.
alertPaymentFailure(context, error)
Call from Stripe/billing routes when a payment processing error occurs.
sendCriticalAlert(options) — generic sender
Accepts severity: 'critical' | 'high' | 'warning' and a free-form message payload. Use for custom alert scenarios not covered by the pre-built helpers.
Graceful Degradation
All alert paths are designed to never break the calling code:
| Scenario | Behaviour |
|---|---|
SLACK_ALERT_WEBHOOK_URL not set (workflow) | Logs ::warning:: to Actions output and continues |
SLACK_ALERT_WEBHOOK_URL not set (runtime) | Logs to console.error (captured by Vercel/CloudWatch) |
| Slack webhook returns non-2xx | Logs HTTP status; does not throw |
| Alert within cooldown window | Silently suppressed; no error thrown |
On-Call Runbook (RUNBOOK.md)
A RUNBOOK.md file in the repository root documents procedures for every automated alert. Key sections:
Severity Classification
| Priority | Response SLA | Examples |
|---|---|---|
| P0 — Critical | Acknowledge within 15 min | DB down, sanctions sync failing 24+ hrs |
| P1 — High | Acknowledge within 1 hour | Screening wrong results, billing failing |
| P2 — Medium | Acknowledge within 4 hours | Slow health checks, partial list sync failure |
| P3 — Low | Next business day | Cosmetic bugs, non-critical integrations |
Regulatory Obligations
The runbook includes a dedicated section on regulatory reporting requirements:
- OFSI — obligations when a sanctions list sync has been stale for a material period
- ICO — 72-hour reporting window for data breaches affecting personal data
Refer to RUNBOOK.md in the repository for complete playbooks.
Related
- Changelog — v0.1.1
RUNBOOK.md(link once merged)- Slack Incoming Webhooks documentation