fix(adminui): link the dead scoped-CSS bundle; add btn/notice-alert/tree-twist rules

Foundation task of the AdminUI UI sweep. CSS/link/doc only — no behavior change
beyond restoring styles that were built but never served.

- App.razor: link the RCL's scoped-CSS bundle
  (_content/ZB.MOM.WW.OtOpcUa.AdminUI/ZB.MOM.WW.OtOpcUa.AdminUI.bundle.scp.css).
  It is produced on every compile and served by the Host, but nothing referenced
  it, so ContextMenu.razor.css was dead at runtime and context menus rendered
  in-flow with no position:fixed.
- site.css: three additions.
  * .btn / .btn-sm sizing as Bootstrap CSS-VARIABLE overrides (never box
    properties — .btn-group depends on Bootstrap's own .btn rules for its seams
    and end-cap radii). Theme 0.3.1 ships no .btn rule, so Bootstrap's 1rem
    applied against the theme's 0.9rem body. Upstreaming candidate, same as the
    ignitionoee router's app.css.
  * .notice-alert — red variant of the kit's amber .notice, on the --bad/
    --bad-bg/--bad-border tokens. The 13 existing call sites hack this with
    style="border-color:var(--alert)", and no --alert token exists anywhere, so
    the tint silently no-ops today. Call-site migration is a separate task.
  * .tree-twist — shared 18px expander column for the tree components, replacing
    repeated inline style="width:18px". Rows are d-flex, so flex-basis is what
    actually holds the column. Adoption is a separate task.
- ContextMenu.razor.css: correct the header comment — the kit is light-only
  (no dark block in Theme 0.3.1, site.css, or this file). No rule changes.
- docs/Telemetry.md: record that driver-health is keyed per driver instance
  across the cluster, not per Akka member (the wire record carries no per-member
  identity). The fact previously lived only in Hosts.razor page copy.
- docs/Configuration.md: new audit-log subsection recording that EventId gives
  cross-restart dedup, enforced by the filtered unique index
  UX_ConfigAuditLog_EventId, so a retried apply inserts no duplicate row;
  CorrelationId joins a row to its originating workflow. Previously only in the
  historical v2 rebuild plan and ClusterAudit page copy.
This commit is contained in:
Joseph Doherty
2026-08-10 16:31:42 -04:00
parent 4d549571cc
commit 697a773340
5 changed files with 89 additions and 1 deletions
+22
View File
@@ -297,6 +297,28 @@ unset (⇒ `Dps`) until the rig is flipped with `Telemetry__Mode=Grpc` / `Teleme
The Config DB itself (the EF Core `OtOpcUaConfigDbContext`, entities, draft/publish generations, `NodeAcl`, `LdapGroupRoleMapping`, migrations) is the durable home for the fleet's drivers, UNS hierarchy, ACLs, and audit log. For the **full schema** see [`docs/v2/config-db-schema.md`](v2/config-db-schema.md). This page does not duplicate it.
### Audit log (`ConfigAuditLog`)
The cluster audit log lives in the Config DB and is written by `ActorAuditWriter`; the AdminUI reads it
per cluster at `/clusters/{id}/audit`. It has no `appsettings` section — it is on whenever an admin node
has a `ConfigDb` — but one schema property is worth recording here because it constrains how callers may
write to it:
- **`EventId` gives cross-restart deduplication, and the DB enforces it.** Each row carries the
stable per-event `AuditEvent.EventId`, under a *filtered* unique index
(`UX_ConfigAuditLog_EventId`, `WHERE [EventId] IS NOT NULL` — so the nullable pre-v2 backfill rows
do not collide with each other). That is what makes an Akka actor safe to retry an apply against
the audit log: the batched writer flushing again after a process crash, a supervision restart, or
an at-least-once redelivery re-sends the same `EventId` and does **not** insert a duplicate row.
`CorrelationId` is the companion column — it joins a row to its originating request/workflow, so
the several rows of one logical operation group together.
- Consequently, **mint the `EventId` per event, never per write attempt.** An id generated inside
the retry path defeats the unique index rather than tripping it, and nothing downstream flags the
result — the log simply grows a second copy of a deployment's audit trail. Carry the id with the
command.
For the full column list see [`docs/v2/config-db-schema.md`](v2/config-db-schema.md).
### Galaxy / MxAccess driver config (`DriverConfig` JSON, not `appsettings`)
The Galaxy/MxAccess connection settings are **not an `appsettings` section.** They are driver-instance options stored in the `DriverConfig` JSON column of the Config DB (edited via the Admin UI), bound to `GalaxyDriverOptions` (`src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Contracts/GalaxyDriverOptions.cs`, namespace `...Driver.Galaxy.Config`). It decomposes into nested records: