Every 400, 403, 404 and 500 on an admin page now answers with an error page in the normal layout: the status, one fixed line explaining it, and a link back to the webhook list, or to sign-in when nobody is signed in. Unknown paths reach it through the router's not-found handler, and a refused form token through the CSRF middleware, which now takes the page to answer with. Status codes are unchanged. The receiver at the entrypoint URL, the healthcheck and /metrics keep their plain answers.
What the diff does not show: if the error page itself fails to render, the answer is the same status in plain text, so a broken template can neither loop nor turn a 404 into a 500. A normal page that fails to render now gets the 500 page.
Judgement call: the page for an unknown path outside every route group carries no form token, so its navbar leaves out Logout rather than offer a button that would be refused.
Judgement call: the line is fixed per status, so a refused form token and another user's profile share the 403 line.
Judgement call: the profile page's busy answer (503), which the issue lists, uses the page too.
Not changed: form validation messages (#381, #370), the middleware's 413 and 429 answers, and the 500 written after a panic stay plain text.
chi wraps a not-found handler in its router's middleware, so an unknown path inside a route group runs that group's middleware twice; all of it is safe to repeat.
Model: opus-5-5
Every 400, 403, 404 and 500 on an admin page now answers with an error page in the normal layout: the status, one fixed line explaining it, and a link back to the webhook list, or to sign-in when nobody is signed in. Unknown paths reach it through the router's not-found handler, and a refused form token through the CSRF middleware, which now takes the page to answer with. Status codes are unchanged. The receiver at the entrypoint URL, the healthcheck and `/metrics` keep their plain answers.
What the diff does not show: if the error page itself fails to render, the answer is the same status in plain text, so a broken template can neither loop nor turn a 404 into a 500. A normal page that fails to render now gets the 500 page.
- Judgement call: the page for an unknown path outside every route group carries no form token, so its navbar leaves out Logout rather than offer a button that would be refused.
- Judgement call: the line is fixed per status, so a refused form token and another user's profile share the 403 line.
- Judgement call: the profile page's busy answer (503), which the issue lists, uses the page too.
- Not changed: form validation messages (https://git.eeqj.de/sneak/webhooker/issues/381, https://git.eeqj.de/sneak/webhooker/issues/370), the middleware's 413 and 429 answers, and the 500 written after a panic stay plain text.
- chi wraps a not-found handler in its router's middleware, so an unknown path inside a route group runs that group's middleware twice; all of it is safe to repeat.
Model: opus-5-5
Every 400, 403, 404 and 500 on an admin page now answers with an
error page in the normal layout: one fixed line for the status and a
link back to the webhook list, or to sign-in when nobody is signed
in. The router's handler for unknown paths and the CSRF middleware's
refusal use the same page. Status codes are unchanged. The receiver,
the healthcheck and /metrics keep their plain answers. If the error
page itself cannot render, the answer is the same status in plain
text.
Model: opus-5-5
Does not build on current next. The branch rebases without conflicts, but HandleSourceDetail in internal/handlers/source_management.go now has two h.serverError(w, msg, err) calls from the recent-events change (#347) that use the old signature, so the handlers package no longer compiles. Acceptable: rebase onto current next and pass the request in both calls, so those two new 500s on the webhook page also render the error page.
A 500 after a panic on an admin page is still plain text. The definition of done says every admin page route answers 500 with a rendered page, and the PR lists this case as not changed. It can be rendered safely: the recoverer already knows whether anything was written, and the page renders into a buffer with a plain-text fallback. Acceptable: on admin page routes, a panic caught before anything was written answers with the 500 error page; if that page fails or panics while rendering, the answer is the plain 500 as today; the receiver, the healthcheck and /metrics keep the plain 500; the panic is still logged and still reported to error tracking; a test sends a panicking admin page handler through the real router.
Some error pages show the signed-in user but can be cached. The page for an unknown path outside the route groups, and the page for a refused form token (sent before NoCache runs), show the user's name and profile link without Cache-Control: no-store. Every other page that shows them sends that header. Acceptable: the error page always sends Cache-Control: no-store, for example set in renderError.
Judgement call: leaving the 413 and 429 answers plain meets the definition of done, which names only 400, 403, 404 and 500.
Judgement call: with metrics turned off, /metrics is an unknown path and now gets the HTML 404 page. The same goes for receiver-like paths that are not an entrypoint URL, such as /webhook/a/b. I read that as the rule for unknown paths, not a change to /metrics or the receiver.
Model: opus-5-5
Review: FAIL (needs-rework)
1. **Does not build on current `next`.** The branch rebases without conflicts, but `HandleSourceDetail` in `internal/handlers/source_management.go` now has two `h.serverError(w, msg, err)` calls from the recent-events change (https://git.eeqj.de/sneak/webhooker/issues/347) that use the old signature, so the handlers package no longer compiles. Acceptable: rebase onto current `next` and pass the request in both calls, so those two new 500s on the webhook page also render the error page.
2. **A 500 after a panic on an admin page is still plain text.** The definition of done says every admin page route answers 500 with a rendered page, and the PR lists this case as not changed. It can be rendered safely: the recoverer already knows whether anything was written, and the page renders into a buffer with a plain-text fallback. Acceptable: on admin page routes, a panic caught before anything was written answers with the 500 error page; if that page fails or panics while rendering, the answer is the plain 500 as today; the receiver, the healthcheck and `/metrics` keep the plain 500; the panic is still logged and still reported to error tracking; a test sends a panicking admin page handler through the real router.
3. **Some error pages show the signed-in user but can be cached.** The page for an unknown path outside the route groups, and the page for a refused form token (sent before `NoCache` runs), show the user's name and profile link without `Cache-Control: no-store`. Every other page that shows them sends that header. Acceptable: the error page always sends `Cache-Control: no-store`, for example set in `renderError`.
- Judgement call: leaving the 413 and 429 answers plain meets the definition of done, which names only 400, 403, 404 and 500.
- Judgement call: with metrics turned off, `/metrics` is an unknown path and now gets the HTML 404 page. The same goes for receiver-like paths that are not an entrypoint URL, such as `/webhook/a/b`. I read that as the rule for unknown paths, not a change to `/metrics` or the receiver.
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.
Every 400, 403, 404 and 500 on an admin page now answers with an error page in the normal layout: the status, one fixed line explaining it, and a link back to the webhook list, or to sign-in when nobody is signed in. Unknown paths reach it through the router's not-found handler, and a refused form token through the CSRF middleware, which now takes the page to answer with. Status codes are unchanged. The receiver at the entrypoint URL, the healthcheck and
/metricskeep their plain answers.What the diff does not show: if the error page itself fails to render, the answer is the same status in plain text, so a broken template can neither loop nor turn a 404 into a 500. A normal page that fails to render now gets the 500 page.
Model: opus-5-5
Review: FAIL (needs-rework)
Does not build on current
next. The branch rebases without conflicts, butHandleSourceDetailininternal/handlers/source_management.gonow has twoh.serverError(w, msg, err)calls from the recent-events change (#347) that use the old signature, so the handlers package no longer compiles. Acceptable: rebase onto currentnextand pass the request in both calls, so those two new 500s on the webhook page also render the error page.A 500 after a panic on an admin page is still plain text. The definition of done says every admin page route answers 500 with a rendered page, and the PR lists this case as not changed. It can be rendered safely: the recoverer already knows whether anything was written, and the page renders into a buffer with a plain-text fallback. Acceptable: on admin page routes, a panic caught before anything was written answers with the 500 error page; if that page fails or panics while rendering, the answer is the plain 500 as today; the receiver, the healthcheck and
/metricskeep the plain 500; the panic is still logged and still reported to error tracking; a test sends a panicking admin page handler through the real router.Some error pages show the signed-in user but can be cached. The page for an unknown path outside the route groups, and the page for a refused form token (sent before
NoCacheruns), show the user's name and profile link withoutCache-Control: no-store. Every other page that shows them sends that header. Acceptable: the error page always sendsCache-Control: no-store, for example set inrenderError./metricsis an unknown path and now gets the HTML 404 page. The same goes for receiver-like paths that are not an entrypoint URL, such as/webhook/a/b. I read that as the rule for unknown paths, not a change to/metricsor the receiver.Model: opus-5-5
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.