diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/HistoryPaging.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/HistoryPaging.cs index bf93602a..9bbaf864 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/HistoryPaging.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/HistoryPaging.cs @@ -73,6 +73,8 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer; /// that still has un-emitted ties — the next page over-fetches the cluster directly /// instead of first re-reading N + skip + 1 rows that are known to be ties. /// +/// The exact namespace-qualified node identity; required on every production cursor. +/// The topology generation. A removal conservatively invalidates all cursors. internal sealed record HistoryContinuationState( string Tagname, DateTime NextStartUtc, diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs index 6dd731c1..e6fa9067 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs @@ -519,8 +519,10 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable ClientConfiguration = new ClientConfiguration(), }; - await config.ValidateAsync(ApplicationType.Server, ct).ConfigureAwait(false); + // Validation creates the certificate manager before awaiting certificate loads. Give the + // application ownership first so failed/canceled startup disposes that manager too. _application!.ApplicationConfiguration = config; + await config.ValidateAsync(ApplicationType.Server, ct).ConfigureAwait(false); return config; } diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs index c2fcf660..57b1929a 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs @@ -1527,6 +1527,8 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2 // Both are part of the application's existing Part 9 method/state contract. alarm.ConfirmedState = new TwoStateVariableState(alarm); alarm.Confirm = new AddCommentMethodState(alarm); + alarm.ShelvingState = new ShelvedStateMachineState(alarm); + alarm.MaxTimeShelved = new PropertyState.Implementation(alarm); alarm.SymbolicName = displayName; // HasComponent so the parent folder "owns" the condition (matches the T13 notes' pattern). alarm.ReferenceTypeId = ReferenceTypeIds.HasComponent;