Skip to content

@rpallas/outcrop-chatops ​

Delivers platform alerts to Slack and Microsoft Teams incoming webhooks. ChatOpsNotifier subscribes one Lambda function to SNS topics (by default the four per-severity alert topics the account baseline publishes) and renders CloudWatch alarm state changes, AWS Budgets notifications, EventBridge events and plain text messages as Slack Block Kit messages or Teams Adaptive Cards.

sh
npm install @rpallas/outcrop-chatops

Creating the webhook secrets ​

Webhook URLs are secrets. Store them in Secrets Manager, never in code or templates. With the account baseline (@rpallas/outcrop-account) declare them as shared secrets:

ts
sharedSecrets: { secrets: { "slack-webhook": {}, "teams-webhook": {} } },

The baseline generates placeholder values and publishes the ARNs under /platform/secrets/{name}/arn. Replace the values once with the real webhook URLs:

sh
aws secretsmanager put-secret-value \
  --secret-id platform-dev-slack-webhook \
  --secret-string 'https://hooks.example.com/services/T000/B000/XXXX'

Plain URL strings and JSON documents { "url": "https://..." } are both accepted.

Usage from a service stack ​

Inside a PlatformStack everything defaults to the SSM contract: the topics are the environment alert topics and the secrets are the shared slack-webhook / teams-webhook secrets.

ts
import { ChatOpsNotifier } from "@rpallas/outcrop-chatops";

new ChatOpsNotifier(this, "ChatOps", {
  destinations: [
    { kind: "slack", channelLabel: "#orders-alerts" },
    { kind: "teams", minimumSeverity: "high", webhookSecretName: "ops-teams-webhook" },
  ],
});

Options:

PropDefaultNotes
destinationsrequiredOne or more Slack/Teams destinations
topicsenvironment alert topicsAny ITopic[]; required outside a PlatformStack
severitiesall fourSubset of the default topics to subscribe to
deadLetterQueuetruefalse to disable, or an existing IQueue
errorAlarmtrueerrors alarm on the function (routed to the high topic)
timeout30 seconds

Per destination: kind (slack or teams), webhookSecretName or webhookSecret, minimumSeverity (default low, meaning everything) and an optional channelLabel rendered in the message.

The construct exposes handler (a PlatformFunction inside a PlatformStack), topics, destinations, deadLetterQueue and errorAlarm.

Usage from the account baseline ​

The account baseline stack is a plain Stack, and the natural place to route the environment's alert topics because it owns them. Outside a PlatformStack the construct falls back to a plain NodejsFunction (ARM64, Node.js 24, X-Ray, one-month log retention) and requires explicit topics and a webhookSecret per destination; the errors alarm is not created there.

ts
import { ALERT_SEVERITIES } from "@rpallas/outcrop";
import { createAccountBaseline } from "@rpallas/outcrop-account";
import { ChatOpsNotifier } from "@rpallas/outcrop-chatops";

const { baseline } = createAccountBaseline(app, { config, modules });
const { alerting, sharedSecrets } = baseline.baseline;
const slackWebhook = sharedSecrets?.secrets["slack-webhook"];
if (alerting && slackWebhook) {
  new ChatOpsNotifier(baseline, "ChatOps", {
    topics: ALERT_SEVERITIES.map((severity) => alerting.topics[severity]),
    destinations: [{ kind: "slack", webhookSecret: slackWebhook }],
  });
}

What gets delivered ​

Each SNS record is normalised into one message:

  • CloudWatch alarms – header :rotating_light: <alarm> is ALARM (:white_check_mark: for OK, :grey_question: for INSUFFICIENT_DATA), fields for severity, environment, service, account, region, time, metric and threshold, the state reason, and a deep link to the alarm in the console. Service and severity come from the platform alarm description ([high] orders: api-errors); the environment from the topic name (platform-dev-alerts-high).
  • AWS Budgets – budget name, threshold and current amount extracted from the notification text.
  • EventBridge events – detail-type, source and the pretty-printed detail.
  • Anything else – subject and message text.

Severity is taken from the platform:severity SNS message attribute when present, otherwise from the topic name suffix (...-alerts-critical), otherwise medium. Destinations with a minimumSeverity above the message severity are skipped.

Slack messages use Block Kit (header, section fields, context with the console link). Teams messages are application/vnd.microsoft.card.adaptive attachments with an Adaptive Card 1.4 (TextBlock, FactSet, Action.OpenUrl).

Delivery failures with 429 or 5xx responses are retried once; a persistent failure makes the invocation fail so the SNS retry policy and the dead letter queue apply.

Limitations ​

  • Incoming webhooks only; no interactive messages, threading or acknowledgements.
  • Both Slack and Teams truncate long payloads; reasons and bodies are cut to fit.
  • Webhook URLs are cached for the lifetime of the Lambda execution environment; rotate a secret and the function picks it up after the next cold start or a failed delivery.
  • The errors alarm of the notifier itself routes to the high topic, so a notifier that is permanently broken produces a notification it cannot deliver; the dead letter queue keeps those.

Classes ​

ChatOpsNotifier ​

Defined in: chatops.ts:78

Delivers SNS alert notifications (CloudWatch alarms, AWS Budgets, EventBridge events or plain text) to Slack and Microsoft Teams incoming webhooks.

Inside a PlatformStack the topics and webhook secrets default to the account baseline's contract and the function is a PlatformFunction with the usual naming, log retention and alarms. In a plain Stack (for example the account baseline itself) pass explicit topics and a webhookSecret per destination.

Extends ​

  • Construct

Constructors ​

Constructor ​
ts
new ChatOpsNotifier(
   scope, 
   id, 
   props
): ChatOpsNotifier;

Defined in: chatops.ts:93

Parameters ​
ParameterType
scopeConstruct
idstring
propsChatOpsNotifierProps
Returns ​

ChatOpsNotifier

Overrides ​
ts
Construct.constructor

Properties ​

PropertyModifierTypeDescriptionDefined in
deadLetterQueuereadonlyIQueue | undefinedDead letter queue when enabled.chatops.ts:89
destinationsreadonlyreadonly object[]Resolved destinations with their secrets.chatops.ts:84
errorAlarmreadonlyPlatformAlarm | undefinedErrors alarm when created.chatops.ts:91
handlerreadonlyNodejsFunctionThe notifier function (PlatformFunction inside a PlatformStack).chatops.ts:80
topicsreadonlyreadonly ITopic[]Topics this notifier is subscribed to.chatops.ts:82

Interfaces ​

AlertField ​

Defined in: message-templates.ts:24

Properties ​

PropertyModifierTypeDefined in
labelreadonlystringmessage-templates.ts:25
valuereadonlystringmessage-templates.ts:26

AlertMessage ​

Defined in: message-templates.ts:7

Normalised notification, independent of the chat provider.

Properties ​

PropertyModifierTypeDescriptionDefined in
account?readonlystring-message-templates.ts:17
env?readonlystring-message-templates.ts:15
fieldsreadonlyreadonly AlertField[]Extra label/value pairs rendered as fields.message-templates.ts:21
kindreadonly"alarm" | "budget" | "event" | "text"-message-templates.ts:8
link?readonlystring-message-templates.ts:19
reason?readonlystring-message-templates.ts:13
region?readonlystring-message-templates.ts:18
service?readonlystring-message-templates.ts:16
severityreadonly"critical" | "high" | "medium" | "low"-message-templates.ts:11
statereadonlyAlertState-message-templates.ts:10
summaryreadonlystring-message-templates.ts:12
time?readonlystring-message-templates.ts:14
titlereadonlystring-message-templates.ts:9

BudgetNotification ​

Defined in: message-templates.ts:51

Parsed AWS Budgets notification (plain text e-mail style message).

Properties ​

PropertyModifierTypeDefined in
accountId?readonlystringmessage-templates.ts:53
actualText?readonlystringmessage-templates.ts:55
bodyreadonlystringmessage-templates.ts:56
budgetName?readonlystringmessage-templates.ts:52
thresholdText?readonlystringmessage-templates.ts:54

ChatOpsDestination ​

Defined in: chatops.ts:26

Properties ​

PropertyModifierTypeDescriptionDefined in
channelLabel?readonlystringFree-text label rendered in the message, for example the channel name.chatops.ts:40
kindreadonlyChatOpsKindChat provider; selects the payload format.chatops.ts:28
minimumSeverity?readonly"critical" | "high" | "medium" | "low"Lowest severity delivered to this destination. Default low (everything).chatops.ts:38
webhookSecret?readonlyISecretExplicit webhook secret instead of webhookSecretName.chatops.ts:36
webhookSecretName?readonlystringName of the shared secret (published by the account baseline under /platform/secrets/{name}/arn) holding the incoming webhook URL. Default slack-webhook / teams-webhook. Requires a PlatformStack.chatops.ts:34

ChatOpsNotifierProps ​

Defined in: chatops.ts:43

Properties ​

PropertyModifierTypeDescriptionDefined in
deadLetterQueue?readonlyboolean | IQueueSend failed deliveries to a dead letter queue. Default true. Pass an existing queue to reuse it.chatops.ts:58
destinationsreadonlyChatOpsDestination[]Where to deliver messages. At least one.chatops.ts:53
errorAlarm?readonlybooleanCreate the errors alarm on the notifier function (routed to the environment's high topic). Default true inside a PlatformStack; never created in a plain Stack.chatops.ts:64
severities?readonly("critical" | "high" | "medium" | "low")[]Only subscribe to these severities when using the default topics. Default: all four.chatops.ts:51
timeout?readonlyDurationFunction timeout. Default 30 seconds.chatops.ts:66
topics?readonlyITopic[]Topics to subscribe to. Default: the environment alert topics published by the account baseline (/platform/env/{env}/alerts/topic-arn/{severity}), which requires a PlatformStack.chatops.ts:49

CloudWatchAlarmNotification ​

Defined in: message-templates.ts:30

Subset of the CloudWatch alarm state change notification that is rendered.

Properties ​

PropertyModifierTypeDefined in
AlarmArn?readonlystringmessage-templates.ts:35
AlarmDescription?readonlystring | nullmessage-templates.ts:32
AlarmNamereadonlystringmessage-templates.ts:31
AWSAccountId?readonlystringmessage-templates.ts:33
NewStateReason?readonlystringmessage-templates.ts:37
NewStateValuereadonlystringmessage-templates.ts:36
OldStateValue?readonlystringmessage-templates.ts:38
Region?readonlystringmessage-templates.ts:34
StateChangeTime?readonlystringmessage-templates.ts:39
Trigger?readonlyobjectmessage-templates.ts:40
Trigger.ComparisonOperator?readonlystringmessage-templates.ts:45
Trigger.Dimensions?readonlyreadonly object[]message-templates.ts:46
Trigger.MetricName?readonlystringmessage-templates.ts:41
Trigger.Namespace?readonlystringmessage-templates.ts:42
Trigger.Statistic?readonlystringmessage-templates.ts:43
Trigger.Threshold?readonlynumbermessage-templates.ts:44

DestinationConfig ​

Defined in: handlers/notify.ts:26

One destination as serialised into the DESTINATIONS environment variable.

Properties ​

PropertyModifierTypeDescriptionDefined in
channelLabel?readonlystring-handlers/notify.ts:31
kindreadonlyChatOpsKind-handlers/notify.ts:27
minimumSeverityreadonly"critical" | "high" | "medium" | "low"-handlers/notify.ts:30
webhookSecretArnreadonlystringSecrets Manager ARN of the secret holding the webhook URL.handlers/notify.ts:29

EventBridgeNotification ​

Defined in: message-templates.ts:60

Parsed EventBridge event (as delivered to SNS by a rule).

Properties ​

PropertyModifierTypeDefined in
account?readonlystringmessage-templates.ts:63
detailreadonlyunknownmessage-templates.ts:66
detailTypereadonlystringmessage-templates.ts:62
region?readonlystringmessage-templates.ts:64
sourcereadonlystringmessage-templates.ts:61
time?readonlystringmessage-templates.ts:65

FormatMessageInput ​

Defined in: message-templates.ts:70

Inputs used to normalise one SNS record.

Properties ​

PropertyModifierTypeDescriptionDefined in
attributes?readonlyReadonly<Record<string, string>>SNS message attributes flattened to name -> value.message-templates.ts:75
messagereadonlystring-message-templates.ts:71
subject?readonlystring-message-templates.ts:72
topicArn?readonlystring-message-templates.ts:73

PayloadOptions ​

Defined in: message-templates.ts:343

Properties ​

PropertyModifierTypeDescriptionDefined in
channelLabel?readonlystringFree-text label shown in the message (for example the channel or team).message-templates.ts:345

Type Aliases ​

AlertState ​

ts
type AlertState = "ALARM" | "OK" | "INSUFFICIENT_DATA" | "INFO";

Defined in: message-templates.ts:4

State of the thing that triggered a notification.


ChatOpsKind ​

ts
type ChatOpsKind = "slack" | "teams";

Defined in: handlers/notify.ts:23

Supported chat providers.

Variables ​

DEFAULT_WEBHOOK_SECRET_NAMES ​

ts
const DEFAULT_WEBHOOK_SECRET_NAMES: Readonly<Record<ChatOpsKind, string>>;

Defined in: chatops.ts:21


DESTINATIONS_ENV ​

ts
const DESTINATIONS_ENV: "DESTINATIONS" = "DESTINATIONS";

Defined in: handlers/notify.ts:35

Name of the environment variable carrying the JSON DestinationConfig[].

Functions ​

alarmConsoleUrl() ​

ts
function alarmConsoleUrl(region, alarmName): string;

Defined in: message-templates.ts:94

Deep link to a CloudWatch alarm in the console.

Parameters ​

ParameterType
regionstring
alarmNamestring

Returns ​

string


formatMessage() ​

ts
function formatMessage(input): AlertMessage;

Defined in: message-templates.ts:240

Normalise an SNS message (alarm, budget, EventBridge event or text) into an AlertMessage.

Parameters ​

ParameterType
inputFormatMessageInput

Returns ​

AlertMessage


meetsMinimumSeverity() ​

ts
function meetsMinimumSeverity(severity, minimum): boolean;

Defined in: message-templates.ts:87

True when severity is at least minimum.

Parameters ​

ParameterType
severity"critical" | "high" | "medium" | "low"
minimum"critical" | "high" | "medium" | "low"

Returns ​

boolean


parseAlarmMessage() ​

ts
function parseAlarmMessage(message): 
  | CloudWatchAlarmNotification
  | undefined;

Defined in: message-templates.ts:138

Parse a CloudWatch alarm state change notification; undefined when the message is something else.

Parameters ​

ParameterType
messagestring

Returns ​

| CloudWatchAlarmNotification | undefined


parseAlarmName() ​

ts
function parseAlarmName(alarmName, description?): object;

Defined in: message-templates.ts:200

Platform alarms are described as [severity] service: name; recover the service (and severity) from that. Falls back to the alarm name segments.

Parameters ​

ParameterType
alarmNamestring
description?string | null

Returns ​

object

NameTypeDefined in
service?stringmessage-templates.ts:203
severity?"critical" | "high" | "medium" | "low"message-templates.ts:203
shortName?stringmessage-templates.ts:203

parseBudgetMessage() ​

ts
function parseBudgetMessage(message, subject?): BudgetNotification | undefined;

Defined in: message-templates.ts:150

Parse an AWS Budgets notification; undefined when the message is not one.

Parameters ​

ParameterType
messagestring
subject?string

Returns ​

BudgetNotification | undefined


parseEventBridgeMessage() ​

ts
function parseEventBridgeMessage(message): EventBridgeNotification | undefined;

Defined in: message-templates.ts:178

Parse an EventBridge event; undefined when the message is not one.

Parameters ​

ParameterType
messagestring

Returns ​

EventBridgeNotification | undefined


severityFromTopicArn() ​

ts
function severityFromTopicArn(topicArn): "critical" | "high" | "medium" | "low" | undefined;

Defined in: message-templates.ts:102

Severity encoded in the platform alert topic name (...-alerts-critical).

Parameters ​

ParameterType
topicArnstring | undefined

Returns ​

"critical" | "high" | "medium" | "low" | undefined


severityRank() ​

ts
function severityRank(severity): number;

Defined in: message-templates.ts:84

Numeric rank of a severity (low = 0 ... critical = 3).

Parameters ​

ParameterType
severity"critical" | "high" | "medium" | "low"

Returns ​

number


slackPayload() ​

ts
function slackPayload(alert, options?): Record<string, unknown>;

Defined in: message-templates.ts:359

Slack Block Kit payload for an incoming webhook.

Parameters ​

ParameterType
alertAlertMessage
optionsPayloadOptions

Returns ​

Record<string, unknown>


teamsPayload() ​

ts
function teamsPayload(alert, options?): Record<string, unknown>;

Defined in: message-templates.ts:397

Microsoft Teams incoming webhook payload with an Adaptive Card (schema 1.4).

Parameters ​

ParameterType
alertAlertMessage
optionsPayloadOptions

Returns ​

Record<string, unknown>

Released under the MIT License.