Three deferred 'surface the failed write' enhancements on the write-outcome
self-correction path in OtOpcUaNodeManager:
- Item A: synchronous structural fail-fast. EvaluateEquipmentWriteStructure
(pure static) rejects a structurally-invalid write INLINE (Bad sync) after
the authz gate but before the optimistic dispatch, so the SDK never applies
it. Null payload -> BadTypeMismatch; plus a confidence-gated cheap built-in
type compatibility check (numeric widening + BaseDataType wildcard tolerated;
uncertain cases defer to the SDK's own coercion).
- Item B: Bad-quality blip on device-write failure. On a revert,
RevertOptimisticWriteIfNeeded first publishes the still-applied optimistic
value with StatusCode BadDeviceFailure, then restores the prior value/status
(both under the existing Lock). Documents the queue-coalescing caveat (a slow
subscriber may see only the restored value -> the audit event is the reliable
signal).
- Item C: Part 8 AuditWriteUpdateEvent on device-write failure. Builds an
AuditWriteUpdateEventState (SourceNode=node, AttributeId=Value, OldValue=prior,
NewValue=attempted, ClientUserId from the threaded identity, Message carries
outcome.Reason) under Lock and reports it via Server.ReportEvent OUTSIDE Lock.
Guarded so auditing-disabled / report failure never breaks the revert.
Threads the writing identity's user-id + node into the continuation. Adds 6
unit tests for EvaluateEquipmentWriteStructure. Build clean (0 warnings);
158/158 OpcUaServer.Tests green.