feat(deploy): reject Tag/VirtualTag NodeId collisions at deploy (surgical DraftValidator gate)
This commit is contained in:
@@ -8,6 +8,7 @@ using ZB.MOM.WW.OtOpcUa.Commons.Types;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Validation;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.ControlPlane.AdminOperations;
|
||||
@@ -78,6 +79,27 @@ public sealed class AdminOperationsActor : ReceiveActor
|
||||
return;
|
||||
}
|
||||
|
||||
// Surgical pre-seal gate: reject only on a Tag↔VirtualTag NodeId collision. The other
|
||||
// DraftValidator rules still run (one pass) but must NOT block here — they are dormant
|
||||
// and the current non-canonical company overlay would otherwise fail them. Filter to the
|
||||
// single collision code so a real OPC UA address-space clash can never be deployed.
|
||||
var draft = await DraftSnapshotFactory.FromConfigDbAsync(db);
|
||||
var collisions = DraftValidator.Validate(draft)
|
||||
.Where(e => e.Code == "EquipmentSignalNameCollision")
|
||||
.ToList();
|
||||
if (collisions.Count > 0)
|
||||
{
|
||||
var summary = string.Join("; ", collisions.Select(e => e.Message));
|
||||
_log.Warning("StartDeployment rejected (signal collision): {Summary}", summary);
|
||||
replyTo.Tell(new StartDeploymentResult(
|
||||
StartDeploymentOutcome.Rejected,
|
||||
DeploymentId: null,
|
||||
RevisionHash: null,
|
||||
Message: summary,
|
||||
msg.CorrelationId));
|
||||
return;
|
||||
}
|
||||
|
||||
var artifact = await ConfigComposer.SnapshotAndFlattenAsync(db);
|
||||
var deploymentId = DeploymentId.NewId();
|
||||
var revHash = RevisionHash.Parse(artifact.RevisionHash);
|
||||
|
||||
Reference in New Issue
Block a user