webhook

package
v0.125.0 Latest Latest
Warning

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

Go to latest
Published: May 11, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

Documentation

Overview

Package webhook dispatches PromptZero lifecycle events as outbound HTTP POSTs. Operators configure per-event subscriptions in config.yaml (`webhooks:`) and events fire non-blocking from the agent's callbacks — tool completion, risk prompts, workflow completion, audit-critical rows, session lifecycle.

The dispatcher queues events to a bounded buffer, retries 5xx/transport errors with exponential backoff, and signs the body with HMAC-SHA256 when a per-subscription secret is set. Close(ctx) drains the queue so shutdown doesn't lose the trailing session_ended payload.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func KnownEventNames added in v0.27.0

func KnownEventNames() []string

KnownEventNames returns the canonical list of event names sorted alphabetically. Useful for error messages and `/webhooks` help output so operators don't have to grep the source.

func ValidateSubscription added in v0.18.0

func ValidateSubscription(s Subscription) error

ValidateSubscription rejects subscription URLs that point at loopback, link-local, or RFC1918 destinations — webhook payloads carry tool inputs/outputs (potentially including captured credentials), so SSRF into the cloud-metadata endpoint (169.254.169.254), local Kubernetes API, or peer services on the host network is in scope.

To target an internal endpoint deliberately, set PROMPTZERO_WEBHOOK_ALLOW_INTERNAL=1 — the rejection becomes a warning.

Validation runs at config-load time so a misconfigured URL fails loudly instead of leaking on first event.

Types

type Dispatcher

type Dispatcher interface {
	Fire(ev Event, payload any)
	// FireByName delivers a payload to a single subscription identified
	// by its `name:` field, bypassing the Events allowlist filter that
	// Fire applies. Used by the rules engine where the operator's intent
	// (`webhook: ops-pager` in a rule's then-block) is "deliver to this
	// specific subscription" rather than "broadcast on this event type".
	// Subscriptions without a matching name are silent — the call is
	// fire-and-forget like Fire. The synthesised event tag is "rule_fired"
	// so the receiver can still distinguish rule-driven deliveries from
	// natural lifecycle events.
	FireByName(name string, payload any)
	Close(ctx context.Context) error
	Subscriptions() []Subscription
	RecentResults(name string) []SendResult
	TestSubscription(ctx context.Context, name string) error
}

Dispatcher is the fire-and-forget interface the rest of the app sees. Fire never blocks (drops with a warning when the queue overflows).

func New

func New(subs []Subscription) Dispatcher

New constructs a dispatcher. When subs is empty it returns a no-op dispatcher so callers don't branch on nil.

type Envelope

type Envelope struct {
	Event     Event     `json:"event"`
	Timestamp time.Time `json:"ts"`
	Payload   any       `json:"payload"`
}

Envelope is the JSON body shape every subscription receives.

type Event

type Event string

Event is one of the seven lifecycle hooks a subscription can filter on. An empty Events list on a subscription means "all events".

const (
	EventToolFinished      Event = "tool_finished"
	EventRiskPrompted      Event = "risk_prompted"
	EventRiskDenied        Event = "risk_denied"
	EventWorkflowCompleted Event = "workflow_completed"
	EventAuditCritical     Event = "audit_critical"
	EventSessionStarted    Event = "session_started"
	EventSessionEnded      Event = "session_ended"
)
const EventRuleFired Event = "rule_fired"

EventRuleFired is the synthetic event tag the worker stamps on envelopes produced by FireByName. Receivers use it to distinguish rule-driven deliveries (one specific subscription) from natural lifecycle events (fan-out by Events filter).

type SendResult

type SendResult struct {
	Event      Event
	At         time.Time
	StatusCode int
	Err        error
}

SendResult is the outcome of a single delivery attempt — used by /webhooks to render a short history per subscription.

type Subscription

type Subscription struct {
	Name    string            `yaml:"name"`
	URL     string            `yaml:"url"`
	Events  []Event           `yaml:"events"`
	Headers map[string]string `yaml:"headers"`
	Secret  string            `yaml:"secret"`
}

Subscription is one configured HTTP webhook target. A zero Events slice opts into every event; a non-empty slice is an allowlist.

Jump to

Keyboard shortcuts

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