Skip to content

feat(ui): wire the runs pages to the live control API - #1334

Merged
kvlonge merged 16 commits into
mainfrom
feat/ui-runs
Nov 7, 2026
Merged

kvlonge merged 16 commits into
mainfrom
feat/ui-runs

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

The Runs pages still read mock data. People need the live run list and run detail, including who or what requested each run, and the ability to cancel and rerun.

Changes

  • RunRecord gains kind, origin, parent and root run, trigger (id and name), tick, rerun source, requester, priority, rewrite flag, status reason and cancel request time. The changes are additive and use the same authorization as the existing run listing. The OpenAPI document and the TypeScript client are regenerated.
  • Requester decision: anyone who may view a run sees requested_by and, for people, only the principal's display name (requester_name). Contact details are never shown. Machine-origin runs show the trigger name or the system actor.
  • The UI maps the listing, nodes, child runs and reruns onto the Runs list and detail. Cancel and rerun (all, or from failure) go through the CSRF-guarded control routes.
  • Widgets without an endpoint (queue, timeline, new run, bulk cancel, events, statements, output, rerun of selected nodes) are hidden rather than shown as placeholders.
  • Short run IDs show the first 8 hex digits of a UUID.
  • Known limit: list, filters, counts and run pages cover the newest 1,000 runs (the server cap); an older run's page says so.
  • Rerun from failure covers failed and skipped nodes only, matching the server.

DuckShop: no new project shape, data value or lifecycle sequence.

Verification

  • Contract tests on SQLite and PostgreSQL cover person launches, system-seeded runs, sensor runs and rerun lineage. A mutated requester join or name fails them.
  • UI: svelte-check is clean, 50 vitest tests pass and the production build succeeds. The new mapping tests fail on mutated requester and count logic.
  • Live sqb server with password login: launched runs show live status and "by ada-admin"; cancelling a running run reaches Cancelled; rerun from failure runs exactly the failed and skipped nodes.
  • make check-ci passes.

A refused location listing named the nodes the person could not view and
read differently for a location that does not exist. Listing refusals now
carry one fixed message with the decision ID, identical for unassigned and
unknown locations. The audit event keeps the missing nodes.
Every refusal from person authorization now shows fixed text per action
and its decision ID; the audit event keeps the missing nodes. Unknown
jobs and triggers are refused only after the caller is authorized for
the target, so an unknown object reads the same as a forbidden one.
Person sessions can read a run's nodes, the target's triggers and a
trigger's ticks. Each read authorizes like the runs list, with view on
every current node of the target, before looking the object up, so an
unknown run or trigger gets the same refusal as a forbidden one. A person
who may view the whole target gets 404 for an unknown object. The machine
reads share the same in-transaction queries.

Validated locally with SQLite and PostgreSQL: orchestration API tests,
including the forbidden-versus-unknown denial cases for the new reads
(a lookup-before-authorize mutation fails them) and the per-role session
matrix; clippy, fensu, and the regenerated TypeScript client check and
test. Not yet reviewed; stacked on the listing-denial branch.
One store read decides whether a person's target-scoped read may name a run
or a trigger. The handler and per-record read shapes join the existing
duplicate allowlists.
…er-reads

# Conflicts:
#	crates/sqlbuild-orchestration/src/authorization/main/mod.rs
#	crates/sqlbuild-orchestration/tests/api/test_denials.rs
…er-reads

# Conflicts:
#	crates/sqlbuild-orchestration/src/api/models.rs
#	crates/sqlbuild-orchestration/tests/api/test_denials.rs
The person and machine run listings now carry the run metadata the store
already keeps: kind, origin, parent and root run, trigger and tick, rerun
source, priority, history rewrite, status reason and cancel request. They
also name the requester: the stored actor, plus the principal's display
name when a person requested the run.

Validated locally: API, runs, sensors and scheduler tests on SQLite and
PostgreSQL; regenerated TypeScript client.
Map listed runs, nodes, reruns and child runs to the runs pages, with
cancel and rerun (all or from failure) through the CSRF-guarded control
routes. Show the requester's display name for people and the trigger or
system actor otherwise. Widgets without a server endpoint (queue,
timeline, new run, bulk cancel, events, statements, output, rerun of
selected nodes) are hidden instead of showing placeholders. Short run
IDs show the first 8 digits of a UUID.

Validated: svelte-check clean, 50 UI unit tests, production build, and
a live sqb server run (launch, live status, cancel, rerun from failure).
Assert the person-requested and system-requested run fields on every
listing the role matrix already reads, and require that both were seen.
Validated: test_person_sessions on SQLite and PostgreSQL; a wrong
requester name fails it.
The server reruns only failed and skipped nodes, so cancelled nodes no
longer count toward rerun from failure. A run outside the newest 1,000
listed runs now says so instead of rendering an empty page, and a load
error is shown. The person-session test now requires every earlier
person launch in each listing.

Validated: 50 UI tests and svelte-check (the old cancelled counting
fails 2 tests); test_person_sessions on SQLite and PostgreSQL, failing
when one listed run is dropped; fensu check clean.
Base automatically changed from feat/person-run-trigger-reads to main November 7, 2026 02:27
@kvlonge
kvlonge enabled auto-merge (squash) November 7, 2026 02:35
@kvlonge
kvlonge merged commit 68a1551 into main Nov 7, 2026
49 checks passed
@kvlonge
kvlonge deleted the feat/ui-runs branch November 7, 2026 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant