fix(code-review): resolve Batch 1 open findings (AdminUI auth, AlarmHistorian dispose guards, docs)

- AdminUI-001: gate Script editor pages at Administrator,Designer + loosen ScriptAnalysis backend to match
- AdminUI-004: explicit [Authorize] on FleetStatus/Alert/ScriptLog hubs
- Core.AlarmHistorian-014: ObjectDisposedException guards on GetStatus/RetryDeadLettered (+ regression test)
- Core.Scripting.Abstractions-004/-007: Deadband tolerance doc + stale ScriptedAlarms.md path
- Host-003: correct config-overlay precedence in ServiceHosting.md
- Configuration-014: LdapGroupRoleMapping collation-dependency doc
- Driver.TwinCAT.Contracts-002: Structure enum doc (discovery-only sentinel)
This commit is contained in:
Joseph Doherty
2026-06-20 22:30:33 -04:00
parent c13fcc1d51
commit 98b27fc1b6
19 changed files with 96 additions and 33 deletions
@@ -2,7 +2,7 @@
@page "/scripts/{ScriptId}"
@* Script CRUD. SourceHash is computed automatically from SourceCode on save so the
integrity check in v2's deployment pipeline doesn't require operator action. *@
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@attribute [Microsoft.AspNetCore.Authorization.Authorize(Roles = "Administrator,Designer")]
@rendermode RenderMode.InteractiveServer
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.EntityFrameworkCore
@@ -1,5 +1,5 @@
@page "/scripts"
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@attribute [Microsoft.AspNetCore.Authorization.Authorize(Roles = "Administrator,Designer")]
@rendermode RenderMode.InteractiveServer
@using Microsoft.EntityFrameworkCore
@using ZB.MOM.WW.OtOpcUa.Configuration
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
@@ -8,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
/// clears, or is acknowledged on any cluster node. Bridge: <c>AlertSignalRBridge</c> subscribes
/// to the <c>alerts</c> DPS topic and forwards to every connected SignalR client.
/// </summary>
[Authorize]
public sealed class AlertHub : Hub
{
public const string Endpoint = "/hubs/alerts";
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Fleet;
@@ -10,6 +11,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
/// Server pushes fleet-status updates to connected clients via <c>FleetStatusSignalRBridge</c>
/// (DistributedPubSub 'fleet-status' → <c>IHubContext&lt;FleetStatusHub&gt;</c>).
/// </summary>
[Authorize]
public sealed class FleetStatusHub : Hub
{
public const string Endpoint = "/hubs/fleet-status";
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
@@ -9,6 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
/// <c>ScriptLogSignalRBridge</c> subscribes to the <c>script-logs</c> DPS topic and forwards
/// to every connected SignalR client.
/// </summary>
[Authorize]
public sealed class ScriptLogHub : Hub
{
public const string Endpoint = "/hubs/script-log";
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
@@ -9,7 +10,9 @@ public static class ScriptAnalysisEndpoints
{
public static IEndpointRouteBuilder MapScriptAnalysisEndpoints(this IEndpointRouteBuilder endpoints)
{
var group = endpoints.MapGroup("/api/script-analysis").RequireAuthorization("FleetAdmin");
// Require Administrator or Designer — matches the Script page gate and the /deployments gate.
var group = endpoints.MapGroup("/api/script-analysis")
.RequireAuthorization(new AuthorizeAttribute { Roles = "Administrator,Designer" });
group.MapPost("/diagnostics", (DiagnoseRequest r, ScriptAnalysisService s) => Results.Ok(s.Diagnose(r)));
group.MapPost("/completions", async (CompletionsRequest r, ScriptAnalysisService s) => Results.Ok(await s.CompleteAsync(r)));
group.MapPost("/hover", async (HoverRequest r, ScriptAnalysisService s) => Results.Ok(await s.Hover(r)));