webpush

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package webpush sends browser push notifications (RFC 8030/8291) to every subscription this control plane's dashboard has registered, backing the "webpush" notification-channel kind in internal/alerting: an operator gets a deploy/alert notification even with no dashboard tab focused or open, something none of the other 17 channel kinds (all webhooks or email) can do on their own.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnsureVAPIDKeys

func EnsureVAPIDKeys(ctx context.Context, keys KeyStore) (publicKey, privateKey string, err error)

EnsureVAPIDKeys returns this control plane's VAPID keypair, generating and persisting one through keys the first time it's called. Call once at startup, before anything can register a subscription against the public half: regenerating the pair later would silently orphan every subscription already registered against the old one (the browser's applicationServerKey would no longer match what this control plane signs with).

Types

type KeyStore

type KeyStore interface {
	Exists(ctx context.Context, serviceName, envKey string) (bool, error)
	SetValue(ctx context.Context, serviceName, envKey, plaintext string) error
	Resolve(ctx context.Context, serviceName, envKey string) (string, error)
}

KeyStore is the narrow internal/secrets surface EnsureVAPIDKeys needs. *secrets.Manager satisfies it structurally, the same "narrow, consumer-defined interface" shape VaultSecrets (internal/api) already establishes.

type Sender

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

Sender sends one notification to every registered browser subscription. It satisfies alerting.PushSender structurally (that package takes a narrow Send(ctx, title, body) interface rather than importing this one, the same "consumer defines the interface it needs" shape email.Sender's own consumers already follow).

func NewSender

func NewSender(subs Subscriptions, publicKey, privateKey, subscriber string, client *http.Client, logger *slog.Logger) *Sender

NewSender builds a Sender. subscriber is the VAPID JWT "sub" claim a push service may contact if this control plane's server is sending too aggressively; an https:// URL or an email address, per RFC 8292.

func (*Sender) Send

func (s *Sender) Send(ctx context.Context, title, body string) error

Send pushes one notification to every registered subscription. A per-subscription failure never aborts the loop: one dead or revoked browser must not silence every other one. Returns an error only when no registered subscription exists at all, or every send attempt failed, mirroring email.Sender's own "nothing configured" failure shape that NewDeployDispatcher's doc comment already describes for every other channel kind.

type Subscriptions

type Subscriptions interface {
	ListPushSubscriptions(ctx context.Context) ([]store.PushSubscription, error)
	DeletePushSubscriptionByID(ctx context.Context, id string) error
}

Subscriptions is the store surface Sender needs: every registered subscription, and a way to prune one a push service has reported permanently gone. *store.DB satisfies this structurally.

Jump to

Keyboard shortcuts

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