Skip to content

feat(ui): wire the platform and admin pages to the control API - #1376

Closed
kvlonge wants to merge 17 commits into
mainfrom
feat/ui-warehouse-sync
Closed

kvlonge wants to merge 17 commits into
mainfrom
feat/ui-warehouse-sync

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Why

The Locations, People, Roles and Audit log pages, the alert banner and the warehouse sync indicator still ran on mock data or were hidden. This wires them to the control API, adding the person reads they need, so the served UI shows live platform and admin state with capability gating.

Changes

  • Audit log: the security audit read pages newest first with a before cursor and names actors on person reads. The page shows the refused action, decision ID and reason for denials.
  • People and roles: GET /api/admin/people (user.manage) and GET /api/admin/roles (role.assign). Disabled people's sessions are not counted as active.
  • Locations: GET …/targets/{target}/health behind the listing gate, filtered to the target before its 100-observation limit. The page derives health, deployed version and connection test from it.
  • Alert banner: GET /api/control/platform/problems derives a stopped scheduler, broken locations and late schedules with the watchdog's thresholds. Per-target access is checked before ticks are read. Nothing is stored.
  • Roles: GET /api/admin/locations/{id}/targets/{target}/roles (server-wide role.assign) returns built-in and published roles with matched nodes and holder counts.
  • Top bar warehouse sync status from the health read. After a refusal it stops asking, so it adds no audited denials.
  • Unsupported widgets stay hidden (no-placeholders rule). No DuckShop case: these are control-API reads and UI, not project shapes or data values.

Verification

  • Native tests on SQLite and PostgreSQL: location health (including a busier target), platform problems, project roles, audit, person-session role matrix.
  • make check-ci, svelte-check, vitest (87).
  • Browser checks against sqb server for admin, viewer and partial-view people: Locations healthy and broken, banner raised and cleared, Roles list and detail, sync status, no denials from polling.

Add a person read of a target's published snapshots with the subjects
each one changed, behind the same listing authorisation as jobs. The
Changes page reads it, and the Lineage page builds its graph and
inspector from the catalog listing, so neither page needs mock data.
Person reads of the security audit accept an exclusive upper cursor that
returns the newest entries first, and name each principal actor. Exports
keep their payload unchanged.
The audit log reads the newest security facts first, lists a denial
under the action it refused with its decision ID and reason, and names
principal actors. Its actor and action filters come from the entries,
and links to the person page and access checker stay hidden until the
people read exists.
Add GET /api/admin/people, which needs user.manage everywhere, and GET
/api/admin/roles, which needs role.assign everywhere. People carry sign-in
facts only: password presence, SSO groups, live session count and last
sign-in. Role holdings list person assignments and SSO group mappings.
The people page lists everyone with their highest role, its source and
last sign-in. A person's sign-in source is shown only when the server
knows it. Links to the person page and access checker, and the risky
actions filter, stay hidden until their reads exist.
Disabling a person blocks their sessions without revoking them, so the
people read no longer counts those sessions as active.
Add GET /api/control/locations/{location_id}/targets/{target}/health
behind the same listing gate as jobs. It returns the target's newest
health observations and instance check-ins, shared with the machine
read through one helper.
Health comes from each location's check-ins and observations: no check-in
for 90 seconds is broken, a failed compile at or after the connected
generation is falling back, and an unhealthy connection is degraded.
People without listing view see the health as unknown. Server status,
detail links and the deploy policy column appear only when supported.
The person health read filtered by target only after the location's
newest 100 observations were taken across all targets, so a busier
target could push out another target's compile or connection reports.
The target filter now applies before each limit.
Add GET /api/control/platform/problems for the UI's alert banner. It
derives problems at read time with the watchdog's thresholds: whether
the scheduler has a leader, location targets whose instances all missed
two check-ins, and running schedules more than 30 seconds late. Broken
locations and late ticks appear only for targets the person lists, and
access is checked per target before that target's ticks are read.
The banner reads the new problems endpoint every 30 seconds, because
missed check-ins and late ticks come from time passing, not change
notices. A stopped scheduler and each broken location are critical, and
late schedules are grouped per location. The read now names each
location and dates a stopped scheduler from its last lease. Links go to
the Locations list until location detail pages are supported.
Add GET /api/admin/locations/{location_id}/targets/{target}/roles behind
server-wide role.assign, like the role holdings read. It returns the
built-in roles with their actions, then the target's published custom
roles with their description, grants and the nodes each selector
matched, and how many active people hold each role there.
The Roles list and role pages read the new role definitions endpoint.
Built-in roles show their actions on every node, and custom roles show
their published grants, the nodes each selector matched, the published
definition and who holds them on this location. Holder counts include
SSO group members, counted once per person. The SSO mappings tab and the
base-role comparison stay hidden until the server provides them.
The top bar reads the target's warehouse sync reports from the health
read: when a table last synced cleanly, and which tables' newest sync
failed and at what stage. It rereads every 30 seconds with the alert
banner, because sync reports send no change notice.
Every refused health read writes an audit denial, so a person who sees a
location but may not list all of its nodes would add one each poll. The
shell now asks once per target per page load and keeps the indicator at
its unknown state after a refusal.
Brings in the Lineage and Changes squash. Moves list_people to the
credentials identities owner so the authorization entry container stays
within its module limit.
@kvlonge
kvlonge enabled auto-merge (squash) November 8, 2026 16:12

kvlonge commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

Folded into the single combined sqlbuild PR (D625/D626), which the SQLBuild lane is assembling now and opens once #1377 lands. Branch kept.

@kvlonge kvlonge closed this Nov 8, 2026
auto-merge was automatically disabled November 8, 2026 21:16

Pull request was closed

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