driver

package
v1.10.1 Latest Latest
Warning

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

Go to latest
Published: Nov 4, 2026 License: MIT Imports: 13 Imported by: 1

Documentation

Overview

Package driver defines the notification driver interface and registry.

Each notification provider (SMTP, Twilio, FCM, etc.) implements the Driver interface. The Registry manages available drivers by name.

Index

Constants

View Source
const (
	PushKindShow     = "show"
	PushKindWithdraw = "withdraw"
)

Push kinds: show a notification, or withdraw one shown earlier.

Variables

View Source
var ErrAddressGone = errors.New("herald: address gone")

ErrAddressGone means the provider says the recipient address no longer exists, so the caller should stop sending to it.

View Source
var ErrDriverNotFound = errors.New("herald: driver not found")

ErrDriverNotFound is returned when a driver is not registered.

Functions

func DataPayload

func DataPayload(data map[string]string) map[string]string

DataPayload returns the provider settings meant for the recipient's payload: keys starting with "data.", with the prefix removed. Nothing else in the merged credentials-and-settings map (API keys, tokens, from addresses) is ever forwarded. It returns nil when there are none.

func HTTPClient

func HTTPClient(timeout time.Duration, ep Endpoint) *http.Client

HTTPClient returns the *http.Client a driver uses to call its vendor. It behaves like &http.Client{Timeout: timeout}: the same default transport, connection pool, HTTP/2 support and redirect policy, and the error a failed request returns is the transport's own, unwrapped.

On top of that, every request it sends is an OpenTelemetry client span under the span in the request's context. The span is named after the method and ep.URLTemplate ("POST /v3/mail/send", or "POST" with no template) and carries http.request.method, server.address and server.port (unless ep.HideHost), url.template, herald.driver and http.response.status_code. It never carries the URL, its path or its query, or any header. A 4xx or 5xx response, or a transport failure, marks it failed with error.type set to the status code or to timeout, canceled, dns, tls, connection or other; the error's message never reaches it.

The request goes out with exactly the headers the driver set: no traceparent, tracestate or baggage. Vendors are third parties, and the inbound request's baggage is not theirs to see.

Types

type DeliveryResult

type DeliveryResult struct {
	ProviderMessageID string         `json:"provider_message_id,omitempty"`
	Status            message.Status `json:"status"`
}

DeliveryResult contains the outcome of a delivery attempt.

type Describer

type Describer interface {
	Fields() []Field
}

Describer is optional. A driver that implements it gets a form built from its fields; one that doesn't gets free-form key/value editing.

type Driver

type Driver interface {
	// Name returns the driver identifier (e.g., "smtp", "twilio", "fcm").
	Name() string

	// Channel returns which notification channel this driver handles.
	Channel() string

	// Send delivers a message and returns a delivery result.
	Send(ctx context.Context, msg *OutboundMessage) (*DeliveryResult, error)

	// Validate checks if the provided credentials and settings are valid.
	Validate(credentials, settings map[string]string) error
}

Driver is the interface that notification provider drivers must implement.

type Endpoint

type Endpoint struct {
	// Driver is the driver's name, recorded as herald.driver.
	Driver string

	// URLTemplate is the request path with its variable parts named, such
	// as "/2010-04-01/Accounts/{account_sid}/Messages.json". It is recorded
	// as url.template and names the span. Leave it empty when the driver
	// can't know the path, such as a webhook URL the user supplies whole.
	URLTemplate string

	// HideHost keeps server.address and server.port off the span. Set it
	// when the user supplies the whole URL, since the host is then theirs
	// (a customer's endpoint) rather than the vendor's.
	HideHost bool
}

Endpoint describes a vendor call for the client span HTTPClient records. None of it is read from the request URL, which is why a span can't leak a token, a device token or an account ID that sits in the URL.

type Field

type Field struct {
	Key       string    `json:"key"`
	Label     string    `json:"label"`
	Help      string    `json:"help,omitempty"`
	Required  bool      `json:"required"`
	Secret    bool      `json:"secret"`
	Placement Placement `json:"placement"`
}

Field describes one value a driver reads from a provider.

func SenderFields

func SenderFields() []Field

SenderFields are the settings Herald reads itself for email: the from address and display name, used when no scoped config supplies them.

type OutboundMessage

type OutboundMessage struct {
	To       string            `json:"to"`
	From     string            `json:"from,omitempty"`
	FromName string            `json:"from_name,omitempty"`
	Subject  string            `json:"subject,omitempty"`
	HTML     string            `json:"html,omitempty"`
	Text     string            `json:"text,omitempty"`
	Title    string            `json:"title,omitempty"`
	Data     map[string]string `json:"data,omitempty"`

	// Push holds per-message push options. Nil means the v1.8 behaviour.
	Push *PushOptions `json:"-"`
	// PublicKey is the recipient device's X25519 public key. Push fan-out only.
	PublicKey []byte `json:"-"`
}

OutboundMessage is the normalized message format passed to drivers.

type Placement

type Placement string

Placement says which provider map a field lives in. Credentials are encrypted at rest when a key is configured and never echoed back; settings are plain configuration.

const (
	PlacementCredential Placement = "credential"
	PlacementSetting    Placement = "setting"
)

Placements.

type PushOptions

type PushOptions struct {
	// Urgency is the delivery priority. Empty means UrgencyActive.
	Urgency Urgency
	// Kind is PushKindShow or PushKindWithdraw. Empty means PushKindShow.
	Kind string
	// CollapseID lets a later push replace an earlier one.
	CollapseID string
	// TTL is how long the provider may hold the push. Zero leaves it to the provider.
	TTL time.Duration
	// ThreadID groups notifications on the device.
	ThreadID string
	// Category names the action set the device shows with the notification.
	Category string
	// Data is extra payload. It wins over provider-level data settings.
	Data map[string]string
	// DataOnly sends no visible notification block.
	DataOnly bool
	// MutableContent lets a device extension rewrite the notification.
	MutableContent bool
	// ContentAvailable wakes the app for a background update.
	ContentAvailable bool
}

PushOptions are the per-message push settings a driver honours. A nil *PushOptions means the v1.8 behaviour.

func (*PushOptions) EffectiveKind

func (o *PushOptions) EffectiveKind() string

EffectiveKind returns the kind, defaulting to PushKindShow. It is safe on a nil receiver.

func (*PushOptions) EffectiveUrgency

func (o *PushOptions) EffectiveUrgency() Urgency

EffectiveUrgency returns the urgency, defaulting to UrgencyActive. It is safe on a nil receiver.

type Registry

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

Registry holds all available notification drivers indexed by name.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a new empty driver registry.

func (*Registry) Describe

func (r *Registry) Describe(name string) ([]Field, bool)

Describe returns a registered driver's fields. The bool is false for an unknown driver and for one that doesn't implement Describer.

func (*Registry) Get

func (r *Registry) Get(name string) (Driver, error)

Get returns a driver by name.

func (*Registry) ListByChannel

func (r *Registry) ListByChannel(ch string) []Driver

ListByChannel returns all drivers that handle the given channel.

func (*Registry) Names

func (r *Registry) Names() []string

Names returns the names of all registered drivers.

func (*Registry) Register

func (r *Registry) Register(d Driver)

Register adds a driver to the registry.

type Urgency

type Urgency string

Urgency says how hard a push should try to reach the user.

const (
	UrgencyPassive       Urgency = "passive"
	UrgencyActive        Urgency = "active"
	UrgencyTimeSensitive Urgency = "time_sensitive"
	UrgencyCritical      Urgency = "critical"
)

Push urgency levels, from quietest to loudest.

func (Urgency) Valid

func (u Urgency) Valid() bool

Valid reports whether u is one of the four urgency levels. The empty string is not valid.

Directories

Path Synopsis
Package drivertest provides shared HTTP mock-server helpers for driver unit tests.
Package drivertest provides shared HTTP mock-server helpers for driver unit tests.
Package email provides email notification drivers.
Package email provides email notification drivers.
Package inapp provides the in-app notification driver.
Package inapp provides the in-app notification driver.
Package push provides push notification drivers.
Package push provides push notification drivers.
Package sms provides SMS notification drivers.
Package sms provides SMS notification drivers.

Jump to

Keyboard shortcuts

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