diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/IScriptLogPublisher.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/IScriptLogPublisher.cs index 010316cf..fb261769 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/IScriptLogPublisher.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/IScriptLogPublisher.cs @@ -4,9 +4,9 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Scripting; /// /// Abstraction over the mechanism that publishes records -/// to a downstream consumer (e.g. an Akka DPS script-logs topic). Implemented by -/// the concrete DPS publisher in a later task; the sink depends only on this interface -/// so the Core.Scripting layer has no Akka dependency. +/// to a downstream consumer (e.g. an Akka DPS script-logs topic). The concrete +/// implementation is DpsScriptLogPublisher (Runtime project), wired via DI; the +/// sink depends only on this interface so the Core.Scripting layer has no Akka dependency. /// public interface IScriptLogPublisher { diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptLogTopicSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptLogTopicSink.cs index 026d5d33..fe9e7f3e 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptLogTopicSink.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptLogTopicSink.cs @@ -7,7 +7,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Scripting; /// /// Serilog sink that converts each script into a /// and forwards it to an . -/// The publisher implementation (supplied by a later task) routes the entry onto the +/// The production publisher (DpsScriptLogPublisher) routes the entry onto the /// Akka DPS script-logs topic so the live Script-log Admin UI page can display it. /// /// diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs index d07c79e3..7874c46a 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs @@ -17,9 +17,9 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browse; /// Folder per gobject; variables placed inside their owner folder. /// Variable's full reference = tag_name.attribute_name — the format MXAccess /// expects for read/write addressing (translated from the contained-name browse path). -/// Hierarchy is rendered flat (one folder per gobject under the driver root) for -/// this PR. PR 4.W's address-space wiring revisits whether to nest under -/// parent_gobject_id for a true tree shape. +/// Hierarchy is rendered flat (one folder per gobject under the driver root). +/// Nesting under parent_gobject_id for a true tree shape is not implemented; +/// the flat layout is the current shipping behaviour. /// /// public sealed class GalaxyDiscoverer diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs index c8847278..a3f098da 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs @@ -863,12 +863,12 @@ public sealed class GalaxyDriver if (_dataWriter is null) { // Mirror the IReadable fallback: production write path runs on top of - // GalaxyMxSession (PR 4.2 skeleton; PR 4.4 wires the live session). Until - // that lands, deployments selecting Galaxy:Backend=mxgateway can't write. + // GatewayGalaxyDataWriter, which is wired by InitializeAsync when the gRPC session + // connects. This guard fires only if the driver is called before initialization completes. throw new NotSupportedException( "GalaxyDriver.WriteAsync requires GatewayGalaxyDataWriter wired against a connected " + - "GalaxyMxSession (PR 4.4). Until that lands, route writes through the legacy-host " + - "backend (Galaxy:Backend=legacy-host)."); + "GalaxyMxSession. Call InitializeAsync and wait for a successful connection before " + + "issuing writes."); } return _dataWriter.WriteAsync(writes, ResolveSecurity, cancellationToken); @@ -887,7 +887,7 @@ public sealed class GalaxyDriver { throw new NotSupportedException( "GalaxyDriver.SubscribeAsync requires a connected GalaxyMxSession + GatewayGalaxySubscriber. " + - "PR 4.W wires the production session; until then route subscriptions through the legacy-host backend."); + "Call InitializeAsync and wait for a successful connection before subscribing."); } var pump = EnsureEventPumpStarted(); @@ -1103,7 +1103,7 @@ public sealed class GalaxyDriver { throw new NotSupportedException( "GalaxyDriver.AcknowledgeAsync requires GatewayGalaxyAlarmAcknowledger wired against a connected " + - "GalaxyMxSession (PR B.2). InitializeAsync must run before alarm acknowledgements can flow."); + "GalaxyMxSession. InitializeAsync must complete successfully before alarm acknowledgements can flow."); } // Acks are issued one-by-one — the gateway RPC accepts a single alarm diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs index 35fa8ebf..97acb700 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/ScriptAnalysis/ScriptAnalysisService.cs @@ -18,9 +18,10 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis; /// context. /// /// -/// Public methods are placeholders returning empty results — later tasks fill in each -/// capability via TDD. The shared seam + the offset helpers are -/// the load-bearing part every later capability reuses; keep them even while unused. +/// All capabilities are fully implemented: Diagnose, Complete, Hover, SignatureHelp, and Format +/// are wired and backed by the real Roslyn document/analysis pipeline. Only InlayHints is +/// intentionally a no-op (empty list) — the endpoint exists for future use but the feature is +/// not implemented. /// public sealed class ScriptAnalysisService { diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs index f272c3cb..462e7b65 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs @@ -41,8 +41,10 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers; /// Stale — ConfigDb unreachable on bootstrap. Background reconnect loop tries to advance. /// /// -/// Children (DriverInstance/VirtualTag/etc.) are spawned in Phase 6 follow-up tasks (41-44). -/// For now the dispatch handler treats the apply as a no-op and writes the ACK back. +/// Children (DriverInstance/VirtualTag/etc.) are fully wired: DispatchDeployment drives +/// which runs the spawn-plan via , +/// maintains the FullName→NodeId live-value routing map, and forwards results to the +/// OPC UA publish actor via ForwardToMux. /// public sealed class DriverHostActor : ReceiveActor, IWithTimers { diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs index abde4509..e5c5f227 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs @@ -243,13 +243,14 @@ public sealed class OpcUaPublishActor : ReceiveActor _applier.MaterialiseScriptedAlarms(composition); // Equipment-namespace tags get their own pass: ensures each signal's Variable (and any // FolderPath sub-folder) exists under its already-materialised equipment folder so - // clients can browse them. Live values arrive in a later milestone; until then the - // variables show BadWaitingForInitialData. + // clients can browse them. Live values are pushed by DriverHostActor.ForwardToMux after + // each subscription cycle; variables show BadWaitingForInitialData only until the first + // publish interval fires. _applier.MaterialiseEquipmentTags(composition); // Equipment-namespace VirtualTags get their own pass right after the equipment tags: // ensures each computed signal's Variable (and any FolderPath sub-folder) exists under its - // equipment folder with a folder-scoped NodeId. The VirtualTagActor fills live values in a - // later milestone; until then the variables show BadWaitingForInitialData (same as tags). + // equipment folder with a folder-scoped NodeId. VirtualTagHostActor.OnResult pushes live + // values once the first dependency update arrives; until then variables show BadWaitingForInitialData. _applier.MaterialiseEquipmentVirtualTags(composition); OtOpcUaTelemetry.OpcUaSinkWrite.Add(1, new KeyValuePair("kind", "rebuild")); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs index 2eba6ddd..c64e518f 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs @@ -62,10 +62,11 @@ public static class ServiceCollectionExtensions // driver path) ends up with exactly one descriptor regardless of registration order. services.TryAddSingleton(); - // Shared ZB.MOM.WW.Auth group→role mapper seam (Task 1.1, additive). Wraps the existing - // RoleMapper.Map + RoleMapper.Merge logic; the login flow is rewired to consume it in a - // later task. Scoped to match ILdapGroupRoleMappingService (DbContext-backed, registered - // Scoped) — a singleton here would capture the scoped DB service. + // Shared ZB.MOM.WW.Auth group→role mapper seam. Wraps the existing RoleMapper.Map + + // RoleMapper.Merge logic; consumed by AuthEndpoints.cs (/auth/login) and by + // LdapOpcUaUserAuthenticator (OPC UA UserName session auth). Scoped to match + // ILdapGroupRoleMappingService (DbContext-backed, registered Scoped) — a singleton here + // would capture the scoped DB service. services.TryAddScoped, OtOpcUaGroupRoleMapper>(); services.AddDataProtection()