Documentation
¶
Overview ¶
Package notify delivers completed investigations to chat (Slack, Matrix).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Format ¶
func Format(inv providers.Investigation) string
Format renders an Investigation as a concise markdown-ish message used by all notifiers.
Invariant: every literal this function emits (labels, separators, bullets) avoids the three mrkdwn-meta chars & < >. The Slack fallback is escapeMrkdwn(Format(inv)) — only untrusted content (evidence, summaries) may carry those chars, so escaping leaves the scaffolding intact. Use · • and *bold*; TestFormatScaffoldingHasNoMrkdwnMeta guards it.
func FormatProgress ¶ added in v0.3.0
func FormatProgress(up providers.ProgressUpdate) string
FormatProgress renders an interim progress update as a concise plain-text status line, shared by notifiers (Slack fallback; Matrix/webhook later). The fields are untrusted (title + model interim text), so a mrkdwn-parsing notifier escapes the composed output before sending.
func Register ¶ added in v0.2.0
func Register(d Descriptor)
Register adds a notifier descriptor to the registry. Panics on duplicate names.
Types ¶
type Descriptor ¶ added in v0.2.0
type Descriptor struct {
Name string
Build func(Deps) (providers.Notifier, error) // returns nil when unconfigured (disabled)
}
Descriptor describes a self-registering notifier.
type FeedbackSink ¶ added in v0.8.0
FeedbackSink records a human 👍/👎 rating on a delivered investigation (implemented by *outcome.Ledger — the same method the Slack path records through, so dedup, trust weighting and the recurrence-cooldown re-arm are shared by construction).
type Matrix ¶
type Matrix struct {
// contains filtered or unexported fields
}
Matrix delivers via the Matrix client-server send API.
func NewMatrix ¶
NewMatrix builds a Matrix notifier. homeserver is the base URL (e.g. https://matrix.org); roomID is like "!abc:hs"; token is an access token.
The txn counter is seeded from the wall clock (UnixNano) rather than 0 so that transaction ids keep increasing across process restarts. Homeservers dedupe by (access_token, txnId); a fresh process starting back at "runlore-1" could otherwise collide with a pre-restart id and have its message silently dropped. Caveat: a backwards wall-clock jump across a restart could still collide — an acceptable residual given the dedup window is minutes and the prior behaviour offered zero protection.
func (*Matrix) Deliver ¶
Deliver sends the formatted investigation as an m.notice message. It carries both a plaintext body (the fallback Matrix renders literally) and a rich formatted_body (org.matrix.custom.html) so the message's mrkdwn renders as bold/links/code instead of leaking raw *asterisks* to Matrix clients.
type MatrixFeedback ¶ added in v0.8.0
type MatrixFeedback struct {
// contains filtered or unexported fields
}
MatrixFeedback is the opt-in reaction listener (notify.matrix.feedback_reactions): it long-polls the homeserver's /sync for m.reaction events in the configured room and records 👍/👎 on RunLore's own investigation messages into the outcome ledger.
Unlike the Slack feedback path, NOTHING is exposed: /sync is an outbound HTTPS long-poll authenticated by the notifier's access token — no inbound endpoint, no signing secret, no NetworkPolicy change. The trade is a long-lived poll loop, which runs leader-only (started in startWork, cancelled with the leadership context) so an HA deployment records each reaction once.
The first /sync response is a position handshake only: historical reactions are deliberately skipped, so feedback counts from startup onward — replaying a room's history through the ledger on every restart would re-stamp old votes with fresh timestamps.
func NewMatrixFeedback ¶ added in v0.8.0
func NewMatrixFeedback(homeserver, roomID, token string, sink FeedbackSink, log *slog.Logger) *MatrixFeedback
NewMatrixFeedback builds the reaction listener. homeserver/roomID/token are the notifier's own settings; sink is where ratings land (the outcome ledger).
func (*MatrixFeedback) Run ¶ added in v0.8.0
func (f *MatrixFeedback) Run(ctx context.Context)
Run long-polls /sync until ctx is cancelled (leadership loss / shutdown). Errors are logged and retried after a fixed backoff — a flaky homeserver must never crash the agent; at worst feedback pauses.
type Multi ¶
type Multi struct {
// contains filtered or unexported fields
}
Multi delivers to several notifiers, best-effort: a failing notifier is logged, not propagated, so one bad sink doesn't block the others.
func BuildEnabled ¶ added in v0.2.0
BuildEnabled builds every registered notifier whose Build returns non-nil, in deterministic (name-sorted) order, and wraps them in a Multi.
func (*Multi) Deliver ¶
Deliver fans out to every notifier (best-effort: one bad sink never blocks the others), logs each failure, and returns the joined errors so the caller can tell delivery was incomplete. Returns nil when all sinks succeed.
func (*Multi) DeliverProgress ¶ added in v0.3.0
DeliverProgress fans an interim progress ping out to every wrapped notifier that implements ProgressNotifier (the type-assert capability check), skipping those that don't (Matrix/webhook may no-op for now). It is best-effort by contract: a failing sink is logged and swallowed, never propagated — a progress ping must never fail an investigation. Returns nil always.
type Slack ¶
type Slack struct {
// FeedbackButtons (opt-in, notify.slack.feedback_buttons) appends 👍/👎 buttons
// so the on-call can rate the diagnosis; clicks land in the outcome ledger via
// the exposed /slack/interactions endpoint.
FeedbackButtons bool
// contains filtered or unexported fields
}
Slack delivers via a Slack incoming webhook.
func (*Slack) Deliver ¶
Deliver posts the formatted investigation to the webhook. When an action carries an ApprovalID, it renders interactive Approve/Reject buttons (Block Kit).
func (*Slack) DeliverProgress ¶ added in v0.3.0
DeliverProgress posts an interim progress ping to the webhook (ProgressNotifier).
type SlackBot ¶
type SlackBot struct {
// FeedbackButtons — see Slack.FeedbackButtons; on the bot path the buttons sit
// on the channel summary message, never on the detail thread reply.
FeedbackButtons bool
// contains filtered or unexported fields
}
SlackBot delivers via the Slack Web API (chat.postMessage) using a bot token, for workspaces that provision a bot app instead of an incoming webhook. Unlike a webhook, chat.postMessage targets an explicit channel and returns HTTP 200 with {"ok":false,"error":...} on logical failures (e.g. not_in_channel).
func NewSlackBot ¶
NewSlackBot builds a bot-token Slack notifier posting to channel (ID or name).
func (*SlackBot) Deliver ¶
Deliver posts the compact summary to the channel, then the full analysis as a thread reply so the channel stays a scannable triage feed. The summary IS the notification; the detail reply is secondary, so a failed thread post returns a wrapped error that records the summary already landed — Multi logs it without implying the alert went undelivered. Nothing is threaded when the summary post yields no ts (empty-body path) or the investigation has no detail beyond it.
func (*SlackBot) DeliverProgress ¶ added in v0.3.0
DeliverProgress posts an interim progress ping to the channel (ProgressNotifier).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package webhook is a generic outgoing-webhook notifier: it POSTs each investigation's findings as JSON to an operator-configured URL.
|
Package webhook is a generic outgoing-webhook notifier: it POSTs each investigation's findings as JSON to an operator-configured URL. |