AdminUI /admin/secrets renders but is non-interactive — Secrets.Ui RCL pages get no render mode #483
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while verifying clustered-secrets enablement on the docker-dev rig (2026-07-18).
Symptom
/admin/secretsreturns HTTP 200 and renders the secrets list (auth fine), but every interactive element is dead — "Add secret" (@onclick) does nothing. Verified with Playwright: the SSR HTML contains zero Blazor interactive markers and no/_blazorcircuit is ever negotiated on that page (button click → no editor, no WebSocket). Every other admin page is interactive.Cause
The
ZB.MOM.WW.Secrets.UiRCL components (SecretsPage/SecretsList) declare no@rendermode, and OtOpcUa'sApp.razor/Routes.razorapplies interactivity per-page (@rendermode InteractiveServeron each of its own pages). Routable pages contributed by the additional assembly therefore fall back to static SSR.Suggested fix
Either apply an InteractiveServer render mode to the additional-assembly routes in OtOpcUa's router, or add
@rendermodein the RCL (a library-side fix inZB.MOM.WW.Secrets.Uiwould benefit every consumer — check how the other three apps host the same page before choosing).Notes
Secrets:Replication:Enabledoff/on makes no difference).secretCLI against the node's store, not the AdminUI page.Fixed —
master@5f72ff85, live-verifiedFix location: this host, not the RCL. The other three family apps render the RCL page under a globally interactive router (
<Routes @rendermode="InteractiveServer"/>), so a page-level@rendermodeinsideZB.MOM.WW.Secrets.Uiwould throw at runtime for all of them (nested render mode on an interactive parent). OtOpcUa alone keeps a static router with per-page opt-in — so the fix is a host-side wrapper:Pages/SecretsAdmin.razorowns/admin/secrets, carries@rendermode RenderMode.InteractiveServer, re-states the RCL page'ssecrets:managepolicy (the router only enforces[Authorize]on the routed component, which is now the wrapper), and renders the RCLSecretsPageas an ordinary child. The RCL assembly is de-registered from bothAdditionalAssembliessites so the route is unambiguous.Guards:
SecretsPageWiringTestspins the render mode (THE regression for this issue), route parity with the RCL page, and policy parity; thePageAuthorizationGuardTestscensus classifies the new page. AdminUI.Tests 665/665.Live verification on the rebuilt docker-dev rig (Playwright):
/_blazorcircuit negotiated on/admin/secretsand Add secret opens the editor — before the fix the same probe found zero interactive markers, no circuit, and a dead click.RCL-side note (no change shipped there): the render-mode gap is inherent to any consumer with a static router; the wrapper pattern in
5f72ff85is the reference approach for such hosts, and the wiring tests keep it from drifting.