sink

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ParamChatID     = "chat_id"
	ParamRoutingKey = "routing_key"
	ParamTopic      = "topic"
	ParamPriority   = "priority"
	ParamUserKey    = "user_key"
	ParamAppToken   = "app_token"
)

Well-known param keys accepted via --webhook-param key=value.

Variables

View Source
var ErrWebhookAllRetriesFailed = errors.New("webhook: all retries failed")

Sentinel for tests / callers that want to distinguish.

Functions

func ResolveFormatterParams

func ResolveFormatterParams(o FormatterOptions) map[string]string

ResolveFormatterParams returns a flat key->string map covering every platform-specific configuration source: typed FormatterOptions fields plus the user-supplied Params. The Param* constants document the recognized keys. Values are stringified so callers don't need to care about types.

func SignHMAC

func SignHMAC(body []byte, secret, headerName, prefix string) (string, string)

SignHMAC adds an HMAC-SHA256 signature header to the body. Used for webhooks that verify request authenticity (e.g. custom intake endpoints). The signature is hex-encoded and prefixed with the given algorithm label.

Types

type FileSink

type FileSink struct {
	// contains filtered or unexported fields
}

FileSink writes one JSON file per result into a directory. Filenames are derived from a hash of (provider, key) plus a millisecond timestamp so that re-runs of the same key are idempotent (overwrite the same path).

func NewFileSink

func NewFileSink(dir string, filter Filter) (*FileSink, error)

NewFileSink prepares a directory for output, creating it if missing.

func (*FileSink) Close

func (s *FileSink) Close() error

func (*FileSink) Count

func (s *FileSink) Count() int64

Count returns the number of files emitted since construction.

func (*FileSink) Emit

type Filter

type Filter int

Filter selects which events are emitted to a sink.

const (
	FilterAll     Filter = iota // all results
	FilterValid                 // only successful validations
	FilterInvalid               // only unsuccessful validations (including rate-limited / skipped)
)

type Formatter

type Formatter interface {
	Platform() Platform
	Format(r *models.ValidationResult) (body []byte, headers map[string]string, err error)
}

Formatter produces the HTTP body and any platform-specific headers for one validation result. It returns the body bytes and any extra headers that should be merged with the user-supplied ones (Content-Type is added by the HTTPSink if not set by the formatter).

type FormatterOptions

type FormatterOptions struct {
	TelegramChatID      string
	PagerDutyRoutingKey string
	NtfyTopic           string
	GotifyPriority      int
	PushoverUserKey     string
	PushoverAppToken    string
	// Params is a free-form key/value map. Both the typed fields above and
	// any well-known keys here are merged into one resolved map by
	// ResolveFormatterParams.
	Params map[string]string
}

FormatterOptions carries platform-specific configuration. All fields are optional except where the formatter requires them.

Typed fields (TelegramChatID, PagerDutyRoutingKey, ...) are kept for backward compatibility with code that constructed FormatterOptions directly. New code should populate Params via the CLI helper --webhook-param key=value. The two views are merged by ResolveFormatterParams.

type HTTPSink

type HTTPSink struct {
	// contains filtered or unexported fields
}

HTTPSink POSTs each result to a single URL or a per-provider template URL. The body is produced by a Formatter; raw JSON is the default. Every request includes the formatter's headers plus any user-supplied headers and an optional HMAC signature. Transient failures are retried with exponential backoff.

func NewHTTPSink

func NewHTTPSink(rawURL string, filter Filter, timeoutSecs int) (*HTTPSink, error)

NewHTTPSink builds an HTTP sink with raw-JSON formatting and a 10-second per-request timeout. timeoutSecs<1 falls back to 10s. For platform-specific formatting use NewHTTPSinkWithFormatter.

func NewHTTPSinkWithFormatter

func NewHTTPSinkWithFormatter(rawURL string, filter Filter, platform Platform, fmtOpts FormatterOptions, sinkOpts HTTPSinkOptions) (*HTTPSink, error)

NewHTTPSinkWithFormatter builds an HTTP sink with the given platform formatter and options. timeoutSecs in opts.Timeout is overridden by a non-zero Timeout field.

func (*HTTPSink) Close

func (s *HTTPSink) Close() error

func (*HTTPSink) Emit

Emit POSTs the result, retrying transient failures.

func (*HTTPSink) Platform

func (s *HTTPSink) Platform() string

Platform returns the formatter platform name.

func (*HTTPSink) Stats

func (s *HTTPSink) Stats() (sent int64, failed int64)

Stats returns the count of attempted and failed emits since construction.

type HTTPSinkOptions

type HTTPSinkOptions struct {
	// Headers applied to every request in addition to whatever the
	// formatter sets. User-supplied headers win on conflict.
	Headers map[string]string
	// Retries is the number of additional attempts on transient HTTP
	// failures (network error, 5xx, 429). Total attempts = Retries + 1.
	// Zero means a single attempt.
	Retries int
	// RetryBackoff is the initial wait between retries. The wait doubles
	// each attempt (exponential) up to RetryMaxBackoff.
	RetryBackoff time.Duration
	// RetryMaxBackoff caps the per-attempt wait.
	RetryMaxBackoff time.Duration
	// SignatureSecret enables HMAC-SHA256 signing of the request body.
	// When set, SignatureHeader (default "X-Kunji-Signature") is set to
	// "<prefix><hex-digest>". Prefix defaults to empty.
	SignatureSecret string
	SignatureHeader string
	SignaturePrefix string
	// Per-request timeout applied to the underlying HTTP client.
	Timeout time.Duration
}

HTTPSinkOptions configures an HTTPSink. All fields are optional; zero values yield the legacy behavior (raw JSON body, no extra headers, no retries, no signature).

type Nop

type Nop struct{}

Nop is a no-op sink used as a placeholder when no --webhook/--sink is set.

func (Nop) Close

func (Nop) Close() error

func (Nop) Emit

type Platform

type Platform string

Platform identifies a built-in webhook payload formatter. The generic "raw" platform posts the ValidationResult unchanged. Other platforms translate the result into the JSON body shape their endpoint expects.

const (
	PlatformRaw       Platform = "raw"       // raw ValidationResult JSON
	PlatformSlack     Platform = "slack"     // Slack-compatible {text, attachments}
	PlatformDiscord   Platform = "discord"   // Discord-compatible {content, embeds}
	PlatformTeams     Platform = "teams"     // Microsoft Teams MessageCard
	PlatformTelegram  Platform = "telegram"  // Telegram Bot API sendMessage
	PlatformPagerDuty Platform = "pagerduty" // PagerDuty Events API v2
	PlatformNtfy      Platform = "ntfy"      // ntfy.sh plain body + Topic header
	PlatformGotify    Platform = "gotify"    // Gotify {message, title}
	PlatformPushover  Platform = "pushover"  // Pushover form-encoded body
)

func ParsePlatform

func ParsePlatform(s string) (Platform, error)

ParsePlatform validates a string against the supported platforms.

type Sink

type Sink interface {
	// Emit sends one validation result. Implementations must be safe for
	// concurrent use by many worker goroutines.
	Emit(ctx context.Context, r *models.ValidationResult) error
	// Close flushes any buffered state and releases resources.
	Close() error
}

Sink is the contract every result sink must satisfy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL