Built, not hosted The Slack code is built and tested with a fake Slack client. It has not been installed in a live workspace yet, and there is no public Spendsaw app in the Slack directory. In the hosted service the weekly digest is deployed and has never posted, because it skips every tenant until that app exists. Approve, snooze and spike alerts run only in the self-hosted application, where you create your own Slack app.
The weekly digest
- One summary line: how many new cuts were found since the last digest, in which account, and about how much they are worth each month. Up to three are named, followed by the open total.
- Up to three cuts, largest first. Each shows the resource id, region, account, monthly amount and its cost source.
- A footer with verified savings, which is only ever an amount the bill has confirmed, and how many cuts are still waiting for a full billing month.
A cut gets Approve and Snooze 7 days buttons only when its plan is executable and its account has opted in to remediation. The message states the risk tier, shows the exact commands approving will run, and ends with the question the button answers. Everything else is shown as a recommendation with the reason.
An action with no backup shows a confirmation dialog before it is approved.
Who can approve
- Only Slack user ids listed in
SLACK_APPROVERScan approve or snooze. An empty list means nobody can. - The approver is recorded as
slack:<team>:<user>on the action record. - Approving from Slack runs the same approval flow and execution checks as the API. The message is updated with the result.
Request verification
Slack's interactivity requests go to POST /slack/interactions. That endpoint sits outside the application's own authentication, because Slack signs requests instead of sending credentials. Each request's signature is verified on the raw body, and a timestamp more than 300 seconds off is rejected so a captured request cannot be replayed. From the payload Spendsaw takes only the workspace id, the user id and one action id; the tenant, the approver list, the finding and the plan are all read again on the server.
Spike alerts
A daily check compares one day's spend with the average of the 14 days before it. Because Cost Explorer keeps revising the most recent day, the day checked is the day before yesterday.
- Alerts when the day is more than
SPIKE_THRESHOLD_PCTabove the average (default 30). - Skipped when the average is below
SPIKE_MIN_BASELINE_USD(default 5) or fewer than 7 baseline days exist. - Names the three services with the largest increase. Sent once per spike day.
Set up (self-hosted)
SLACK_SIGNING_SECRET=
SLACK_BOT_TOKEN=
SLACK_TEAM_ID=
SLACK_CHANNEL=
SLACK_APPROVERS=U0123ABCD,U0456EFGH
SPIKE_THRESHOLD_PCT=30
SPIKE_MIN_BASELINE_USD=5
Point your Slack app's interactivity request URL at /slack/interactions on your deployment. Then schedule the two jobs:
python -m delivery.slack.run_digest --scan # weekly
python -m delivery.slack.run_spikes # daily
--scan scans the accounts first; without it the digest uses the stored findings.
Sources: delivery/slack/digest.py, delivery/slack/interactions.py, delivery/slack/routes.py, delivery/slack/spikes.py, delivery/slack/config.py, .env.example.