Configure
Channels and routes live undernotifications: 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 optionalmin_severity(info,warningorcritical; defaultinfo). 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|denysendsapproval_decidedto 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
Awebhook channel POSTs JSON:
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.

