Files
scadaproj/components/ui-theme/GAPS.md
T
Joseph Doherty 3dd7aa40ff docs: publish LocalDb 0.1.0 to the feed + reconcile component status against verified state
Publishes the three ZB.MOM.WW.LocalDb packages to the Gitea feed (restore-verified
from a scratch consumer) and adds the build/push.sh the other shared libs already have.

The status prose across CLAUDE.md, README.md and components/*/GAPS.md had drifted from
reality, so it was re-derived from the feed listing and the actual PackageReferences +
registration calls on each consumer's default branch rather than from prior claims.
Five claims were false: Health "not yet adopted" (all four apps wire MapZbHealth),
GalaxyRepository's mxaccessgw adoption "a follow-on" (its Server wires
AddZbGalaxyRepository), Configuration "not yet pushed", Secrets G-8 "not yet
committed", and Theme pinned at 0.2.0 (all four are on 0.3.1). Every doc also said
"three apps" while HistorianGateway is a fourth consumer of seven libs, and all
eight libraries' test counts were stale (re-ran each suite; all green).

Surfaces one previously unrecorded gap: Secrets source is at 0.1.3 with KEK rotation
committed, but the feed tops out at 0.1.2, so no app can consume rotation until it
is published.

Health and observability divergence tables are labelled historical, not re-verified —
the libraries are proven wired, but per-app probe coverage vs spec was not re-walked.

Claude-Session: https://claude.ai/code/session_01BL2Vu1ESDQ9SCN4gVKkdts
2026-07-18 03:06:49 -04:00

8.5 KiB
Raw Blame History

UI Theme — gaps & adoption backlog

Divergence of each project from spec/SPEC.md, and the ordered backlog to reach adoption of the ZB.MOM.WW.Theme shared RCL. Status legend: gap · 🟡 partial · matches.

Current state (verified 2026-07-18): the kit has moved on from the 0.2.0 this banner describes — the Gitea feed carries 0.2.0, 0.2.1, 0.3.0, 0.3.1, and all four apps are pinned to 0.3.1 (HistorianGateway is a fourth consumer this file predates). The 0.3.0/0.3.1 nav/aria/login fixes are recorded in themeissues.md, not here. Library suite: 48 bUnit tests, green 2026-07-18. History below is accurate for the original cutover.

ADOPTED 2026-06-03 (local-only). Backlog #2#4 implemented across all three apps on each repo's feat/adopt-zb-theme branch — full canonical cutover (SPEC §7): <ThemeHead/>/<ThemeScripts/>, thin MainLayout<ThemeShell> + NavRailItem/NavRailSection, per-app theme.css/IBM-Plex fonts/ nav-state.js deleted, <LoginCard> sign-in, and StatusPill (OtOpcUa's dead StatusBadge deleted; MxGateway's StatusBadge redirected to a thin StatusPill adapter; inline domain .chip-* kept as page content per §6). Library first enhanced to 0.2.0 — nav-expand persistence promoted INTO the kit (NavRailSection.Keydata-nav-key + a localStorage nav-state.js enhancer emitted by a new <ThemeScripts/>), so all three apps get uniform persistence from one source (OtOpcUa's bespoke cookie/JS-interop nav island retired). 0.2.0 published to the Gitea feed; 44 bUnit tests. MxGateway additionally gained a net-new Blazor <LoginCard> /login page reusing its existing hardened POST /login endpoint (antiforgery + SanitizeReturnUrl + SignInAsync preserved). Every task spec+code reviewed (high-risk via serial spec→code; the MxGateway login via an Opus security review), then fast-forward-merged into each repo's local default and PUSHED to origin (gitea) 2026-06-03 (in sync; feat/* kept locally): OtOpcUa master@11de14d, ScadaBridge main@58352a6, MxGateway main@73e54e2. Plan: docs/plans/2026-06-03-ui-theme-adoption*.md. The /🟡 cells below describe the PRE-adoption divergence (kept for history).

Post-adoption CSS prune (2026-06-03, branch chore/theme-css-prune per app). An audit found each app's kept site.css still carried the old shell CSS the kit now owns — broader than first logged. Pruned: OtOpcUa shed a near-verbatim copy of the kit's layout.css (.app-shell/.side-rail/.rail-link/ .rail-foot/.login-*) plus dead #sidebar-collapse (kit emits #theme-rail) and .rail-eyebrow-chevron (167 lines), keeping only app-only .rail-eyebrow + .chip-alert/.chip-caution; ScadaBridge shed the dead .sidebar/.nav-link/.nav-section-toggle block (95), keeping #reconnect-modal/.script-editor-modal; MxGateway shed the dead .sidebar block + orphaned .dashboard-login/.login-card (106), keeping .app-bar (still used by /denied) + the .chip override. Each verified unreferenced before removal; all three build clean (0 warn/0 err). OtOpcUa's copy was the notable one — it overrode the kit, not just dead code. Still deferred: a kit-side layout.css calc(100vh - 3.3rem) review; and ScadaBridge's Host consumes the kit only transitively via CentralUI (no direct PackageReference) — builds green, but an implicit dependency.

Feed note: the same audit re-confirmed ZB.MOM.WW.Theme 0.2.0 is genuinely on the Gitea feed (registration count:1, package base versions:["0.2.0"], search totalHits:1) — the publish was real, not optimism.


Divergence vs spec

§1 Design tokens — theme.css

Item OtOpcUa MxAccessGateway ScadaBridge
Tokens identical to canonical identical identical identical
File maintained in one place (RCL) own copy own copy own copy
Font path url('../fonts/…') url('fonts/…')latent 404 🟡 url('/fonts/…') — absolute, not portable url('../fonts/…') — correct
IBM Plex fonts in one place own wwwroot/fonts/ own wwwroot/fonts/ own wwwroot/fonts/

Gap T1: All three apps maintain a copy of theme.css — the single-source guarantee is broken today. Any token change must be applied in four places (three apps + the RCL) once the RCL exists. → Gap T2: OtOpcUa url('fonts/…') is a latent 404 masked by system-font fallback. Adoption fixes it automatically. → Gap T3: Each app vendors fonts — 3× duplication. The RCL eliminates it.

§2 Typography

All three apps reference IBM Plex via the token stacks. No typography divergence — the token values are identical. Gap is delivery (T3 above).

§3 Canonical side-rail layout

Item OtOpcUa MxAccessGateway ScadaBridge
.app-shell root element div.app-shell div.d-flex … (no .app-shell) div.d-flex … (no .app-shell)
Rail CSS class .side-rail .sidebar .sidebar
Nav item CSS class .rail-link .nav-link .nav-link
Nav item element <a> (NavLink) <li><NavLink> inside <ul> <li><NavLink> inside <ul>
Shell component bespoke MainLayout + NavSidebar combined MainLayout (210 lines) MainLayout + NavMenu
Thin-MainLayout pattern not yet not yet not yet

Gap L1: OtOpcUa already uses the right CSS classes but the component structure doesn't use ThemeShell. Low-risk migration. → Gap L2: MxAccessGateway and ScadaBridge use .sidebar / .nav-link / <ul><li>. Migration requires class name changes throughout their nav markup and site.css sidebar blocks. Medium (ScadaBridge) to high (MxGateway combined layout) risk.

§4 Component contract

Component OtOpcUa MxAccessGateway ScadaBridge
StatusPill (vs bespoke StatusBadge) StatusBadge (string CSS class) StatusBadge (string text → class) raw .chip-* classes inline
LoginCard inline markup in Login.razor no Blazor login page Bootstrap .card markup in Login.razor
NavRailItem / NavRailSection NavLink + NavSection (interactive) NavLink+<li> + NavSection NavLink+<li> + NavSection
ThemeShell / thin MainLayout not yet not yet not yet
ThemeHead manual <link> tags manual <link> tags manual <link> tags

§5 Delivery

Item OtOpcUa MxAccessGateway ScadaBridge
Asset via _content/ZB.MOM.WW.Theme/… _content/…AdminUI/css/… root-relative /css/… _content/…CentralUI/css/…
<ThemeHead /> in <head> manual <link> tags manual <link> tags manual <link> tags

Adoption backlog (ordered)

# Item Projects Priority Effort Risk Notes
1 Build ZB.MOM.WW.Theme RCL scadaproj High M Low DONE0.1.0 built + tested in this repo
2 Adopt in OtOpcUa AdminUI OtOpcUa High S Low Already rail; fix latent font 404; cookie nav-state optional retain
3 Adopt in ScadaBridge CentralUI + Host ScadaBridge Med M Med Sidebar class migration + MainLayout replace; scoped .razor.css unchanged
4 Adopt in MxAccessGateway Dashboard MxAccessGateway Low L High Combined MainLayout migration; sidebar idiom change; largest UX-visible change — verify visually

Sequencing: #2 first (lowest risk, validates the adoption pattern); #3 next (medium effort, no design change); #4 last (highest risk — verify dashboard UX thoroughly before merging). Each adoption is a per-repo PR, independent.


Open questions

  • MxGateway login: No Blazor login page today. If one is added during adoption (#4), use <LoginCard>. If the server-redirect pattern is kept, <LoginCard> is not needed.
  • OtOpcUa cookie nav state: Decide whether to retain otopcua_nav cookie persistence (keep bespoke interactive NavSection alongside ThemeShell's Nav slot) or drop it (CSS-only NavRailSection replaces it, losing expand-state persistence across page loads).
  • ScadaBridge AuthorizeView policy gating in nav: Verify <NavRailSection> inside <AuthorizeView> renders + hides correctly with the canonical SSR rendering model.