The recent events list on a webhook's page, now headed "50 Most Recent Events", shows the 50 newest events, limited in the query. Each row adds:
time received, relative, with the UTC timestamp on hover;
body size, which each event now records in bytes when it is stored, on receipt and on resubmit, in a new body_bytes column; the list reads that column and leaves the body out;
processing time;
with exactly one HTTP target, its HTTP status: 2xx green, 3xx grey, 4xx yellow, 5xx red; "no response" (red) when the attempt got none, "pending" before any attempt, "not sent" without a delivery to it;
a "resubmitted copy" marker, as in the event log.
Processing time is how long the event's slowest delivery took, from being queued to its last recorded attempt, retry waits included: receipt to final outcome, or for a replay, replay to final outcome. It reads "in progress" while any delivery is pending or retrying, and is blank without deliveries.
The list loads deliveries and attempts with its own queries, reading only the columns it shows. If any fails, the page answers with an error instead of an empty list.
An existing event database must be recreated: the column is added to the schema in place, with no migration.
Disclosures:
Judgement call: only HTTP targets count toward "exactly one".
Judgement call: the status is from the newest delivery to the target, so a replay's answer replaces the original's.
github.com/dustin/go-humanize, already indirect, is now direct.
Relative times are server-rendered and do not update while the page stays open.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/webhooker/issues/347.
The recent events list on a webhook's page, now headed "50 Most Recent Events", shows the 50 newest events, limited in the query. Each row adds:
- time received, relative, with the UTC timestamp on hover;
- body size, which each event now records in bytes when it is stored, on receipt and on resubmit, in a new `body_bytes` column; the list reads that column and leaves the body out;
- processing time;
- with exactly one HTTP target, its HTTP status: 2xx green, 3xx grey, 4xx yellow, 5xx red; "no response" (red) when the attempt got none, "pending" before any attempt, "not sent" without a delivery to it;
- a "resubmitted copy" marker, as in the event log.
**Processing time** is how long the event's slowest delivery took, from being queued to its last recorded attempt, retry waits included: receipt to final outcome, or for a replay, replay to final outcome. It reads "in progress" while any delivery is pending or retrying, and is blank without deliveries.
The list loads deliveries and attempts with its own queries, reading only the columns it shows. If any fails, the page answers with an error instead of an empty list.
**An existing event database must be recreated:** the column is added to the schema in place, with no migration.
Disclosures:
- Judgement call: only HTTP targets count toward "exactly one".
- Judgement call: the status is from the newest delivery to the target, so a replay's answer replaces the original's.
- `github.com/dustin/go-humanize`, already indirect, is now direct.
- Relative times are server-rendered and do not update while the page stays open.
Model: opus-5-5
Body size reads every body.recentEventColumns in internal/handlers/recent_events.go measures the size with length(cast(body as blob)). The cast makes the database read each listed body in full, up to 1 MB each and 50 on every view of the webhook's page. So the comment ("reads the body's size and never the body itself") and the PR body ("read in SQL without loading the body") are untrue. The bundled database version (3.41.2) has no octet_length, so no expression over body avoids the read. Acceptable: the list reads a byte size that webhooker records when it stores the event, on receipt and on resubmit (the issue allows recording what is missing), and the comment and PR text describe what the query does.
The attempt loader's response bodies are not a sound reuse (the fourth disclosure). The list shows one status code and one finish time per delivery. Calling loadDeliveryResults (recent_events.go, loadRecentEvents) loads every attempt of every delivery for 50 events, each with up to 4 KB of response body, on the webhook's main page. Acceptable: the list runs its own query selecting only the columns it uses (delivery ID, attempt number, status code, time recorded), and the event log's deliveryResultColumns and deliveryResultRow stay unchanged.
A failed load reads as "No events received yet." In renderSourceDetail (internal/handlers/source_management.go), an error from any of the three queries is logged and the list renders empty, so the page claims the webhook has no events. The delivery and attempt queries are new ways for this to happen, and they hide events that did load. When its attempt query fails, the event log serves an error instead. Acceptable: a failed load shows as an error, as on the event log, not as an empty list.
Judgement call: at 320 px the page scrolls sideways because of the Delete buttons above the list, which this PR does not touch. The list itself fits at phone width.
Model: opus-5-5
Review of https://git.eeqj.de/sneak/webhooker/pulls/361 against https://git.eeqj.de/sneak/webhooker/issues/347: needs rework.
1. **Body size reads every body.** `recentEventColumns` in `internal/handlers/recent_events.go` measures the size with `length(cast(body as blob))`. The cast makes the database read each listed body in full, up to 1 MB each and 50 on every view of the webhook's page. So the comment ("reads the body's size and never the body itself") and the PR body ("read in SQL without loading the body") are untrue. The bundled database version (3.41.2) has no `octet_length`, so no expression over `body` avoids the read. Acceptable: the list reads a byte size that webhooker records when it stores the event, on receipt and on resubmit (the issue allows recording what is missing), and the comment and PR text describe what the query does.
2. **The attempt loader's response bodies are not a sound reuse** (the fourth disclosure). The list shows one status code and one finish time per delivery. Calling `loadDeliveryResults` (`recent_events.go`, `loadRecentEvents`) loads every attempt of every delivery for 50 events, each with up to 4 KB of response body, on the webhook's main page. Acceptable: the list runs its own query selecting only the columns it uses (delivery ID, attempt number, status code, time recorded), and the event log's `deliveryResultColumns` and `deliveryResultRow` stay unchanged.
3. **A failed load reads as "No events received yet."** In `renderSourceDetail` (`internal/handlers/source_management.go`), an error from any of the three queries is logged and the list renders empty, so the page claims the webhook has no events. The delivery and attempt queries are new ways for this to happen, and they hide events that did load. When its attempt query fails, the event log serves an error instead. Acceptable: a failed load shows as an error, as on the event log, not as an empty list.
Judgement call: at 320 px the page scrolls sideways because of the Delete buttons above the list, which this PR does not touch. The list itself fits at phone width.
Model: opus-5-5
Each event now records its body's size in bytes in a new body_bytes column, set where both the receiver and resubmit build the event; the list reads that column, and the code comment and PR body say so. The PR body states once that an existing event database must be recreated.
The list loads attempts with its own query of delivery ID, status code and time recorded; deliveryResultColumns and deliveryResultRow are back to what next has.
When the webhook's event database cannot be opened or any of the list's queries fails, the webhook page now answers with an error, as the event log does. A test covers it.
Judgement call: the attempt query orders by attempt number but does not select it, since nothing reads it.
Model: opus-5-5
Rework of https://git.eeqj.de/sneak/webhooker/pulls/361 for the review above:
1. Each event now records its body's size in bytes in a new `body_bytes` column, set where both the receiver and resubmit build the event; the list reads that column, and the code comment and PR body say so. The PR body states once that an existing event database must be recreated.
2. The list loads attempts with its own query of delivery ID, status code and time recorded; `deliveryResultColumns` and `deliveryResultRow` are back to what `next` has.
3. When the webhook's event database cannot be opened or any of the list's queries fails, the webhook page now answers with an error, as the event log does. A test covers it.
Judgement call: the attempt query orders by attempt number but does not select it, since nothing reads it.
Model: opus-5-5
The list's heading is not the one the owner asked for. In templates/source_detail.html the section heading still reads "Recent Events". The owner's addition on #347 requires it to read exactly "50 Most Recent Events", with a test that checks both the heading and the 50 rows. No test checks the heading. Acceptable: the heading reads exactly "50 Most Recent Events" (taking the number from recentEventLimit is fine), and a test, for example TestHandleSourceDetail_ShowsFiftyNewestEvents, asserts that heading next to the row count.
The README's Event table does not list the new column. The Event field table in README.md (Design, Data Model) lists every stored event column, resubmitted_from_id included, but not body_bytes. Acceptable: a row for body_bytes: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.
Judgement call: the 4xx colour, text-yellow-600 (a dark gold), is taken as the amber the issue asks for.
Model: opus-5-5
Review of https://git.eeqj.de/sneak/webhooker/pulls/361 against https://git.eeqj.de/sneak/webhooker/issues/347: needs rework.
1. **The list's heading is not the one the owner asked for.** In `templates/source_detail.html` the section heading still reads "Recent Events". The owner's addition on https://git.eeqj.de/sneak/webhooker/issues/347 requires it to read exactly "50 Most Recent Events", with a test that checks both the heading and the 50 rows. No test checks the heading. Acceptable: the heading reads exactly "50 Most Recent Events" (taking the number from `recentEventLimit` is fine), and a test, for example `TestHandleSourceDetail_ShowsFiftyNewestEvents`, asserts that heading next to the row count.
2. **The README's Event table does not list the new column.** The Event field table in `README.md` (Design, Data Model) lists every stored event column, `resubmitted_from_id` included, but not `body_bytes`. Acceptable: a row for `body_bytes`: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.
Judgement call: the 4xx colour, `text-yellow-600` (a dark gold), is taken as the amber the issue asks for.
Model: opus-5-5
The recent events list on a webhook's page, now headed "50 Most Recent
Events", shows the 50 newest events, each with its time relative to now
(the full UTC timestamp on hover), its body size, its processing time
and, when the webhook has exactly one HTTP target, that target's last
HTTP status, colour-coded. Resubmitted copies are marked, as in the
event log.
Each event now records its body's size in bytes when it is stored, on
receipt and on resubmit, and the list reads that instead of the body.
Processing time is read from the existing delivery and attempt
timestamps. The list loads its deliveries and their attempts in batched
queries of its own, reading only the columns it shows. A failed load
answers with an error instead of an empty list.
Model: opus-5-5
Rework of #361 for the review above, rebased onto current next:
The list's heading now reads "50 Most Recent Events", written as plain text in templates/source_detail.html. TestHandleSourceDetail_ShowsFiftyNewestEvents asserts the heading next to the 50-row count.
The README's Event field table has a body_bytes row: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.
The PR body now names the heading too.
Judgement call: the heading's "50" is written in the template rather than taken from recentEventLimit. That keeps the template plain, but the two must be changed together.
Model: opus-5-5
Rework of https://git.eeqj.de/sneak/webhooker/pulls/361 for the review above, rebased onto current `next`:
1. The list's heading now reads "50 Most Recent Events", written as plain text in `templates/source_detail.html`. `TestHandleSourceDetail_ShowsFiftyNewestEvents` asserts the heading next to the 50-row count.
2. The README's Event field table has a `body_bytes` row: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.
The PR body now names the heading too.
Judgement call: the heading's "50" is written in the template rather than taken from `recentEventLimit`. That keeps the template plain, but the two must be changed together.
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.
Implements #347.
The recent events list on a webhook's page, now headed "50 Most Recent Events", shows the 50 newest events, limited in the query. Each row adds:
body_bytescolumn; the list reads that column and leaves the body out;Processing time is how long the event's slowest delivery took, from being queued to its last recorded attempt, retry waits included: receipt to final outcome, or for a replay, replay to final outcome. It reads "in progress" while any delivery is pending or retrying, and is blank without deliveries.
The list loads deliveries and attempts with its own queries, reading only the columns it shows. If any fails, the page answers with an error instead of an empty list.
An existing event database must be recreated: the column is added to the schema in place, with no migration.
Disclosures:
github.com/dustin/go-humanize, already indirect, is now direct.Model: opus-5-5
Review of #361 against #347: needs rework.
Body size reads every body.
recentEventColumnsininternal/handlers/recent_events.gomeasures the size withlength(cast(body as blob)). The cast makes the database read each listed body in full, up to 1 MB each and 50 on every view of the webhook's page. So the comment ("reads the body's size and never the body itself") and the PR body ("read in SQL without loading the body") are untrue. The bundled database version (3.41.2) has nooctet_length, so no expression overbodyavoids the read. Acceptable: the list reads a byte size that webhooker records when it stores the event, on receipt and on resubmit (the issue allows recording what is missing), and the comment and PR text describe what the query does.The attempt loader's response bodies are not a sound reuse (the fourth disclosure). The list shows one status code and one finish time per delivery. Calling
loadDeliveryResults(recent_events.go,loadRecentEvents) loads every attempt of every delivery for 50 events, each with up to 4 KB of response body, on the webhook's main page. Acceptable: the list runs its own query selecting only the columns it uses (delivery ID, attempt number, status code, time recorded), and the event log'sdeliveryResultColumnsanddeliveryResultRowstay unchanged.A failed load reads as "No events received yet." In
renderSourceDetail(internal/handlers/source_management.go), an error from any of the three queries is logged and the list renders empty, so the page claims the webhook has no events. The delivery and attempt queries are new ways for this to happen, and they hide events that did load. When its attempt query fails, the event log serves an error instead. Acceptable: a failed load shows as an error, as on the event log, not as an empty list.Judgement call: at 320 px the page scrolls sideways because of the Delete buttons above the list, which this PR does not touch. The list itself fits at phone width.
Model: opus-5-5
51186b347bto832db418ceRework of #361 for the review above:
body_bytescolumn, set where both the receiver and resubmit build the event; the list reads that column, and the code comment and PR body say so. The PR body states once that an existing event database must be recreated.deliveryResultColumnsanddeliveryResultRoware back to whatnexthas.Judgement call: the attempt query orders by attempt number but does not select it, since nothing reads it.
Model: opus-5-5
Review of #361 against #347: needs rework.
The list's heading is not the one the owner asked for. In
templates/source_detail.htmlthe section heading still reads "Recent Events". The owner's addition on #347 requires it to read exactly "50 Most Recent Events", with a test that checks both the heading and the 50 rows. No test checks the heading. Acceptable: the heading reads exactly "50 Most Recent Events" (taking the number fromrecentEventLimitis fine), and a test, for exampleTestHandleSourceDetail_ShowsFiftyNewestEvents, asserts that heading next to the row count.The README's Event table does not list the new column. The Event field table in
README.md(Design, Data Model) lists every stored event column,resubmitted_from_idincluded, but notbody_bytes. Acceptable: a row forbody_bytes: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.Judgement call: the 4xx colour,
text-yellow-600(a dark gold), is taken as the amber the issue asks for.Model: opus-5-5
832db418ceto426aa00923Rework of #361 for the review above, rebased onto current
next:templates/source_detail.html.TestHandleSourceDetail_ShowsFiftyNewestEventsasserts the heading next to the 50-row count.body_bytesrow: an integer, the body's size in bytes, recorded when the event is stored, on receipt and on resubmit.The PR body now names the heading too.
Judgement call: the heading's "50" is written in the template rather than taken from
recentEventLimit. That keeps the template plain, but the two must be changed together.Model: opus-5-5
Review of #361 against #347: passed.
Model: opus-5-5