v0.9.0
- A blue team check page. Each check a team is scored on now has its own page, showing the fields
that team controls, how the check has been going for them, and the recent rounds with the reason
for each failure
- Check names on the scoreboard are links. A blue teamer lands on their own team's view of that
check, staff land on the check's settings in the admin panel, and an anonymous viewer gets no
link, since the scoreboard is public and the destinations are not
- Blue teams can set their own values for a check's declared variables. Everything on the card
saves in one request, and a rejected variable takes the whole batch with it, so the form can
never half-apply. A secret stays write-only, so its box starts empty and a badge says whether the
team has already set one
- Per-check statistics for a team: passed, failed, uptime, the points the check has earned, and
average and most recent response time
- Two charts on the check page, drawn with @tanstack/charts. An uptime strip with one bar per
round, and a response time line. Hovering either names the round, the result and the points, or
the latency
- A paginated table of recent rounds, with page sizes, a Refresh button and a last-updated time.
It also polls on the round interval, so a team watching a fix land sees it without pressing
anything
- Chain checks show which step failed and which never ran. The runner stops at the first required
failure and records nothing for the steps after it, so the page reads the chain's declared steps
and marks those as never run rather than leaving them off the list
- `GET /api/checks/{id}/results/mine` and `GET /api/checks/{id}/stats/mine`, both blue team gated,
both scoped to the calling team by its token rather than by anything in the request
- Check fields can be hidden by a condition. An http request body is now hidden until a content
type is chosen, instead of sitting there asking to be filled in for a request that will not
carry it
- The browser tab reads "(DEV) Hermes" when the frontend runs in development, so a dev tab is not
mistaken for the live one
## Changed
- `PUT /api/checks/{id}/variables/mine` takes the whole set of variables in one `variables` JSON
array instead of one `variable_name` and `variable_value` per request. This breaks any existing
caller. The saved Bruno requests are updated
- A check's status on the scoreboard is now derived from whether the check succeeded, with its
status text asked only whether the check reached a verdict at all. The scoreboard and the blue
team check page read the same four states with the same wording, so a round cannot be labelled
one way in one place and another way in the other. Each theme keeps its own colours
- Blue team check code gathered into one `blue_checks.go` per package, and the blue team requests
moved out of the Bruno collection's "admin actions" folder into their own
- The blue team check page split into a page plus three components, in line with how the admin
check pages are laid out
- A new index on `Round_Ledger (user_id, check_id, round_id DESC)`. A team's history for one check
used to scan the whole ledger, since the existing unique constraint leads with `round_id`.
`setup_db.go` only runs against a fresh database, so an existing deployment needs the statement
applied by hand
## Fixed
- The scoreboard logged `retrieved unknown check status` to the console on every cell, every
render, for any status outside a fixed list it matched against. That list had fallen behind the
engine: a cancelled check was never in it, and neither were rows left over from an earlier
version. Both now resolve without the noise