THE FULL VERSION OF THIS PAGE SHIPS IN THE REPOSITORY AS DOCS/NOTIFICATIONS.MD. THE PROVIDER LIST BELOW IS GENERATED FROM THE REGISTRY THAT RENDERS THE EDITOR, AND CI FAILS IF THEY DISAGREE.

Notifications

One sentence first, because everything else on this page exists to make it true: when Vigil decides to alert you, that decision is durable, and the message is delivered at least once or recorded as failed where you can see it.

Ten channel providers, one pipeline

A channel is a provider, its settings, its encrypted credentials and the event classes it subscribes to. Every provider rides the same transactional outbox: durable enqueue in the transaction that decided to alert, leases, retries with jittered backoff, idempotency keys derived from the cause, and a per-channel rate limit. No provider has a queue of its own.

Provider Transport Credential you supply
SlackIncoming webhookthe webhook URL
DiscordChannel webhookthe webhook URL
Microsoft TeamsWorkflows webhook, Adaptive Card payloadthe workflow URL
TelegramBot API sendMessagebot token and chat id
Google ChatSpace incoming webhookthe webhook URL
GotifyPOST /message with X-Gotify-Keyapplication token
ntfyJSON publish, ntfy.sh or your servertoken or user + password, optional
WebhookSigned JSON POST, X-Vigil-SignatureHMAC signing secret
SMTPOwn client: STARTTLS/TLS, AUTH PLAINyour mail server, password optional
ResendPOST /emails with Idempotency-KeyAPI key

Three of those rows are contracts worth reading twice. Teams is the Power Automate Workflows webhook: Microsoft disabled the old Office 365 connector URLs in May 2026, and Vigil never speaks the retired MessageCard format. Every credential is yours: there is no Vigil-funded relay, account or hosted service behind any provider. And Gotify, ntfy and the signed webhook may point at servers on your own network; cloud metadata and link-local space are refused wherever a URL points or resolves, and redirects are never followed.

Event classes

A channel subscribes to classes, and every event belongs to exactly one, so one logical event cannot reach the same channel twice: monitor down/up, incident lifecycle, certificate and domain expiry (a carve-out of down/up by monitor kind - the certificate channel hears about certificates, the 3am pager does not), and in the commercial edition recovery results and remote-probe quorum. Recovery notifies outcomes only: success once verified, failure once the chain is exhausted. Quorum events fire on the transition, not once per round.

Credentials and errors

Channel secrets are stored encrypted (AES-256-GCM) and are never sent back to a browser; the editor only shows which secret fields are set. Delivery errors are scrubbed of secret values and URL query strings before they are stored, and the delivery history shows provider, event, destination, attempts, final status and that redacted error. SMTP refuses to authenticate without TLS and certificate verification has no off switch.

Retries, honestly

Delivery is at-least-once: six attempts, exponential jittered backoff, a provider's Retry-After honored, permanent rejections (a 404, a revoked credential) marked failed immediately instead of hiding behind a queue. The unavoidable window is a crash after a provider accepted a message but before the row records it; where the provider offers idempotency (Resend), the retry collapses on their side. The wording the product uses everywhere: at most one message per logical notification where the provider cooperates, at least one everywhere.

The full engineering document, including the outbox schema and the exact guarantee wording, ships in the repository as docs/NOTIFICATIONS.md.