Files
pad/internal/models/webhook.go
T
xarmian f6938b33a5 feat(webhooks): owner webhooks keep per-endpoint delivery state; 408/425/429 are retried (TASK-3409) (#1809)
* fix(webhooks): 408, 425 and 429 are transient on the owner and app delivery paths, through one shared RetryableStatus (TASK-3409)

* feat(webhooks): owner hooks keep per-endpoint delivery state: a retry goes only to endpoints still owed, a 4xx is final for the event, and endpoints still owed when retention gives up are counted as dropped (GET /webhooks, pad webhook list) (TASK-3409)

* fix(webhooks): an owner endpoint deactivated while an event is still owed to it is recorded and counted as dropped, not silently skipped (TASK-3409, codex r1)

* fix(store): the automatic deactivation settles the endpoint's owed deliveries as dropped and counts them, in its own transaction (TASK-3409, codex r2)
2026-10-05 14:44:50 -04:00

38 lines
1.6 KiB
Go

package models
import "time"
// Webhook represents a registered webhook endpoint that receives
// POST notifications when events occur in a workspace.
type Webhook struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
URL string `json:"url"`
// Secret is the HMAC signing secret in PLAINTEXT. It is encrypted at rest
// (see internal/store/webhooks.go) and decrypted on read for internal use
// (the dispatcher signs payloads with it). API responses return the raw
// secret ONLY on creation; list/get responses mask it — see
// internal/server/handlers_webhooks.go::maskWebhookSecret.
Secret string `json:"secret,omitempty"`
// HasSecret reports whether an HMAC secret is configured, without leaking
// the value. Populated on reads so masked responses still signal presence.
HasSecret bool `json:"has_secret"`
Events string `json:"events"`
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastTriggeredAt *time.Time `json:"last_triggered_at,omitempty"`
FailureCount int `json:"failure_count"`
// DroppedCount counts events this endpoint was still owed when the outbox
// gave up on them at its retention bound (TASK-3409; app hooks also count
// their 24 h drop, U10c).
DroppedCount int `json:"dropped_count"`
}
// WebhookCreate is the input for registering a new webhook.
type WebhookCreate struct {
URL string `json:"url"`
Secret string `json:"secret,omitempty"`
Events string `json:"events,omitempty"` // JSON array of event types, defaults to ["*"]
}