All Docs
FeaturesCalmony Sanctions MonitorUpdated March 11, 2026

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

AlertTriggerSeverityCooldown
Nightly Sanctions Sync Failednightly-sync.ymlif: failure()P0 — CriticalNone (per-run)
Monthly Billing Failedmonthly-billing.ymlif: failure()P1 — CriticalNone (per-run)
Health Check DegradedGET /api/health returns degradedP1 — High15 minutes
Health Check UnhealthyGET /api/health returns unhealthyP0 — Critical15 minutes
Payment Processing FailedalertPaymentFailure() in billing routesP1 — HighNone

Configuration

1. Create a Slack Incoming Webhook

  1. Go to https://api.slack.com/messaging/webhooks
  2. Click Create your Slack app and follow the setup flow
  3. Under Incoming Webhooks, activate the feature and add a new webhook to your alerts channel
  4. 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.md for 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:

ScenarioBehaviour
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-2xxLogs HTTP status; does not throw
Alert within cooldown windowSilently 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

PriorityResponse SLAExamples
P0 — CriticalAcknowledge within 15 minDB down, sanctions sync failing 24+ hrs
P1 — HighAcknowledge within 1 hourScreening wrong results, billing failing
P2 — MediumAcknowledge within 4 hoursSlow health checks, partial list sync failure
P3 — LowNext business dayCosmetic 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