Expand description
POST /api/webhooks/{source} — the console’s webhook ingress (#5089 step 3).
Why: ADR-0032 removed every sibling daemon’s HTTP listener, and ADR-0034
rules that console terminates the GitHub request and relays inward over UDS.
The two handlers this path replaced both acknowledged GitHub before the
work ran and downgraded every later failure to a log line. GitHub never
retries an acknowledged delivery, so each of those failures was permanent,
silent loss with every health signal still green. #5181 deleted them —
trusty-review’s POST /pr/github/webhook and trusty-analyze’s
POST /webhooks/github now 404 — so this route is the only HTTP webhook
surface in the workspace, and the only holder of the shared secret.
What: one route, multiplexed by {source} over both targets. The order of
operations is the fix and is not negotiable:
- unknown
{source}→404, before any secret handling; - HMAC verified once, over the exact received bytes; unset secret and bad
signature both →
401(ADR-0034 §2 unifies the policy to fail-closed); - the delivery is written and fsync’d to the spool — on failure
500, and no202is ever sent, so GitHub keeps the delivery redeliverable; - the relay runs, and its outcome is recorded durably: an explicit ack
deletes the entry, anything else leaves it
pendingwith an incremented attempt count; 202, because step 3 succeeded — not because step 4 did.
🔴 Explicitly absent, per ADR-0034 §2: let _ = relay(...), a bare
tracing::warn! as the sole record of a failed relay, and any 202 issued
before the spool write returns.
Spawn-on-demand — console starting a target that is not resident — landed in
#5182 alongside the targets’ listeners: spawn::TargetSupervisor runs
ensure_running before each relay. A target that will not start is still
relay::RelayOutcome::Unreachable, which is a durable pending state, not a
dropped delivery.
Test: tests.rs.
Re-exports§
pub use schedule::BackoffPolicy;
Modules§
- health
- Oldest-pending-age as a red health state on
/api/console/metrics/*. - relay
- Sending a spooled delivery to its target, and deciding what counts as an acknowledgement.
- schedule
- Who may relay an entry, and when — the two guards that keep one delivery from becoming several relays.
- spawn
- Starting a relay target that is not running (#5182, ADR-0034 §1).
- spool
- The durable spool: a delivery is on disk and fsync’d before console acknowledges GitHub.
Structs§
- Sweep
Report - Counts from one
WebhookIngress::retry_pending_oncepass. - Target
- One relay target reachable through
/api/webhooks/{source}. - Webhook
Ingress - The webhook ingress: spool, secret, and one relay per target.
Enums§
- Ingest
Outcome - Result of one ingress attempt, before it becomes an HTTP response.
Constants§
- MAX_
WEBHOOK_ BODY_ BYTES - Largest webhook body the ingress route accepts.
- SECRET_
ENV - Environment variable holding the shared webhook secret.
Functions§
- default_
spool_ root - The spool root, for callers that need it before an ingress exists.
- metrics_
webhooks_ handler GET /api/console/metrics/webhooks— oldest-pending-age as a health state.- start_
retry_ sweep - Run
WebhookIngress::retry_pending_onceon an interval, forever. - webhook_
handler POST /api/webhooks/{source}— the axum front door.