review(OpcUaServer): fix silent auto-unshelve failure (empty User -> 'system')
Cross-module fix from the review sweep. -007 (Medium): OnTimedUnshelve built its AlarmCommand with User=string.Empty, so Part9StateMachine.ApplyUnshelve rejected it (ArgumentException, swallowed) and a TimedShelve never auto-expired. Pass the canonical 'system' user; the AlarmAck-gate bypass is preserved. Repurposed the test that had encoded the bug.
This commit is contained in:
@@ -674,7 +674,14 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2
|
||||
alarm.OnTimedUnshelve = (context, condition) =>
|
||||
{
|
||||
var alarmId = condition.NodeId.Identifier?.ToString() ?? string.Empty;
|
||||
AlarmCommandRouter?.Invoke(new AlarmCommand(alarmId, "Unshelve", string.Empty, null, null));
|
||||
// User MUST be non-empty: the engine's Part9StateMachine.ApplyUnshelve rejects a
|
||||
// null/whitespace user (ArgumentException "User required."), and that exception is swallowed
|
||||
// downstream — an empty user would make the timed auto-unshelve silently no-op, so a
|
||||
// TimedShelve would never auto-expire. There is no client principal on a system-timer
|
||||
// unshelve, so label it the canonical engine-internal "system" user (matching the engine's
|
||||
// own AutoUnshelve audit user and the codebase-wide "system" system-actor convention). The
|
||||
// AlarmAck gate bypass is intentional and preserved — this is a session-less SDK timer.
|
||||
AlarmCommandRouter?.Invoke(new AlarmCommand(alarmId, "Unshelve", "system", null, null));
|
||||
return ServiceResult.Good;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user