Skip to content

feat(#10586): add the superadmin dashboard cards - #10619

Open
agatha197 wants to merge 120 commits into
feat/gh-10585-project-admin-cardsfrom
feat/gh-10586-superadmin-cards
Open

agatha197 wants to merge 120 commits into
feat/gh-10585-project-admin-cardsfrom
feat/gh-10586-superadmin-cards

Conversation

@agatha197

@agatha197 agatha197 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Resolves #10586, #10620, #10638, #10642

Summary

Seventh layer of the role-aware dashboard stack (#10422), reviewed after the board feature: the superadmin dashboard (/admin/dashboard) gets its cards. Every card that also exists for members or project admins is the same component (#10597) read over the current domain (ADR 0012); superadmin-only fields are used only where no scoped field exists.

Default board

Card Data Setting
Session Status 9 scopedSessionsV2(scope: {domain}) count aliases: status stats and a session-type donut with the total -
Pending Sessions scopedSessionsV2 PENDING, oldest first, with project and resource group; reason from compute_session_nodes(scope_id: "domain:<name>") resource group
Scheduling Failures adminSessionSchedulingHistories: donut by result (FAILURE, GIVE_UP, EXPIRED, NEED_RETRY) and the newest attempts; names open the session drawer range
Agents agentsV2: status donut and agent list (replaces the legacy Active Agents card) -
Agent Statistics agentStats (unchanged) -
Failures by Entity Type adminAuditLogsV2 ERROR/DENIED counts per entity type (7 types and "other") as a donut range
Audit Log adminAuditLogsV2 with the shared stats, sparklines, failure-only switch and copyable descriptions range
Top Projects by Usage adminProjectUsageBuckets for the domain, rows ordered by CPU core-hours range, resource group
Fair Share rgProjectFairShares per resource group, lowest factor first resource group

Catalog only: Long-running Sessions, Resource Allocation (adminDomainResourceAllocationV2), Deployment Status, Folders, Users and Resource Groups and Capacity over the domain; Recently Created Sessions; Resource Policies; Keypairs and Sign-ins (adminKeypairsV2, failed sign-ins from adminLoginHistoryV2); Container Registries.

PanelDefinition gains a per-page order and per-page defaultHidden, so one shared definition can be on the board on one page and catalog-only on another. activeSessions, SessionCountDashboardItem, RecentlyCreatedSession and ActiveAgents are removed; stored boards drop the old keys on read.

Behaviour notes for review

  • Audit log reads the whole cluster: a domain entity scope returns only the domain's direct children (566 of 35,002 rows, no session rows), so the superadmin Audit Log and Failures by Entity Type use adminAuditLogsV2; their tooltips say so.
  • Scheduling failures are cluster-wide (the history filter has no domain field), and grouped by result because errorCode is null on every row of this manager.
  • Top Projects is a table, not a stacked area: usage buckets can only be ordered by period start, and ranking whole projects would mean summing rows in the browser. Each row is one manager bucket (project, resource group, day), up to 200, ordered by its CPU core-hours.
  • Keypairs have no expiry field, so "expiring" is shown as inactive. Project names are not links (no per-project admin page); deployments open /admin/deployments/:id.

Verification

VERIFY_TESTS=1 VERIFY_BASE=origin/main bash scripts/verify.sh   (on this branch)
...
=== ALL PASS ===
  • New tests: cardScope.test.ts, superadminCardData.test.ts, per-page order and defaultHidden cases in boardModel.test.ts and panelCatalog.test.ts.
  • Every query was checked against a 26.10 manager first. Browser check on /admin/dashboard and /project/default/admin/dashboard: no GraphQL errors; donut and sparkline tooltips; the Scheduling Failures range setting opens in edit mode; the admin account's stored boards were not changed.

Follow-up fixes in this layer: the Agents card shows its status counts as a stat row and its agents through the agent list's own table (schedulable as a check icon); the Scheduling Failures, Keypairs and Sign-ins, Container Registries and Fair Share tables render their columns the way their list pages do; the Notifications card is removed (WebUI has no page for notification rules or channels); My Sessions is 2x2 again.

Changes after the ready-gate review

  • Recently Created Sessions is hidden on a new superadmin board, so its e2e tests turn it on from the edit sider first and turn it off again when they added it.

Server load

  • Agent statistics are fetched by the agent statistics card itself. The admin page query that held only that fragment refetched network-only every 30 s on both admin pages, even with the card off the board (an empty operation for a project admin, agentStats plus two agent_nodes counts for a superadmin on the project admin page); it is removed.
  • The fair share card pages on the server (limit/offset, same factor order): 5 rows per resource group per refresh instead of 50, and projects past the 50th are no longer dropped.
  • Admin audit log card: the same history/live split as the scoped card (AuditLogPanelAdminHistoryQuery + AuditLogPanelAdminQuery), 17 to 7 aliases per 1-minute refresh for the default range.
  • Failures by Entity Type: each per-type count alias carries @catch(to: NULL), so one failing count shows as 0 instead of erroring the card.
  • The domain session status query drops its active alias, as the mine and project queries did in feat(#10585): add the project admin dashboard cards #10597.

Decisions (2026-10-29)

  • "Keypairs and sign-ins" becomes a "Failed sign-ins" card: catalog key failedLogins, FailedLoginsPanel, title dashboard.card.FailedLogins, new tooltip dashboard.card.FailedLoginsTooltip. The keypair and inactive keypair counts are dropped; the failed sign-in count with its previous-range delta and the recent failed sign-ins table stay. The unused Keypairs, InactiveKeypairs, KeypairsAndLogins and KeypairsAndLoginsTooltip keys are removed.
  • A stored board that still holds keypairsLogins is migrated on read: sanitizeBoard maps it to failedLogins through RENAMED_PANEL_KEYS (id, layout, range setting and knownKeys carried over, so a removed card stays removed).
  • Fair Share reads the card's single resource group (one table instead of one per group); the Fair Share, pending sessions and top projects tooltips say "resource group".
  • The superadmin catalog entries no longer declare refresh: { min } (ADR 0018).

Card header, View all links and ui-common board items (was #10627)

This PR folds the three card-header follow-ups of the stack into one review: #10639 and #10643 were closed into it. The branch now holds all three layers; the review reads the final card header (title, help, header controls, "View all") in one place.

Card "View all" links (was #10627) (#10620)

Summary

Every dashboard card whose subject has a list page gets a small "View all" text button with a right chevron at the right end of its header (an ArrowUpRight icon at first, which read like "enlarge this card"). It opens that page in the same tab, with the card's scope and the filters the page reads from its URL.

  • Each card declares detailLink in panelCatalog.tsx; the board resolves it for the page's scope (mine, project, domain) and the shared card header draws the button. The button reads "View all" (dashboard.card.ViewAll); its tooltip and accessible name read "View in {menu}" (dashboard.card.ViewIn), both in all 21 locales.
  • The destination follows the viewer's role: /project/<p>/session, /project/<p>/admin/session or /admin/session, and the same for deployments, data and users.
  • Only filters the destination parses are passed: sessions statusCategory=running, pending sessions tab=pending-sessions&resourceGroup=<first configured group>, agents status=ALIVE, users tab=credentials, environment tab=registry.
  • No button where no list page exists: failures by entity type, top projects by usage, audit log, scheduling failures, resource and capacity cards, start cards. The card's time range is not carried; most list pages take no date filter from the URL.
Card Member Project admin Superadmin
My Sessions / Session Status /project/p/session?statusCategory=running /project/p/admin/session?statusCategory=running /admin/session?statusCategory=running
Long-running Sessions - as above as above
Recent Sessions /project/p/session - /admin/session
Pending Sessions - none (no pending tab there) /admin/session?tab=pending-sessions&resourceGroup=…
Deployments /project/p/deployments /project/p/admin/deployments /admin/deployments
Folders - /project/p/admin/data /admin/data
Users - /project/p/admin/users /admin/users
Agents / Agent Statistics - - /admin/agent?status=ALIVE / /admin/agent
Fair Share - - /admin/scheduler
Resource Policies - - /admin/resource-policy
Keypairs and Sign-ins - - /admin/users?tab=credentials
Container Registries - - /admin/environment?tab=registry

Verification

  • VERIFY_BASE=origin/main VERIFY_TESTS=1 bash scripts/verify.sh: === ALL PASS ===. detailLink.test.ts covers the role and scope cases.
  • Clicked on the review server: superadmin Agents, Pending Sessions, Session Status, Fair Share; project admin Session Status, Long-running Sessions, Deployments, Folders, Users; member My Sessions, My Recent Sessions, My Deployments. Each destination opened with the filter applied.

Changes after the ready-gate review

  • Agent Statistics draws its own header, so its "View all" never showed. The button moved out of PanelFrame into PanelDetailLinkButton, which both headers render; AgentStats.test.tsx covers it.
  • The member Folders card is pulled until BA-8719, so the Folders row has no member link.

Change a card's resource group and range from its header for a moment (was #10639) (#10638)

Summary

A card whose settings include a resource group or a time range now shows that value as a compact control by its title, like the old dashboard's "My resources in " select. A value picked there is a temporary view; the edit-mode card settings stay the saved default, and the settings modal now says so.

  • panelSettingOverrides.ts: a jotai atom of header picks keyed by board id and panel id (card ids repeat across boards), plus the pure resolution: effective = header pick ?? saved setting ?? card default.
  • useDashboardBoard: every card gets its effective settings through the same panel / vars / detail-link inputs it already reads, so no card component changed how it reads them. Edit and save paths keep using the saved panel.
  • PanelSettingsHeaderControls + PanelHeaderSettingsContext: the resource group select (BAIScopedResourceGroupSelect, same resourceGroupScopeOf as the settings modal, moved to dashboardScope.ts) and the range select (RANGE_PRESETS), size="sm". PanelFrame renders them right after the title and its help glyph; the row's end keeps the card's own actions and the detail link. The total-resources card draws the select where its resource group name was.
  • useResetOnLeavingPath: the "reset when the path changes, not on a same-path remount" rule the board already used for edit mode and the temporary table sort, now a hook that also clears the header picks.
  • Settings modal and sider: "Default settings: {name}", "Default resource groups", "Default time range", a help line, and the sider button "Default card settings".

Behaviour

Event Header value
Pick a value in the header the card reads it at once; the control turns to the secondary variant and a reset button (tooltip "Back to the saved setting (...)") appears
Auto refresh or the refresh button kept
Pick the saved value again, or press reset back to the saved setting, modified state off
Page reload, or leaving the page path dropped; the saved setting shows
Save the card settings in edit mode the new default is saved and that card's header pick is cleared
Another board tab its own picks (keyed by board)

Resource groups: the header picks one group, or clears to the card default (the current resource group, or all groups on a custom panel), the same resourceGroups shape the settings use. A saved choice of several groups is shown as the joined names until a single group is picked.

Cards that got a control: My Total Resource Usage, Resource Presets, Total Resources in Resource Group, Pending Sessions and Reasons, Resource Groups and Capacity, Top Projects by Usage, Fair Share and custom table panels whose source supports a resource group (resource group); My Activity, Audit Log, Long-running Sessions, Scheduling Failures, Failures by Entity Type, Keypairs and Logins (range).

New i18n keys in all 21 locales: dashboard.settings.BackToSavedSetting, DefaultSettingsOf, DefaultCardSettings, DefaultResourceGroups, DefaultTimeRange, DefaultSettingsHelp; CardSettings, CardSettingsOf and ResourceGroups are replaced and removed.

Verification

  • VERIFY_BASE=origin/main VERIFY_TESTS=1 bash scripts/verify.sh: === ALL PASS ===.
  • Unit tests: panelSettingOverrides.test.ts (effective-value resolution, modified flags, override merge, board keying) and useResetOnLeavingPath.test.ts (resets on a path change, not on a same-path remount).
  • On the review server (sujin backend):
    • Superadmin /admin/dashboard: Total Resources picked sftp (CPU 11 → 15 Core); kept after the refresh button and after a 30 s auto refresh; back to default after reload. Scheduling Failures picked "Last 7 days" (failures 666/669 → 7,270/7,281); back to "Last 24 hours" after reload.
    • Project admin /project/default/admin/dashboard: Long-running Sessions "Last 1 hour", Pending Sessions sftp; both back to the default after leaving and returning.
    • Member /project/default/dashboard as a plain user: My Total Resource Usage picked sftp (13 → 17 Core); kept after refresh; back to default after reload. The select lists the project's resource groups from scopedResourceGroups.

Where to look: any card with a resource group or time range on the three dashboard pages; the select sits right after the card title.

Changes after the ready-gate review

  • Total Resources in Resource Group: the card title is the plain card name ("자원 그룹별 총자원" in Korean, which the TotalResourcesInResourceGroup key now reads), with the header picker and one Used/Free switch beside it like on other cards. Every resource group section, the first included, is labelled with its own group name, so two saved default groups no longer show "a, b" over group a's numbers.

Move the dashboard onto ui-common's title and description board items (was #10643) (#10642)

Summary

Verification

  • VERIFY_BASE=origin/main VERIFY_TESTS=1 bash scripts/verify.sh → === ALL PASS === (token gate: 0 undeclared).
  • On the review server, in Korean, the superadmin, project admin and member dashboards: every card has one title row in the board header, with the handle centred on the title line (handle centre and heading centre within 1px), edit mode and header controls unchanged.
  • Resize handle: a click without a drag activates it; a click elsewhere in the board ends it (the card leaves uic-board-item--active, and an arrow key afterwards no longer resizes it).
  • Moving a card right and back three times leaves its header row and the board order unchanged.

Decisions (2026-10-29)

  • The card header picker and the default settings modal select one resource group. The header shows the saved group or the default as its placeholder (the several-groups label is gone), the override compares the one group, and an older multi-group setting reads its first group. The modal label is now "Default resource group" (dashboard.settings.DefaultResourceGroup).

Ready gate (round 1)

🤖 Generated with Claude Code

Risk tier: High — AGENTS.md, pnpm-lock.yaml, pnpm-workspace.yaml, react/AGENTS.md, react/src/__generated__/AuditLogPanelScopedHistoryQuery.graphql.ts
Suggested human approvals: 2 (branch protection decides)
Reviewed by fw ready gate at 43f61a9 (round 1)

@agatha197
agatha197 added this pull request to stack #10591 October 27, 2026 02:38
@github-actions github-actions Bot added area:ux UI / UX issue. area:i18n Localization size:XL 500~ LoC labels Oct 27, 2026
@agatha197 agatha197 changed the title feat/gh 10586 superadmin cards feat(#10586): add the superadmin dashboard cards Oct 27, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 24.88% 10509 / 42234
🔵 Statements 22.02% 13877 / 63007
🔵 Functions 21.53% 1788 / 8302
🔵 Branches 17.58% 7882 / 44816
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/AgentStats.tsx 91.8% 39.62% 25% 93.84% 88, 143-163, 218-220, 167
react/src/components/MyResource.tsx 91.81% 61.42% 70% 92.2% 84-85, 126, 130, 287-303
react/src/components/MyResourceWithinResourceGroup.tsx 84.37% 67.85% 50% 84.37% 52-54, 166, 232-257
react/src/components/QuotaPerStorageVolumeDashboardItem.tsx 3.03% 0% 0% 4.34% 24-39
react/src/components/StorageStatusPanelCard.tsx 0% 0% 0% 0% 34-194
react/src/components/TotalResourceWithinResourceGroup.tsx 3.01% 0% 0% 4.42% 111-158, 179-184, 198-426
react/src/components/UserSessionsMetrics.tsx 0% 0% 0% 0% 34-322
react/src/components/DashboardPanels/DashboardEditSider.tsx 0% 0% 0% 0% 52-278
react/src/components/DashboardPanels/DashboardPanelBoard.tsx 0% 0% 0% 0% 51-154
react/src/components/DashboardPanels/PanelDetailLinkButton.tsx 100% 73.33% 100% 100%
react/src/components/DashboardPanels/PanelFrame.tsx 2.04% 0% 0% 3.57% 48-66
react/src/components/DashboardPanels/PanelSettingsHeaderControls.tsx 2.63% 0% 0% 5.4% 48-83
react/src/components/DashboardPanels/PanelSettingsModal.tsx 97.14% 53.62% 50% 97.5% 82, 145-148
react/src/components/DashboardPanels/ResourceCountPanel.tsx 3.07% 0% 0% 6.06% 33-39, 60-85
react/src/components/DashboardPanels/ResourceTablePanel.tsx 3.09% 0% 0% 5.35% 50-68, 111-149
react/src/components/DashboardPanels/boardLayout.ts 100% 100% 100% 100%
react/src/components/DashboardPanels/boardModel.ts 92.02% 87.05% 83.92% 92.17% 79-81, 206-209, 398, 419-423, 431-437
react/src/components/DashboardPanels/cardScope.ts 100% 84.21% 100% 100%
react/src/components/DashboardPanels/dashboardScope.ts 77.77% 53.84% 50% 75% 47-51
react/src/components/DashboardPanels/detailLink.ts 100% 66.66% 100% 100%
react/src/components/DashboardPanels/panelCatalog.tsx 78.57% 73.07% 90.9% 81.08% 53-57
react/src/components/DashboardPanels/panelSettingOverrides.ts 100% 96.66% 100% 100%
react/src/components/DashboardPanels/types.ts 100% 100% 100% 100%
react/src/components/DashboardPanels/useDashboardBoard.tsx 0% 0% 0% 0% 74-358
react/src/components/DashboardPanels/useResetOnLeavingPath.ts 100% 100% 100% 100%
react/src/components/DashboardPanels/cards/AuditLogPanel.tsx 4.86% 0% 0% 8.25% 54-60, 88-94, 101-241, 247-382, 388-459, 467-532, 553-635, 664-637
react/src/components/DashboardPanels/cards/DeploymentStatusPanel.tsx 6.94% 0% 0% 14.28% 40-41, 52-87, 94-131, 140-141, 150-151, 160-197, 207-214, 221-233, 256-274
react/src/components/DashboardPanels/cards/FoldersPanel.tsx 4.47% 0% 0% 8.33% 27-29, 48-98, 124-170, 178-212, 219-226, 231-249
react/src/components/DashboardPanels/cards/LongRunningSessionsPanel.tsx 10% 0% 0% 15.38% 39-45, 102-105
react/src/components/DashboardPanels/cards/PendingSessionsPanel.tsx 7.03% 0% 0% 10% 53-87, 101-122, 169-185, 285-261
react/src/components/DashboardPanels/cards/ResourceAllocationPanel.tsx 5.55% 0% 0% 10.25% 20-44, 54-78, 88-98, 108-125
react/src/components/DashboardPanels/cards/SessionList.tsx 7.86% 0% 0% 18.91% 49-51, 60-96, 105-138, 147-180, 185-192, 202, 209-211
react/src/components/DashboardPanels/cards/SessionStatusPanel.tsx 6.99% 0% 0% 12.82% 59-76, 81-99, 133-178, 185-261, 268-344, 351-363, 372-389
react/src/components/DashboardPanels/cards/UsersPanel.tsx 4.76% 0% 0% 8.62% 22-24, 42-93, 114-148, 165-172, 178-195
react/src/components/DashboardPanels/charts/TrendStat.tsx 7.31% 0% 0% 13.63% 43-96
react/src/components/DashboardPanels/memberCards/MemberCard.tsx 7.5% 0% 0% 15% 18, 41-44, 72-74
react/src/components/DashboardPanels/memberCards/MyResourcesPanel.tsx 4.44% 0% 0% 7.4% 20-54, 70-75
react/src/components/DashboardPanels/memberCards/ResourceGroupTotalPanel.tsx 2.04% 0% 0% 3.5% 34-61, 78-85
react/src/components/DashboardPanels/memberCards/ResourcePresetsPanel.tsx 2.89% 0% 0% 5.26% 24-82, 99-62
react/src/components/DashboardPanels/projectAdminCards/ResourceGroupCapacityPanel.tsx 5.88% 0% 0% 8.69% 19-45, 64-52
react/src/components/DashboardPanels/superadminCards/AgentStatsPanel.tsx 8% 0% 0% 14.28% 14-34, 39-42
react/src/components/DashboardPanels/superadminCards/AgentsPanel.tsx 3.44% 0% 0% 5.88% 23-86, 125-137
react/src/components/DashboardPanels/superadminCards/ContainerRegistriesPanel.tsx 2.5% 0% 0% 4.16% 31-69, 121-130
react/src/components/DashboardPanels/superadminCards/FailedLoginsPanel.tsx 2.63% 0% 0% 5% 28-32, 39-98, 151-93
react/src/components/DashboardPanels/superadminCards/FailuresByEntityTypePanel.tsx 3.63% 0% 0% 6.25% 26-74, 104-111
react/src/components/DashboardPanels/superadminCards/FairSharePanel.tsx 3.33% 0% 0% 5.35% 31-33, 40-97, 156-121
react/src/components/DashboardPanels/superadminCards/ResourcePoliciesPanel.tsx 3.17% 0% 0% 6.06% 16-44, 71-83
react/src/components/DashboardPanels/superadminCards/SchedulingFailuresPanel.tsx 3.3% 0% 0% 5.71% 44-47, 53-136, 231-133
react/src/components/DashboardPanels/superadminCards/TopProjectsUsagePanel.tsx 4.92% 0% 0% 8.97% 41-46, 58-89, 111-171, 178-181, 234-214
react/src/components/DashboardPanels/superadminCards/superadminCardData.ts 96.42% 66.66% 90.9% 96% 126
react/src/pages/AdminDashboardPage.tsx 0% 0% 0% 0% 17-50
Generated in workflow #2749 for commit a680c4f by the Vitest Coverage Report Action

@agatha197
agatha197 force-pushed the feat/gh-10586-superadmin-cards branch from 781d239 to 4d4797d Compare October 27, 2026 04:06
agatha197 and others added 10 commits October 27, 2026 04:54
The cards the project admin dashboard shares with the superadmin one now
take a third scope, the current domain (ADR 0012, ADR 0015 "one UI, scope
as input"), and keep the same layout:

- Session Status: 8 scopedSessionsV2(scope: {domain}) count aliases.
- Pending, Long-running and Recent Sessions: SessionList over
  scopedSessionsV2; the domain rows add Project and Resource Group columns,
  and the pending reason reads compute_session_nodes(scope_id: "domain:").
  Pending Sessions narrows to its resource group setting only when one is
  set (both pages; no setting reads every group).
- Audit Log: adminAuditLogsV2 on the superadmin page. A domain entity scope
  (scopedAuditLogsV2) returns only the domain's own children (projects,
  users, roles, resource groups: 566 rows against 35,002) and none of the
  sessions, folders or deployments in it (0 session rows against 185), so
  that card reads the whole cluster and its tooltip says so. Both queries
  render one view (stats with sparklines, table, failures-only switch).
- Deployment Status: scopedDeployments(scope: {domain}).
- Folders: scopedVFoldersV2(scope: {domain}) ready and trash counts (the
  domain has no folder limit).
- Users (moved to cards/UsersPanel): scopedUsersV2 active, inactive and
  ACTIVE role ADMIN counts.
- Resource Allocation (moved to cards/ResourceAllocationPanel):
  adminDomainResourceAllocationV2(domainName).
- i18n: the domain tooltips and the superadmin card strings, 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The superadmin dashboard (/admin/dashboard) gets its own cards next to the
shared ones; each owns its query, and range or resource group cards declare
a per-card setting.

Default board, in this order (PanelDefinition.order per page):
1. Session Status (shared; replaces the legacy Active Sessions card)
2. Pending Sessions (shared; resource group setting)
3. Scheduling Failures: adminSessionSchedulingHistories, a donut of four
   result count aliases (FAILURE, GIVE_UP, EXPIRED, NEED_RETRY; errorCode
   is null on every row of manager 26.10) and the newest attempts with the
   session (opens the drawer), project, result and message; range setting.
4. Agents (key activeAgents, replacing the legacy AgentList card): an
   agentsV2 status donut (four count aliases) and the agents with resource
   group, status, schedulable and containers.
5. Agent Statistics (agentStats, unchanged)
6. Failures by Entity Type: adminAuditLogsV2 ERROR/DENIED counts for seven
   entity types plus one "other types" alias, as a donut; range setting.
7. Audit Log (shared; adminAuditLogsV2 here)
8. Top Projects by Usage: adminProjectUsageBuckets of the domain over the
   range (periodStart after the day before) and resource group setting;
   each bucket row (project, resource group, day) as the manager recorded
   it, ordered by its CPU core-hours, never added together.
9. Fair Share: rgProjectFairShares per resource group setting, lowest
   factor first.
Then Total Resources in Resource Group, as before.

Catalog only: Long-running Sessions, Resource Allocation, Deployment
Status, Folders, Users (shared cards over the domain), Resource Groups and
Capacity, Recently Created Sessions (the member Recent Sessions card over
the domain, under its old key), Resource Policies (keypair/user/project
policy counts linking to their tabs), Keypairs and Sign-ins
(adminKeypairsV2 total and inactive, adminLoginHistoryV2 failed sign-ins
of the domain with delta and list), Container Registries and Notifications
(rules and channels with enabled counts).

- PanelDefinition.defaultHidden takes a page list and `order` places a card
  per page, so one shared definition can be default on one page and
  catalog-only on another.
- Removed: the activeSessions key (stored boards drop it through
  sanitizeBoard), SessionCountDashboardItem, RecentlyCreatedSession and
  ActiveAgents, and their fragments from the admin page query; the unused
  activeAgent.* and session.ActiveSessions strings.
- Unit tests for the scope resolver, the per-page seeding and the pure
  usage/failure helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The card title and factor column now read webui.menu.FairShare and
fairShare.FairShareFactor, so they match the Fair Share page in every
locale. The duplicate dashboard.card.FairShare / FairShareFactor keys are
gone, and FairShareTooltip uses each locale's own labels for both terms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e agent list does

The status donut above the table was squeezed to a few pixels once the
table took the card's height. The four status counts now sit in a stat row
like Session Status's, and the table is the agent list page's BAIAgentTable
(ID and endpoint, resource group, the status badge, the schedulable check
icon) with the container count added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es do

- Container Registries: the registry page's column names, the type as plain
  text and the project as a token.
- Fair Share: the Fair Share page's number format, with "(default)" beside a
  weight that is not set.
- Keypairs and Sign-ins: the login history page's BAILoginHistoryTable (time,
  result token, client IP) with the user's email added; its failed sign-in
  delta now carries the range for the hover explanation.
- Scheduling Failures: BAISchedulingHistoryNodes' created-at and result
  columns, with the session, project and reason added.

The card-only column titles that no longer render leave every locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It counted the manager's notification rules and channels, but WebUI has no
page that shows or manages them, so the numbers meant nothing and there was
nowhere to link. A stored board that still lists the card drops it, as
sanitizeBoard does with any unknown key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The status counts are drawn small and the type legend flows into two
columns when it runs out of height, so the card fits 2x2 without the extra
row this layer gave it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A card whose subject has a list page now has one arrow button at the right
end of its header, named after the destination ("View in Sessions"). The
destination is declared on the catalog entry (`detailLink`), resolved by
the board for the page's route scope, and rendered by the shared card
header. Only query keys the destination page parses are passed: the session
lists' statusCategory, the superadmin pending tab and its resource group,
the agent list's status, and the users and environment pages' tab. Cards
without a list page (failures by entity type, top projects by usage, the
audit logs, scheduling failures, resource and start cards) get no button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@agatha197
agatha197 force-pushed the feat/gh-10586-superadmin-cards branch from 4d4797d to 7930fe6 Compare October 27, 2026 04:59

@agatha197 agatha197 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready-gate agent review — 11 findings — 8 Important, 3 Nit, 0 Pre-existing. The summary comment on this PR lists every finding and its outcome.

Comment thread react/src/components/DashboardPanels/PanelFrame.tsx
Comment thread react/src/components/DashboardPanels/boardModel.ts Outdated
Comment thread react/src/components/DashboardPanels/cards/AuditLogPanel.tsx
Comment thread react/src/components/DashboardPanels/cards/PendingSessionsPanel.tsx Outdated
Comment thread react/src/components/DashboardPanels/superadminCards/TopProjectsUsagePanel.tsx Outdated
Comment thread react/src/components/DashboardPanels/useDashboardBoard.tsx
Comment thread react/src/components/DashboardPanels/useDashboardBoard.tsx
Comment thread scripts/migration-gates/token-gate.allowlist.json Outdated
@agatha197

agatha197 commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

11 findings — 8 Important, 3 Nit, 0 Pre-existing

Round 1 — 43f61a9

# Tag File:line Finding Outcome
1 Important react/src/components/DashboardPanels/PanelFrame.tsx:86 Resource group and range pickers now render in every card header in view mode, contradicting ADR 0018 ('Edit mode only'; card headers in view mode show no setting values), and the ADR is not updated in this PR. fixed 69b607a (ADR 0018 in #10592)
2 Nit react/src/components/DashboardPanels/boardModel.ts:317 activeSessions (shipped on main in admin_dashboard_board_items) is dropped without a RENAMED_PANEL_KEYS entry, while the listed keypairsLogins rename never left this stack. fixed db083e5
3 Important react/src/components/DashboardPanels/cards/AuditLogPanel.tsx:94 On the superadmin page the audit log card (and FailuresByEntityTypePanel) read cluster-wide adminAuditLogsV2, while ADR 0012 and ADR 0018 say this page reads the current domain; the deviation is recorded only in a code comment, not in an ADR. fixed 69b607a (ADR 0018 in #10592)
4 Important react/src/components/DashboardPanels/cards/PendingSessionsPanel.tsx:294 Pending Sessions (and Top Projects by Usage, TopProjectsUsagePanel.tsx:217) read raw panel.settings?.resourceGroups instead of vars.resourceGroup, so with no saved setting they count every resource group while the header picker shows the current group as the card's value (ADR 0018 'Defaults'). fixed 28fe34d, 9ef81a5
5 Important react/src/components/DashboardPanels/memberCards/ResourceGroupTotalPanel.tsx:66 The header Used/Free toggle never reaches the body: TotalResourceWithinResourceGroup reads useControllableValue(props) with the default valuePropName: 'value', so the displayType prop is ignored and the bars stay on 'free' (and displayType is spread onto the root BAIFlex DOM node). fixed 4cc4d92
6 Important react/src/components/DashboardPanels/superadminCards/AgentStatsPanel.tsx:37 AgentStatsPanel now runs its own useLazyLoadQuery with only a Suspense boundary; custom cards get no BAIBoardItemErrorBoundary from contentOf, so a query error escapes the card. fixed f5607f7
7 Important react/src/components/DashboardPanels/superadminCards/FairSharePanel.tsx:46 The Fair Share table's page offset is not reset when the resource group changes (ResourceGroupFairShares is not keyed by it), and the new header picker makes that change routine. fixed 31d78ac
8 Important react/src/components/DashboardPanels/superadminCards/TopProjectsUsagePanel.tsx:105 'Top projects' are ranked client-side by CPU from an arbitrary 200 buckets: every row shares the same periodStart, so PERIOD_START DESC does not pick the heaviest ones, and the 'Showing the 200 newest' note is wrong. fixed 9ef81a5
9 Nit react/src/components/DashboardPanels/useDashboardBoard.tsx:158 removePanel and resetLayout leave header overrides in panelSettingOverridesAtom; built-in cards reuse their key as id, so a removed and re-added card comes back with the old header pick. fixed 3590ff1
10 Important react/src/components/DashboardPanels/useDashboardBoard.tsx:251 A header pick that makes a card's query fail cannot be undone: MemberCard's BAIBoardItemErrorBoundary wraps PanelFrame and has no reset key, so its fallback drops the header picker and the reset button. fixed e94c544
11 Nit scripts/migration-gates/token-gate.allowlist.json:10 The new --board-item-padding-top allowlist entry says BAIBoard.css reads it, but no file in the tree references that token any more, so it is a stale exemption with a false reason. fixed ac3a1c5

Security review: 0 findings

Posted inline: 11 · already inline from this round: 0 · table only (outside the diff): 0 · repeats of an earlier round dropped: 0 · Nits over the cap of 3 dropped: 0 · not posted (no file:line, or style-only): 0

agatha197 and others added 12 commits October 30, 2026 07:54
… refresh

BAIBoardItemErrorBoundary takes resetKeys now. MemberCard resets it on
the card's fetch key, and the resource-group cards also on their project
and resource group, so a refresh, the auto refresh or a new resource
group retries a card that failed once instead of leaving the error until
a page reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e reach the bars

TotalResourceWithinResourceGroup read its display type through
useControllableValue's default 'value' prop, so the header's Used/Free
toggle never reached the bars and displayType leaked onto the root DOM
node. It now reads displayType and keeps the display-type props off the
DOM. The card also says when no resource group is selected, resets its
boundary on refresh and resource group, and keeps the header picks in
its failed state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uery failure in its card

AgentStatsPanel runs its own query now, and custom cards get no error
boundary from the board, so a failed query took down the dashboard.
It is wrapped in BAIBoardItemErrorBoundary, reset on refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p in Pending Sessions

The card read the raw saved setting, so with none saved it listed every
resource group while the header showed the current one. It reads the
card's effective resource group (vars.resourceGroup) now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ole day

Usage buckets order by period start only, so the first 200 rows of the
latest day were an arbitrary subset. The card now reads every bucket of
that day, 200 per page (up to 5000), before ranking by CPU, and the note
says how many rows the ranking used when the cap is hit. It also reads
the card's effective resource group instead of the raw saved setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… member card

MemberCard's error fallback showed only the title, so a header pick that
made the query fail could not be undone. The fallback keeps the header
controls (and the reset button), and the boundary resets when the
effective settings change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e on a new resource group

The table is keyed by resource group and domain, so a header pick no
longer queries the previous group's page offset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removing a card, deactivating it from the sider or resetting the layout
now clears its in-memory header override, so a re-added card starts
from its saved settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
keypairsLogins never shipped, and main's activeSessions lived only in
the localStorage layout that #10590 no longer migrates, so no stored
app-config board can hold either key. The rename machinery goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…owlist entry

Nothing in the tree reads --board-item-padding-top any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The superadmin audit cards read adminAuditLogsV2 cluster-wide; the
decision is recorded in ADR 0018 by the cascade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
agatha197 and others added 2 commits October 30, 2026 08:24
Moves @lablup/ui-common and @lablup/ui-common-cli to
0.2.0-alpha.20.canary-20261029050354-1feb007cd, which carries
lablup/ui-common#107 (needed by #10496). No codemods run between the two
canaries; the AGENTS.md ui-common blocks are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
…Tooltip

Pin @lablup/ui-common to 0.2.0-alpha.20.canary-20261030092430-1f45b2b9a,
which carries lablup/ui-common#115: Stat takes a deltaTooltip anchored to
the delta itself. TrendStat no longer wraps the whole Stat in a Tooltip,
forces a tabIndex and fit-content width on it, or moves the sparkline out
of media to keep the two tooltips apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n Localization area:ux UI / UX issue. size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Superadmin dashboard cards: all-scope, cluster and audit visuals

2 participants