audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested).
What is missing: an http or slack target with retries that keeps failing trips its circuit breaker. Webhooker then stops attempting it until a cooldown ends (internal/delivery/target_http.go, which logs "circuit breaker open, skipping delivery"). Nothing in the UI shows this.
In the audit, a target answering 500 tripped its breaker. On the webhook page, the target list still showed it as "Active" with nothing amiss. In the event log, its deliveries sat at "retrying" for minutes, several of them with "0 attempts" and "No attempts recorded yet". Nothing said why nothing was happening or when it would resume. The breaker's state already feeds a metric (publishCircuitState), but no page shows it.
Definition of done:
On the webhook page, a target whose breaker is open or half-open shows that deliveries to it are paused, and until when: the time the cooldown ends, in UTC and relative.
In the event log, a delivery waiting on an open breaker says so, for example "waiting: target paused after repeated failures, resumes 20:05 UTC". It no longer shows a bare "retrying" with no attempts.
Tests: trip the breaker on a test target, then check that both pages show it, and that both stop showing it once the breaker closes.
PRIORITY: from the owner's audit request of 1 October (#377), in the tier of #367 to #376.
Model: opus-5-5
Owner's request, https://git.eeqj.de/sneak/webhooker/issues/377 (chat, 2026-10-01):
> audit the whole app for stupid cases of missing functionality or basic things like this (like the stats panel at the top that i requested).
What is missing: an `http` or `slack` target with retries that keeps failing trips its circuit breaker. Webhooker then stops attempting it until a cooldown ends (`internal/delivery/target_http.go`, which logs "circuit breaker open, skipping delivery"). Nothing in the UI shows this.
In the audit, a target answering 500 tripped its breaker. On the webhook page, the target list still showed it as "Active" with nothing amiss. In the event log, its deliveries sat at "retrying" for minutes, several of them with "0 attempts" and "No attempts recorded yet". Nothing said why nothing was happening or when it would resume. The breaker's state already feeds a metric (`publishCircuitState`), but no page shows it.
Definition of done:
- On the webhook page, a target whose breaker is open or half-open shows that deliveries to it are paused, and until when: the time the cooldown ends, in UTC and relative.
- In the event log, a delivery waiting on an open breaker says so, for example "waiting: target paused after repeated failures, resumes 20:05 UTC". It no longer shows a bare "retrying" with no attempts.
- Tests: trip the breaker on a test target, then check that both pages show it, and that both stop showing it once the breaker closes.
PRIORITY: from the owner's audit request of 1 October (https://git.eeqj.de/sneak/webhooker/issues/377), in the tier of https://git.eeqj.de/sneak/webhooker/issues/367 to https://git.eeqj.de/sneak/webhooker/issues/376.
Model: opus-5-5
clawbot
self-assigned this 2026-10-01 22:06:19 +02:00
The delivery engine already keeps each target's circuit breaker in memory and publishes its state to a metric (publishCircuitState). Add one plain read: for a target ID, whether its breaker is open or half-open and when its cooldown ends. The handlers get it the way they already get the engine's other state, with no new mechanism.
Webhook page: a target whose breaker is open or half-open shows, in its target list row, that deliveries to it are paused and until when: the cooldown's end in UTC and relative.
Event log: a delivery that is retrying while its target's breaker is open says so, for example "waiting: target paused after repeated failures, resumes 20:05 UTC", instead of a bare "retrying" with no attempts.
Tests: trip the breaker on a test target, check both pages show it, close the breaker, check both stop showing it.
Uses the shared styles; every class defined in the stylesheet; make test-browser unchanged unless a control is added.
Model: opus-5-5
Plan.
- The delivery engine already keeps each target's circuit breaker in memory and publishes its state to a metric (`publishCircuitState`). Add one plain read: for a target ID, whether its breaker is open or half-open and when its cooldown ends. The handlers get it the way they already get the engine's other state, with no new mechanism.
- **Webhook page:** a target whose breaker is open or half-open shows, in its target list row, that deliveries to it are paused and until when: the cooldown's end in UTC and relative.
- **Event log:** a delivery that is retrying while its target's breaker is open says so, for example "waiting: target paused after repeated failures, resumes 20:05 UTC", instead of a bare "retrying" with no attempts.
- Tests: trip the breaker on a test target, check both pages show it, close the breaker, check both stop showing it.
- Uses the shared styles; every class defined in the stylesheet; `make test-browser` unchanged unless a control is added.
Model: opus-5-5
#478 shows a target whose circuit breaker is turning its deliveries away. Its row on the webhook page says its deliveries are paused after repeated failures and until when, in UTC and from now. Each of its retrying deliveries shows as waiting in the event log, and on its delivery line in the event log and on the event's page as "waiting: target paused after repeated failures, resumes" with the same times. When the breaker closes, the plain status returns. The engine gains one read of a target's breaker; the README's circuit breaker section describes what the pages show.
Judgement call: the event's own page shows the same waiting line as the event log.
Judgement call: the event log's collapsed summary says only "waiting"; the reason and time are on the expanded delivery line.
While a half-open breaker's probe delivery is in flight, the time shown is one whole cooldown from now, the delay the breaker gives the other deliveries.
Model: opus-5-5
https://git.eeqj.de/sneak/webhooker/pulls/478 shows a target whose circuit breaker is turning its deliveries away. Its row on the webhook page says its deliveries are paused after repeated failures and until when, in UTC and from now. Each of its `retrying` deliveries shows as waiting in the event log, and on its delivery line in the event log and on the event's page as "waiting: target paused after repeated failures, resumes" with the same times. When the breaker closes, the plain status returns. The engine gains one read of a target's breaker; the README's circuit breaker section describes what the pages show.
- Judgement call: the event's own page shows the same waiting line as the event log.
- Judgement call: the event log's collapsed summary says only "waiting"; the reason and time are on the expanded delivery line.
- While a half-open breaker's probe delivery is in flight, the time shown is one whole cooldown from now, the delay the breaker gives the other deliveries.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Owner's request, #377 (chat, 2026-10-01):
What is missing: an
httporslacktarget with retries that keeps failing trips its circuit breaker. Webhooker then stops attempting it until a cooldown ends (internal/delivery/target_http.go, which logs "circuit breaker open, skipping delivery"). Nothing in the UI shows this.In the audit, a target answering 500 tripped its breaker. On the webhook page, the target list still showed it as "Active" with nothing amiss. In the event log, its deliveries sat at "retrying" for minutes, several of them with "0 attempts" and "No attempts recorded yet". Nothing said why nothing was happening or when it would resume. The breaker's state already feeds a metric (
publishCircuitState), but no page shows it.Definition of done:
PRIORITY: from the owner's audit request of 1 October (#377), in the tier of #367 to #376.
Model: opus-5-5
Plan.
publishCircuitState). Add one plain read: for a target ID, whether its breaker is open or half-open and when its cooldown ends. The handlers get it the way they already get the engine's other state, with no new mechanism.make test-browserunchanged unless a control is added.Model: opus-5-5
#478 shows a target whose circuit breaker is turning its deliveries away. Its row on the webhook page says its deliveries are paused after repeated failures and until when, in UTC and from now. Each of its
retryingdeliveries shows as waiting in the event log, and on its delivery line in the event log and on the event's page as "waiting: target paused after repeated failures, resumes" with the same times. When the breaker closes, the plain status returns. The engine gains one read of a target's breaker; the README's circuit breaker section describes what the pages show.Model: opus-5-5