Skip to main content
Reversi can push events to the places your team already watches. A notification never changes what Reversi decided: a channel that is down, slow or misconfigured is logged as a warning and the call, approval or rollback carries on.

Configure

Channels and routes live under notifications: in reversi.config.yaml. ${NAME} is replaced from the environment, so secrets stay out of the file (a missing variable is a config error).
reversi.config.yaml
  • Routes pick channels by event name ("*" for all) and an optional min_severity (info, warning or critical; default info). A message goes to every channel named by any matching route, once.
  • No routes: every event goes to every channel.
  • A route naming a channel that does not exist, a duplicate channel name, or a missing required field fails when the config loads, with the field named.
  • Notifications are sent by the process that sees the event: the server, gateway, console, or the CLI when it decides an approval (reversi approvals approve|deny sends approval_decided to the channels in the project file; see approvals).

Channels

Email speaks SMTP directly with no dependency: secure: true for implicit TLS (port 465), otherwise STARTTLS is used when the server offers it (starttls: false turns that off), user and pass authenticate with AUTH PLAIN, and the certificate is verified unless verify_tls: false. A permanent rejection (a 5xx reply) is not retried. Delivery. Every channel sends through the egress guard, with a 10 second timeout and up to three attempts (waits of 0.2 s and 0.4 s) on network errors, 429 and 5xx. A 4xx fails at once: it means a wrong URL or key. Error messages have key=, token= and secret= values blanked.

Events

Messages carry names and ids (tool, run, actor, argument names), never argument values.

The signed webhook

A webhook channel POSTs JSON:
with headers x-reversi-event (the event name) and, when secret is set, x-reversi-signature: sha256=<hex>, the HMAC-SHA-256 of the raw request body under the secret. Compute it over the bytes exactly as received, before parsing JSON, and compare in constant time.
verify_webhook_signature returns False for a missing header, a missing sha256= prefix or any change to the body. It is also ReversiClient.verify_webhook_signature. Anchor webhooks use the same header and scheme.

Test it

doctor checks every channel URL against the egress rules and then sends a test message through all channels. Admins can also press Send a test notification under Settings in the console, which lists the channels that were reached and the ones that failed.

The older approval webhook

REVERSI_APPROVAL_WEBHOOK (or approval.webhook) is a single URL that gets each new approval request with a text field. It keeps working beside channels. Prefer channels: they add retries, routing, signing, decisions and the egress guard.

Not verified here

The Slack, Teams, PagerDuty, Opsgenie and SMTP payloads are covered by this repository’s tests against local fakes. They have not been exercised against the real services.