rdev/internal/domain/webhook.go
jordan bc47e426b0 feat: Add CI pipeline proxy, DNS alias management, and worker executor system
- Add ListPipelines/GetPipeline to CIProvider port with Woodpecker adapter
- Add DNS alias endpoints: GET/POST/DELETE /projects/{id}/domains
- Implement worker executor daemon, build executor, and git operations
- Add build service, worker service, and build audit tracking
- Add worker registry with PostgreSQL adapter and migration
- Add multi-provider code agent interface (Claude Code + OpenCode)
- Add create-and-build combo endpoint
- Update landing-page cookbook to reflect all gaps closed
- Fix tech debt: unified validation, auth scopes, error wrapping, slog patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:05:28 -07:00

156 lines
5.1 KiB
Go

package domain
import (
"time"
)
// WebhookID is a strongly-typed identifier for webhooks.
type WebhookID string
// String returns the webhook ID as a string.
func (id WebhookID) String() string {
return string(id)
}
// WebhookEventType represents the type of event that triggers a webhook.
type WebhookEventType string
// Available webhook event types.
const (
WebhookEventCommandStarted WebhookEventType = "command.started"
WebhookEventCommandCompleted WebhookEventType = "command.completed"
WebhookEventCommandFailed WebhookEventType = "command.failed"
WebhookEventPodReady WebhookEventType = "pod.ready"
WebhookEventPodFailed WebhookEventType = "pod.failed"
)
// AllWebhookEventTypes lists all valid webhook event types.
var AllWebhookEventTypes = []WebhookEventType{
WebhookEventCommandStarted,
WebhookEventCommandCompleted,
WebhookEventCommandFailed,
WebhookEventPodReady,
WebhookEventPodFailed,
}
// IsValid checks if a webhook event type is valid.
func (t WebhookEventType) IsValid() bool {
for _, valid := range AllWebhookEventTypes {
if t == valid {
return true
}
}
return false
}
// String returns the event type as a string.
func (t WebhookEventType) String() string {
return string(t)
}
// Webhook represents a webhook subscription for a project.
type Webhook struct {
ID WebhookID `json:"id"`
ProjectID string `json:"project_id"`
URL string `json:"url"`
Secret string `json:"-"` // Never expose secret in JSON responses
Events []WebhookEventType `json:"events"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// HasSecret returns true if the webhook has a signing secret configured.
func (w *Webhook) HasSecret() bool {
return w.Secret != ""
}
// SubscribesToEvent checks if the webhook subscribes to the given event type.
func (w *Webhook) SubscribesToEvent(eventType WebhookEventType) bool {
for _, e := range w.Events {
if e == eventType {
return true
}
}
return false
}
// WebhookDeliveryID is a strongly-typed identifier for webhook deliveries.
type WebhookDeliveryID string
// String returns the delivery ID as a string.
func (id WebhookDeliveryID) String() string {
return string(id)
}
// WebhookDelivery represents a single webhook delivery attempt.
type WebhookDelivery struct {
ID WebhookDeliveryID `json:"id"`
WebhookID WebhookID `json:"webhook_id"`
EventType WebhookEventType `json:"event_type"`
Payload string `json:"payload"` // JSON payload that was sent
ResponseStatus int `json:"response_status,omitempty"`
ResponseBody string `json:"response_body,omitempty"`
DeliveredAt time.Time `json:"delivered_at"`
Success bool `json:"success"`
RetryCount int `json:"retry_count"`
ErrorMessage string `json:"error_message,omitempty"`
}
// WebhookEvent represents an event to be dispatched to webhooks.
type WebhookEvent struct {
Type WebhookEventType `json:"type"`
Timestamp time.Time `json:"timestamp"`
ProjectID string `json:"project_id"`
Data any `json:"data"`
}
// WebhookPayload is the structure sent to webhook endpoints.
type WebhookPayload struct {
ID string `json:"id"` // Unique delivery ID
Event WebhookEventType `json:"event"` // Event type
Timestamp time.Time `json:"timestamp"` // When the event occurred
ProjectID string `json:"project_id"` // Project this event relates to
Data any `json:"data"` // Event-specific data
}
// CommandEventData is the data structure for command-related webhook events.
type CommandEventData struct {
CommandID string `json:"command_id"`
CommandType CommandType `json:"command_type"`
ProjectID string `json:"project_id"`
StartedAt time.Time `json:"started_at,omitempty"`
CompletedAt time.Time `json:"completed_at,omitempty"`
ExitCode int `json:"exit_code,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Error string `json:"error,omitempty"`
}
// PodEventData is the data structure for pod-related webhook events.
type PodEventData struct {
PodName string `json:"pod_name"`
ProjectID string `json:"project_id"`
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
// WebhookFilters contains filter options for listing webhook deliveries.
type WebhookDeliveryFilters struct {
EventType *WebhookEventType // Filter by event type
Success *bool // Filter by success status
Limit int // Max results (default 100)
Offset int // For pagination
}
// DefaultWebhookDeliveryFilters returns sensible defaults.
func DefaultWebhookDeliveryFilters() *WebhookDeliveryFilters {
return &WebhookDeliveryFilters{
Limit: 100,
Offset: 0,
}
}
// Webhook-related errors are defined in errors.go for centralized error definitions.