Approvals
Where people approve 3AM's proposals, how requests escalate, and when two approvers are needed.
Every change 3AM makes is approved by a person, in the tool they already use. The request carries everything needed to decide: the confirmed cause, the evidence values, the exact change, the rehearsal's result, and whether it can be undone.
Channels
| Channel | How people answer | Assurance |
|---|---|---|
| Slack | React ✅ or ❌ to 3AM's message, or reply approve / reject in the thread | High |
| Symphony | Press Approve or Reject on 3AM's message (read from the bot's datafeed; nothing connects in) | High |
| PagerDuty | Add a note saying approve or reject on the approval incident (guide) | High |
| Phone (Twilio) | Answer the call, press 1 to approve or 2 to reject, optionally with a PIN | High |
| Reply approve or reject on the first line | Low: never used when two approvers are needed |
Each channel can list who may approve: a reaction, press or note from anyone else is ignored. The approver's identity (Slack user, Symphony e-mail, PagerDuty e-mail, phone number) is recorded in the audit log.
None of these needs an inbound connection to 3AM: 3AM reads the answers from the tools.
Escalation
The approval chain in the policy lists channels in order, with delays: for example Slack at once, PagerDuty after 5 minutes, a phone call after 15. 3AM asks the next channel only if no decision has arrived. The first valid decision from any reached channel counts, and the others are closed with a note.
Each channel is the name you gave the connector:
"approval_chain": [{"channel": "slack"}, {"channel": "pagerduty", "after_s": 300}, {"channel": "phone", "after_s": 900}]Raising a service's autonomy has its own chain and quorum:
"autonomy_change": {"quorum": 2, "chain": [{"channel": "slack"}]}Quorum
Some changes need two different people (the number is configurable):
| When | Default |
|---|---|
| Raising a service's autonomy (for example shadow → L1) | 2 approvers, high-assurance channels only |
Policy rules you set, for example {"match": {"risk": "high"}, "quorum": 2} | As configured |
| High-risk actions | 2 approvers |
The same person approving twice counts once. Two people may answer on the same channel or on different channels. Any single reject ends the request.
Expiry
A request that nobody answers expires (30 minutes by default; 60 for autonomy changes). Nothing changes, and the incident is escalated with the evidence.