333 lines
24 KiB
Markdown
333 lines
24 KiB
Markdown
# Cluster 05 — Dashboard
|
||
|
||
Audited docs: `docs/DashboardInterfaceDesign.md`, `docs/GatewayDashboardDesign.md`
|
||
Verified against: `src/ZB.MOM.WW.MxGateway.Server/Dashboard/**`, `src/ZB.MOM.WW.MxGateway.Server/wwwroot/**`
|
||
Audit date: 2026-06-03
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 39–57
|
||
CLAIM / "The shell does not use a sidebar. A horizontal navigation bar is enough…" with a `<div class="dashboard-shell">` / `<nav class="navbar navbar-expand-lg bg-body border-bottom dashboard-navbar">` HTML skeleton
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor:7 — layout now delegates to `<ThemeShell Product="MXAccess Gateway" Accent="#2f5fd0">` with `NavRailSection`/`NavRailItem` kit components; there is no local navbar, no `dashboard-shell` class, no `dashboard-navbar` class, and no `container-fluid` content area anywhere in the codebase
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Replace the HTML skeleton and prose description with the current ThemeShell side-rail pattern (`<ThemeShell>` → `<Nav>` → `<NavRailSection>` / `<NavRailItem>`). Update the note about "horizontal navigation bar" — the nav is now a collapsible side rail managed by the ZB.MOM.WW.Theme kit.
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 115–123
|
||
CLAIM / Navigation uses `NavLink` and labels: `Overview`, `Sessions`, `Workers`, `Events`, `Settings`
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/MainLayout.razor:9–23 — actual nav items are `Dashboard` (not "Overview"), `Sessions`, `Workers`, `Events`, `Alarms`, `Repository`, `Browse`, `API Keys`, `Settings`; the old flat list of five labels has been replaced by three grouped NavRailSections (`Runtime`, `Galaxy`, `Admin`) with eight leaf items
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Update the nav-label list to match the current ThemeShell Nav: Dashboard / [Runtime: Sessions, Workers, Events, Alarms] / [Galaxy: Repository, Browse] / [Admin: API Keys, Settings].
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 63–79
|
||
CLAIM / Four local CSS tokens: `--mxgw-surface: #f7f8fa`, `--mxgw-border: #d8dee6`, `--mxgw-ink-muted: #667085`, `--mxgw-accent: #146c64`
|
||
CLAIM_TYPE / config-key
|
||
VERDICT / wrong
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/wwwroot/css/site.css:1–7 — no `--mxgw-*` tokens are defined anywhere in `site.css`; the file's own header states "Every colour … resolves to a theme.css token — no hard-coded hex." All colour expressions in site.css use theme kit tokens: `var(--card)`, `var(--rule)`, `var(--ink)`, `var(--ink-faint)`, `var(--accent)`, `var(--accent-deep)`, `var(--bad)`, `var(--bad-bg)`, etc.
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Remove the `--mxgw-*` token table entirely. Replace with a note that the dashboard's view-layer CSS (`site.css`) resolves all colour via the `ZB.MOM.WW.Theme` kit tokens (`--card`, `--rule`, `--ink`, `--ink-faint`, `--accent`, `--accent-deep`, etc.) and defines no local colour tokens.
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 87–97
|
||
CLAIM / Page headings use `1.35rem`, weight `650`. Metric labels use `uppercase text at .78rem` and weight `650`. Metric values use `1.7rem`, weight `700`, and the accent color.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / site.css:30–31 (page h1: `font-size: 1.15rem; font-weight: 600`), site.css:64–65 (agg-label: `font-size: 0.68rem; font-weight: 600`), site.css:76–77 (agg-value: `font-size: 1.5rem; font-weight: 600; color: var(--ink)`) — page headings are `1.15rem/600` (not `1.35rem/650`); metric values are `1.5rem/600` in `var(--ink)` (not `1.7rem/700` in accent color)
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Update typography table: h1 → 1.15rem/600, agg-label → 0.68rem/600/uppercase, agg-value → 1.5rem/600/var(--ink). Note metric values render in ink (not the accent colour) per the post-theme-migration design.
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 99–111
|
||
CLAIM / Page content has `1.25rem` padding on desktop and `.75rem` on small screens. Metric grids use `.75rem` gaps. Cards and empty states use Bootstrap's small radius `.375rem`. Content sections start with a top border and `1rem` top padding.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / site.css:272–279 (`@media (max-width: 700px)` sets `.page { padding: 0.85rem }`; no 1.25rem desktop padding rule exists in site.css). site.css:59 (`border-radius: 8px` for `.agg-card`, not `.375rem`). site.css:59 (`box-shadow: none` but no top-border-only sections — `.dashboard-section` at line 91–100 is a raised card with `border: 1px solid var(--rule); border-radius: 8px`).
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Update spacing table: small-screen padding is 0.85rem; cards use 8px radius; sections are full-border raised cards (not top-border-only dividers).
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 153–168
|
||
CLAIM / `metric-grid` uses `repeat(auto-fit, minmax(12rem, 1fr))` and `compact` variant uses `minmax(10rem, 1fr)`
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / site.css:49 (`grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr))`) and site.css:54 (`repeat(auto-fill, minmax(10rem, 1fr))`) — base grid is `auto-fill, 11rem` (not `auto-fit, 12rem`); `auto-fill` not `auto-fit`
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Update code block: base grid is `repeat(auto-fill, minmax(11rem, 1fr))`; compact stays `minmax(10rem, 1fr)`.
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 191–200
|
||
CLAIM / Status uses Bootstrap badge classes (`text-bg-success`, `text-bg-info`, `text-bg-secondary`, `text-bg-danger`, `text-bg-light text-dark border`) with mapping: `Closed` → `text-bg-secondary`; `Creating`/`StartingWorker`/`WaitingForPipe`/`InitializingWorker`/`Closing` → `text-bg-info`
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / wrong
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Shared/StatusBadge.razor:1–16 — `StatusBadge` is now a thin adapter over the kit's `<StatusPill State="…">` component; no Bootstrap `text-bg-*` classes are used at all. State mapping uses `StatusState.Ok/Warn/Bad/Idle`. `Closed` falls through to `StatusState.Idle` (no `text-bg-secondary`). `Closing` is mapped to `StatusState.Warn` (not info). New states `Stale`, `Degraded`, `Active`, `Unavailable` are handled; `Unknown state` → `StatusState.Idle` (was `text-bg-light text-dark border`).
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Replace the badge-class table with the current `StatusState` enum vocabulary: Ok (`Ready`, `Healthy`, `Active`); Warn (`Creating`, `StartingWorker`, `WaitingForPipe`, `InitializingWorker`, `Closing`, `Stale`, `Degraded`); Bad (`Faulted`, `Unavailable`); Idle (everything else including `Closed`). Note that visual rendering is owned by the ZB.MOM.WW.Theme `StatusPill` component.
|
||
|
||
---
|
||
|
||
DOC / DashboardInterfaceDesign.md / LINES / 229–245
|
||
CLAIM / Responsive breakpoint CSS: `.dashboard-content { padding: .75rem }` at `max-width: 700px`
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / site.css:272–279 — the responsive rule targets `.page { padding: 0.85rem }` (not `.dashboard-content`; not `.75rem`)
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Update code block to `@media (max-width: 700px) { .page { padding: 0.85rem; } … }`.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 78–110
|
||
CLAIM / Component tree lists `Layout/DashboardLayout.razor` and `Shared/StatusBadge.razor` as standalone status component
|
||
CLAIM_TYPE / path
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Layout/ contains only `MainLayout.razor` and `LoginLayout.razor`; there is no `DashboardLayout.razor`. `StatusBadge.razor` still exists but is now a thin wrapper delegating to the kit's `StatusPill`; the doc's tree implies it is a standalone Bootstrap-badge component.
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / In the component tree rename `DashboardLayout.razor` → `MainLayout.razor` and `LoginLayout.razor`. Add a note that `StatusBadge` delegates to `ZB.MOM.WW.Theme`'s `StatusPill`. Also add `BrowseTreeNodeView.razor` and `ConfirmDialog.razor` which are present in code but absent from the tree.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 507–510
|
||
CLAIM / "The dashboard serves Bootstrap 5.3.3 assets from `src/ZB.MOM.WW.MxGateway.Server/wwwroot/lib/bootstrap/` and local layout/status styling from `src/ZB.MOM.WW.MxGateway.Server/wwwroot/css/dashboard.css`."
|
||
CLAIM_TYPE / path
|
||
VERDICT / wrong
|
||
EVIDENCE / find shows `wwwroot/css/site.css` exists; there is no `dashboard.css` under wwwroot. Bootstrap 5.3.3 is confirmed (bootstrap.min.css header). App.razor:8–9 loads `/css/site.css`, not `/css/dashboard.css`. Additionally the denied-page renderer at DashboardEndpointRouteBuilderExtensions.cs:172–173 also loads theme kit CSS: `/_content/ZB.MOM.WW.Theme/css/theme.css` and `/_content/ZB.MOM.WW.Theme/css/layout.css`.
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Change `dashboard.css` → `site.css` throughout. Add that App.razor also loads `<ThemeHead />` (which injects the theme kit's CSS) and `<ThemeScripts />`. Note the denied-page also pulls `/_content/ZB.MOM.WW.Theme/css/theme.css` and `/_content/ZB.MOM.WW.Theme/css/layout.css` directly.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 406–428
|
||
CLAIM / "`DashboardAuthenticator` binds against `MxGateway:Ldap` … using `Novell.Directory.Ldap.NETStandard`"
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs:1–6 — imports are `ZB.MOM.WW.Auth.Abstractions.Ldap`, `ZB.MOM.WW.Auth.Abstractions.Roles`, `ZB.MOM.WW.Auth.AspNetCore`; the csproj references `ZB.MOM.WW.Auth.Ldap 0.1.2`, not Novell. DashboardServiceCollectionExtensions.cs:35 calls `services.AddZbLdapAuth(configuration, "MxGateway:Ldap")`. `Novell.Directory.Ldap.NETStandard` is not referenced in the csproj.
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Replace "using `Novell.Directory.Ldap.NETStandard`" with "using the shared `ZB.MOM.WW.Auth.Ldap` package (`ILdapAuthService`), registered via `AddZbLdapAuth`".
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 420–422
|
||
CLAIM / Cookie name is `__Host-MxGatewayDashboard`
|
||
CLAIM_TYPE / config-key
|
||
VERDICT / wrong
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationDefaults.cs:38 — `public const string CookieName = "MxGatewayDashboard"` (no `__Host-` prefix). The code comment explains the `__Host-` prefix is not used; the cookie path is `/` set explicitly at DashboardServiceCollectionExtensions.cs:72.
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Change `__Host-MxGatewayDashboard` to `MxGatewayDashboard` everywhere in the auth section. Note that the cookie name is configurable via `MxGateway:Dashboard:CookieName`.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 289–306
|
||
CLAIM / Browse page is at `/dashboard/browse`; tree built by `DashboardBrowseTreeBuilder` from `IGalaxyHierarchyCache.Current`; subscription panel is the explicit opt-in for tag values
|
||
CLAIM_TYPE / path
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/BrowsePage.razor:1 — route is `@page "/browse"` (not `/dashboard/browse`). `DashboardBrowseTreeBuilder` is found at DashboardBrowseModel.cs:66 as a static class. Browse uses `IGalaxyHierarchyCache` (injected via `IDashboardBrowseService`) confirmed at BrowsePage.razor:3.
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Fix route to `/browse` (not `/dashboard/browse`). The tree builder name is accurate but clarify it is a static class inside `DashboardBrowseModel.cs`.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 307–318
|
||
CLAIM / Alarms page is at `/dashboard/alarms`; defaults to showing unacknowledged `Active` alarms; Alarms page reads via `IDashboardLiveDataService`
|
||
CLAIM_TYPE / path
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/AlarmsPage.razor:1 — route is `@page "/alarms"` (not `/dashboard/alarms`). The claim that alarm data comes from "gateway's always-on central monitor" via `IGatewayAlarmService.CurrentAlarms` is contradicted by the implementation: AlarmsPage.razor:3 injects `IDashboardLiveDataService` and calls `LiveData.QueryAlarmsAsync` in a poll loop — not `IGatewayAlarmService.CurrentAlarms` directly.
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Fix route to `/alarms`. Correct the live data source description: the Alarms page uses `IDashboardLiveDataService.QueryAlarmsAsync` (a polling loop every 3 s), not a direct read of `IGatewayAlarmService.CurrentAlarms`.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 337–345
|
||
CLAIM / API keys page is at `/dashboard/apikeys`
|
||
CLAIM_TYPE / path
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/ApiKeysPage.razor:1 — route is `@page "/apikeys"` (not `/dashboard/apikeys`)
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Fix route to `/apikeys`.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 387–391
|
||
CLAIM / "Every management action appends an `api_key_audit` entry (`dashboard-create-key`, `dashboard-rotate-key`, `dashboard-revoke-key`, `dashboard-delete-key`) with the key id and the caller's remote address."
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs:59 — "both rows land in the canonical audit_event store"; DashboardApiKeyManagementService.cs:69,113,156,201 — action strings `dashboard-create-key`, `dashboard-rotate-key`, `dashboard-revoke-key`, `dashboard-delete-key` are confirmed. However the table used is `audit_event` (via `IAuditWriter`), not `api_key_audit`. Comments explicitly state "the library's `api_key_audit` table is left in place but UNUSED".
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Change "appends an `api_key_audit` entry" to "appends an `audit_event` entry (via `IAuditWriter`)". The `api_key_audit` table is no longer used for dashboard actions.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 68–69
|
||
CLAIM / Galaxy page is at `/galaxy`; "summary is fed by `GalaxySummaryCache`, which is refreshed off the request path by `GalaxySummaryRefreshService` on the `MxGateway:Galaxy:DashboardRefreshIntervalSeconds` cadence"
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / `GalaxySummaryCache` and `GalaxySummaryRefreshService` do not exist in the codebase. The actual implementation uses `IGalaxyHierarchyCache` (GalaxyHierarchyCache.cs) refreshed by `GalaxyHierarchyRefreshService` (Galaxy/GalaxyHierarchyRefreshService.cs:19), driven by `GalaxyRepositoryOptions.DashboardRefreshIntervalSeconds` under config key `MxGateway:Galaxy:DashboardRefreshIntervalSeconds` (confirmed by appsettings.json:74). Galaxy page route `/galaxy` is confirmed.
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Replace `GalaxySummaryCache` / `GalaxySummaryRefreshService` with `GalaxyHierarchyCache` / `GalaxyHierarchyRefreshService`. Config key `MxGateway:Galaxy:DashboardRefreshIntervalSeconds` is correct.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 160–170
|
||
CLAIM / "Updates flow over three SignalR hubs … `DashboardSnapshotPublisher` (BackgroundService consuming `IDashboardSnapshotService.WatchSnapshotsAsync`)"; hub table row for EventsHub: "`DashboardEventBroadcaster` invoked by `EventStreamService` for each event it forwards to a gRPC client"
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / accurate
|
||
EVIDENCE / Dashboard/Hubs/DashboardSnapshotPublisher.cs confirms BackgroundService consuming `WatchSnapshotsAsync`. Dashboard/Hubs/EventsHub.cs:6–17 comment: "The publisher side is intentionally a follow-up. Today the dashboard's per-session event view is fed by the snapshot hub … Once a dedicated MxEvent broadcaster lands, this hub's group convention is what it will publish to." — so the doc's description of `DashboardEventBroadcaster` being active is aspirational; it currently exists as a stub.
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Flag only — add a note that `EventsHub`'s broadcaster is a planned follow-up; today the per-session events view in `SessionDetailsPage` connects to `/hubs/events` directly and `DashboardEventBroadcaster` exists but the EventStreamService hook is not yet wired. The hub routing convention is stable.
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 171–177
|
||
CLAIM / "`DashboardPageBase` … seeds `Snapshot` synchronously from `IDashboardSnapshotService.GetSnapshot()` … and calls `InvokeAsync(StateHasChanged)` on every `SnapshotUpdated` push. SignalR's `WithAutomaticReconnect` handles transient disconnects."
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / accurate
|
||
EVIDENCE / Dashboard/Components/DashboardPageBase.cs:37–78 — `GetSnapshot()` seed on line 37, hub `On<DashboardSnapshot>` calls `InvokeAsync(StateHasChanged)` on line 65. DashboardHubConnectionFactory.cs:36 — `.WithAutomaticReconnect()` confirmed.
|
||
CODE_AREA / dashboard.hub
|
||
SEVERITY / low
|
||
PROPOSED_FIX / flag only
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 559–577
|
||
CLAIM / "Initial Implementation Slice … 2. local Bootstrap static assets."
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / stale
|
||
EVIDENCE / App.razor:7–8 — `<ThemeHead />` is loaded before `/css/site.css`; ThemeScripts at line 15. The theme kit (`ZB.MOM.WW.Theme 0.2.0`) is now the primary asset provider via `/_content/ZB.MOM.WW.Theme/`. The "local Bootstrap static assets" description is no longer the full picture — Bootstrap is still vendored locally but the theme kit adds additional CSS/JS layers. DashboardEndpointRouteBuilderExtensions.cs:172–173 directly references `/_content/ZB.MOM.WW.Theme/css/theme.css` and `/_content/ZB.MOM.WW.Theme/css/layout.css`.
|
||
CODE_AREA / dashboard.css
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Update item 2 to: "local Bootstrap static assets plus `ZB.MOM.WW.Theme` kit (PackageReference `0.2.0`) providing theme CSS, layout CSS, and JS via `<ThemeHead />` / `<ThemeScripts />`".
|
||
|
||
---
|
||
|
||
DOC / GatewayDashboardDesign.md / LINES / 463–465
|
||
CLAIM / "Two environmental bypasses … `MxGateway:Authentication:Mode = Disabled` authorizes every request"
|
||
CLAIM_TYPE / config-key
|
||
VERDICT / unverifiable
|
||
EVIDENCE / No code path for `MxGateway:Authentication:Mode` was found in Dashboard/ — search returned no matches. The `AllowAnonymousLocalhost` bypass is confirmed at DashboardAuthorizationHandler.cs (referenced from DashboardAuthorizationRequirement). The global Auth mode bypass may live in GatewayOptions outside the dashboard cluster.
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Cross-check against GatewayOptions and the auth middleware — if this config key was removed or renamed, update the doc. If it lives outside dashboard code, add a cross-reference.
|
||
|
||
---
|
||
|
||
## Gap findings (code behavior undocumented)
|
||
|
||
DOC / gap
|
||
LINES / n/a
|
||
CLAIM / `Login.razor` is a Blazor page (`@page "/login"`) using `LoginLayout` and the kit's `<LoginCard>` component. GET /login is served by this Blazor page, not a static HTML form. POST /login is a minimal-API endpoint.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / gap
|
||
EVIDENCE / Dashboard/Components/Pages/Login.razor:1–27; DashboardEndpointRouteBuilderExtensions.cs:27–36
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Add to the auth section: "GET `/login` is served by the Blazor `Login.razor` page (using the shared kit's `<LoginCard>`); the page is `[AllowAnonymous]` and uses `LoginLayout` (no side rail). POST `/login` remains a minimal-API endpoint."
|
||
|
||
---
|
||
|
||
DOC / gap
|
||
LINES / n/a
|
||
CLAIM / `StatusBadge.razor` now maps `Closed` → `StatusState.Idle` (not `text-bg-secondary`); adds `Stale`, `Degraded` → Warn; adds `Active` → Ok; adds `Unavailable` → Bad. None of these new states are documented.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / gap
|
||
EVIDENCE / Dashboard/Components/Shared/StatusBadge.razor:10–14
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Document the full current state-to-StatusState mapping including `Active`, `Stale`, `Degraded`, `Unavailable`.
|
||
|
||
---
|
||
|
||
DOC / gap
|
||
LINES / n/a
|
||
CLAIM / `ZB.MOM.WW.Theme 0.2.0` is a PackageReference and provides `ThemeShell`, `ThemeHead`, `ThemeScripts`, `NavRailSection`, `NavRailItem`, `StatusPill`, `LoginCard` components. This dependency is not mentioned in either dashboard doc.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / gap
|
||
EVIDENCE / ZB.MOM.WW.MxGateway.Server.csproj (PackageReference ZB.MOM.WW.Theme Version=0.2.0); MainLayout.razor; App.razor; Login.razor
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / high
|
||
PROPOSED_FIX / Add a "Theme Kit" section to GatewayDashboardDesign.md (and update DashboardInterfaceDesign.md) documenting the ZB.MOM.WW.Theme dependency, which components it provides, and that the kit owns the shell frame, nav rail, login card, status pill rendering, and base CSS tokens.
|
||
|
||
---
|
||
|
||
DOC / gap
|
||
LINES / n/a
|
||
CLAIM / `DashboardOptions` has a `CookieName` override property (`MxGateway:Dashboard:CookieName`) and a `RequireHttpsCookie` flag. Neither is mentioned in the Configuration section of GatewayDashboardDesign.md.
|
||
CLAIM_TYPE / config-key
|
||
VERDICT / gap
|
||
EVIDENCE / src/ZB.MOM.WW.MxGateway.Server/Configuration/DashboardOptions.cs; DashboardServiceCollectionExtensions.cs:87–97
|
||
CODE_AREA / dashboard.login
|
||
SEVERITY / medium
|
||
PROPOSED_FIX / Add `CookieName` and `RequireHttpsCookie` to the effective-configuration JSON block and the configuration section prose.
|
||
|
||
---
|
||
|
||
DOC / gap
|
||
LINES / n/a
|
||
CLAIM / `SessionsPage` and `WorkersPage` both render admin `Close`/`Kill` action buttons (with `ConfirmDialog`), not only `SessionDetailsPage` as the doc implies. The `ConfirmDialog` shared component (`Shared/ConfirmDialog.razor`) is not listed in the component tree.
|
||
CLAIM_TYPE / behavior-rule
|
||
VERDICT / gap
|
||
EVIDENCE / Dashboard/Components/Pages/SessionsPage.razor:31–37 (ConfirmDialog usage); Dashboard/Components/Shared/ConfirmDialog.razor (file exists)
|
||
CODE_AREA / dashboard.theme
|
||
SEVERITY / low
|
||
PROPOSED_FIX / Add `ConfirmDialog.razor` to the Shared/ component tree. Note admin controls appear on Sessions list and Workers list pages, not only SessionDetailsPage.
|
||
|
||
---
|
||
|
||
## Summary
|
||
|
||
| Verdict | Count |
|
||
|---------|-------|
|
||
| accurate | 2 |
|
||
| stale | 11 |
|
||
| wrong | 4 |
|
||
| unverifiable | 1 |
|
||
| gap | 6 |
|
||
|
||
| Severity | Count |
|
||
|----------|-------|
|
||
| high | 7 |
|
||
| medium | 9 |
|
||
| low | 8 |
|
||
|
||
## High-severity findings
|
||
|
||
- **Layout: no horizontal navbar** — Both docs describe a horizontal top navbar with `dashboard-shell`/`dashboard-navbar`/`container-fluid` classes. The actual layout is a `ZB.MOM.WW.Theme` `ThemeShell` side-rail with `NavRailSection`/`NavRailItem` components. The HTML skeleton in DashboardInterfaceDesign.md is obsolete.
|
||
|
||
- **Nav labels wrong** — DashboardInterfaceDesign.md lists five flat labels (Overview/Sessions/Workers/Events/Settings). Actual nav has eight items in three groups (Runtime, Galaxy, Admin) and the home link is labelled "Dashboard" not "Overview".
|
||
|
||
- **CSS tokens do not exist** — DashboardInterfaceDesign.md documents four `--mxgw-*` custom CSS properties. None exist in `site.css`; all colour resolves through ZB.MOM.WW.Theme kit tokens.
|
||
|
||
- **StatusBadge uses Bootstrap `text-bg-*` classes** — DashboardInterfaceDesign.md documents a Bootstrap badge mapping. `StatusBadge` now delegates to the kit's `StatusPill` with `StatusState` enum; no `text-bg-*` classes are used.
|
||
|
||
- **`dashboard.css` does not exist** — GatewayDashboardDesign.md refers to `wwwroot/css/dashboard.css` as the local stylesheet. The file is `wwwroot/css/site.css`.
|
||
|
||
- **Cookie name wrong** — GatewayDashboardDesign.md states cookie name `__Host-MxGatewayDashboard`. Actual default is `MxGatewayDashboard` (no `__Host-` prefix).
|
||
|
||
- **ZB.MOM.WW.Theme dependency undocumented** — Neither doc mentions the theme kit package, its components (`ThemeShell`, `LoginCard`, `StatusPill`, etc.) or its CSS token system. This is the single most architecturally significant post-migration gap.
|