Help us shape the future of Go! Take the 2026 Go Developer Survey

webhooks

package
v0.3.5 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package webhooks is the one place a Workspace's Webhook endpoints are created, updated, read, listed and deleted. It owns the URL rule, the signing secret (generated server-side, stored sealed, returned decrypted) and the Enterprise rule that selecting audit.entry needs a license (ADR 0022). The site and external handlers only map DTOs and the sentinels below to a 422. The endpoint is an audited entity, so the scoped client records its changes (a regenerated secret included); the one thing the module records itself is a test delivery, which writes no row.

Order: a catalogue, ascending by id (see package pagination).

Index

Constants

View Source
const (
	DisableFailures = 20
	DisableWindow   = 2 * time.Hour
)

An endpoint disables itself (ADR 0039) on a 410, or when a run of consecutive failures has both lasted the window and reached the count. The window is what makes the count safe: a restart in the middle of a burst piles up failures in minutes and never retires a healthy endpoint.

View Source
const TestSendTimeout = 15 * time.Second

TestSendTimeout bounds a test delivery, the same budget as a real one.

Variables

View Source
var (
	// ErrInvalidURL: the URL is not an absolute http(s) URL (a 422 on `url`).
	ErrInvalidURL = validation.Refuse("webhooks: url must be an absolute http or https URL", "errors.webhook_url_invalid")
	// ErrAuditNeedsLicense: audit.entry was selected without an Enterprise license
	// (a 422 on `eventTypes`).
	ErrAuditNeedsLicense = validation.Refuse("webhooks: audit.entry needs an Enterprise license", "errors.webhook_audit_needs_license")
	// ErrNotFound: no such endpoint in this Workspace.
	ErrNotFound = validation.Refuse("webhooks: webhook not found", "errors.webhook_not_found")
)

Domain errors. Callers match with errors.Is.

View Source
var ErrInvalidEventType = validation.Refuse("webhooks: the event type must be 1 to 100 characters", "errors.webhook_event_type_invalid")

ErrInvalidEventType means the event type to send a sample of is blank or too long.

Functions

This section is empty.

Types

type CreateInput

type CreateInput struct {
	URL        string
	EventTypes []string
	Enabled    *bool
}

CreateInput is a new endpoint. A nil Enabled keeps the default (enabled).

type Endpoint

type Endpoint struct {
	*ent.WebhookEndpoint

	Secret string
}

Endpoint is a Webhook endpoint with its signing secret decrypted.

type Licensing

type Licensing interface{ Licensed() bool }

Licensing reports whether the Enterprise license is active. A nil Licensing means unlicensed.

type Module

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

Module is the webhooks module. Every call receives the Workspace-scoped client.

func New

func New(bus *events.Bus, cipher *secrets.Cipher, lic Licensing, client webhook.Doer, notify ownernotice.Notify) *Module

New builds the module. lic may be nil (unlicensed). client is the one hardened outbound client, used by TestSend. notify mails the Owners when an endpoint disables itself; nil sends nothing.

func (*Module) Create

func (m *Module) Create(ctx context.Context, s *ent.Scoped, in CreateInput) (Endpoint, error)

Create validates the URL and the event filter, generates the signing secret and stores it sealed.

func (*Module) Delete

func (m *Module) Delete(ctx context.Context, s *ent.Scoped, id int64) error

Delete removes the endpoint. An unknown id is ErrNotFound.

func (*Module) Get

func (m *Module) Get(ctx context.Context, s *ent.Scoped, id int64) (Endpoint, error)

Get returns one endpoint. An unknown id is ErrNotFound.

func (*Module) List

List returns one page of the Workspace's endpoints, ascending by id.

func (*Module) RecordDelivery

func (m *Module) RecordDelivery(ctx context.Context, s *ent.Scoped, e *ent.WebhookEndpoint, sendErr error, now time.Time) error

RecordDelivery keeps the endpoint's failure state after one delivery attempt (ADR 0039): a failed delivery extends the run of failures with its closed error kind, a 2xx clears it, and a 429 (the receiver is alive and asks us to slow down) is neither and leaves the counters alone. A failure that meets the disable rule turns the endpoint off. e is the row as the delivery loaded it; s is the endpoint's Workspace scope. The counter writes carry no actor, so they are not audited.

func (*Module) RegenerateSecret

func (m *Module) RegenerateSecret(ctx context.Context, s *ent.Scoped, id int64) (Endpoint, error)

RegenerateSecret replaces the signing secret at once: the old one stops verifying with the next delivery. The row update is audited by the scoped client (secret_encrypted is a sensitive field, so the entry only says it changed).

func (*Module) TestSend

func (m *Module) TestSend(ctx context.Context, s *ent.Scoped, id int64, eventType string) (TestResult, error)

TestSend delivers a sample event of the given type to the endpoint, signed as a real delivery, and returns what the receiver answered. It is synchronous, works on a disabled endpoint and never touches the failure state. It writes no row, so it is recorded as an explicit Audit entry (webhook_endpoint.test).

func (*Module) Update

func (m *Module) Update(ctx context.Context, s *ent.Scoped, id int64, in UpdateInput) (Endpoint, error)

Update applies the set fields. An unknown id is ErrNotFound.

type TestResult

type TestResult struct {
	Delivered bool
	Status    int
	Kind      webhook.ErrorKind
}

TestResult is the outcome of one test delivery: Delivered with the receiver's Status on a 2xx, otherwise the closed error Kind (and the Status of an http_status failure).

type UpdateInput

type UpdateInput struct {
	URL        *string
	EventTypes []string
	Enabled    *bool
}

UpdateInput changes only what is set: a nil field is left alone.

Jump to

Keyboard shortcuts

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