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
- Variables
- type CreateInput
- type Endpoint
- type Licensing
- type Module
- func (m *Module) Create(ctx context.Context, s *ent.Scoped, in CreateInput) (Endpoint, error)
- func (m *Module) Delete(ctx context.Context, s *ent.Scoped, id int64) error
- func (m *Module) Get(ctx context.Context, s *ent.Scoped, id int64) (Endpoint, error)
- func (m *Module) List(ctx context.Context, s *ent.Scoped, p pagination.Params) (pagination.Page[Endpoint], error)
- func (m *Module) RecordDelivery(ctx context.Context, s *ent.Scoped, e *ent.WebhookEndpoint, sendErr error, ...) error
- func (m *Module) RegenerateSecret(ctx context.Context, s *ent.Scoped, id int64) (Endpoint, error)
- func (m *Module) TestSend(ctx context.Context, s *ent.Scoped, id int64, eventType string) (TestResult, error)
- func (m *Module) Update(ctx context.Context, s *ent.Scoped, id int64, in UpdateInput) (Endpoint, error)
- type TestResult
- type UpdateInput
Constants ¶
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.
const TestSendTimeout = 15 * time.Second
TestSendTimeout bounds a test delivery, the same budget as a real one.
Variables ¶
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.
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 ¶
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 ¶
Create validates the URL and the event filter, generates the signing secret and stores it sealed.
func (*Module) List ¶
func (m *Module) List(ctx context.Context, s *ent.Scoped, p pagination.Params) (pagination.Page[Endpoint], error)
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 ¶
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).
type TestResult ¶
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 ¶
UpdateInput changes only what is set: a nil field is left alone.