diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/App.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/App.razor
index 7255b31d..4697fe81 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/App.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/App.razor
@@ -19,7 +19,7 @@
-
+
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor
index 50b5ecdf..29be26aa 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor
@@ -20,6 +20,7 @@
+
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
index 72a33228..8bff8987 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
@@ -1,3 +1,4 @@
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
@@ -10,6 +11,7 @@ using ZB.MOM.WW.OtOpcUa.Commons.Browsing;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser;
using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser;
+using ZB.MOM.WW.Secrets.Ui;
namespace ZB.MOM.WW.OtOpcUa.AdminUI;
@@ -28,8 +30,13 @@ public static class EndpointRouteBuilderExtensions
// Razor class library static assets (_content/ZB.MOM.WW.OtOpcUa.AdminUI/**) are
// served via the Host's app.UseStaticFiles() middleware which must run BEFORE
// UseAuthentication() — see Program.cs.
+ // The /admin/secrets management page lives in the external ZB.MOM.WW.Secrets.Ui RCL, so its
+ // routable component must be discovered at the endpoint layer (AddAdditionalAssemblies) —
+ // the interactive Router's AdditionalAssemblies (App.razor) alone is not enough for SSR
+ // endpoint discovery. Both registrations are required or /admin/secrets 404s.
app.MapRazorComponents()
- .AddInteractiveServerRenderMode();
+ .AddInteractiveServerRenderMode()
+ .AddAdditionalAssemblies(typeof(ZB.MOM.WW.Secrets.Ui.SecretsPage).Assembly);
return app;
}
@@ -43,6 +50,15 @@ public static class EndpointRouteBuilderExtensions
services.AddRazorComponents().AddInteractiveServerComponents();
services.AddOtOpcUaDriverStatusServices();
+ // Secrets-management UI (ZB.MOM.WW.Secrets.Ui RCL, mounted at /admin/secrets). Register its
+ // "secrets:manage"/"secrets:reveal" authorization policies additively onto the AuthorizationOptions
+ // that AddOtOpcUaAuth (called just before AddAdminUI on admin nodes) sets up — Configure stacks,
+ // so this ADDS the two policies without disturbing FleetAdmin/DriverOperator/ConfigEditor. The
+ // policies' AdminRole = "Administrator" reads the same ClaimTypes.Role claim as FleetAdmin, so an
+ // existing Administrator satisfies them with no new group→role mapping. Registered here (the AdminUI
+ // composition layer that already references the RCL) rather than in the core Security lib.
+ services.Configure(o => o.AddSecretsAuthorization());
+
// Browse pipeline — see docs/plans/2026-05-28-driver-browsers-design.md
services.AddSingleton();
services.AddHostedService();