DraftValidator/DraftSnapshot is dead code (no src/ caller) — possible publish-time enforcement gap #422
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
DraftValidator(the managed "pre-publish validator per decision #91") has no live caller anywhere insrc/. A repo-wide search finds its only references are its own source files and its test:src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cssrc/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftSnapshot.cstests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftValidatorTests.cs(15 tests)Nothing constructs a
DraftSnapshotor callsDraftValidator.Validate(...)/ValidateClusterTopology(...)outside that test. It is not registered in DI and is not invoked from the publish path.The enforced pre-publish draft validation actually runs DB-side in
sp_ValidateDraft(src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Migrations/20260417215224_StoredProcedures.cs,Procs.ValidateDraft~:157), as part of theStatus='Draft' → sp_PublishGenerationgeneration lifecycle. So the managedDraftValidatoris currently dormant complement code — and there are passing tests exercising a validator that production never calls.Why this may be more than dead code (potential enforcement gap)
DraftValidator's own doc-comment (:7–13) says it "complements the structural checks insp_ValidateDraft— this layer owns schema validation for JSON columns, UNS segment regex, EquipmentId derivation, cross-cluster checks, and anything else uncomfortable to express in T-SQL." But because it is not wired in, the rules it uniquely owns may be enforced nowhere at publish time.Comparing its private rule methods against the
sp_ValidateDraftRAISERROR checks:DraftValidatorrulesp_ValidateDraft?ValidateUnsSegments(UNS segment regex)ValidatePathLength(≤ 200)ValidateEquipmentIdDerivationValidateClusterTopology(topology vsRedundancyMode)ValidateEquipmentUuidImmutability:233)ValidateSameClusterNamespaceBinding:218,BadCrossClusterNamespaceBinding)ValidateReservationPreflight(ZTag/SAPID):245/:257)ValidateDriverNamespaceCompatibilitySo UNS-segment regex, path-length, EquipmentId derivation, and cluster-topology-vs-RedundancyMode appear to be guarded only by the uncalled C# validator. (I have not read the full stored-proc body or checked for DB constraints/triggers that might cover them — worth confirming before concluding they're truly unenforced.)
Suggested resolution — pick one
DraftValidatoras intended — invoke it in the publish path (alongside / beforesp_ValidateDraft) so the JSON-schema / UNS-regex / EquipmentId-derivation / cluster-topology rules are actually enforced. Confirms the 15 existing tests guard live behavior.DraftValidator.cs,DraftSnapshot.cs, andDraftValidatorTests.cs, and confirmsp_ValidateDraft(plus any DB constraints) is the intended sole enforcement. Only safe if the four "No" rules above are genuinely covered elsewhere or deliberately dropped.Option 1 is preferable if those rules matter at publish time; option 2 only after verifying nothing is lost.
Context
Surfaced while normalizing config-validation across the
ZB.MOM.WW.*family (scadaproj→ZB.MOM.WW.Configuration). This is purely an OtOpcUa housekeeping/correctness question — unrelated to that shared options-validation library (draft/generation-content validation is correctly out of its scope either way). Filing here so it isn't lost.Verified against
mainon 2026-06-01.Stale — the issue's premise is now inverted.
DraftValidatoris LIVE-wired into the deploy gate; do NOT delete. (Verified onmaster@5908339d.)When this was filed (2026-06-01) it was against a pre-v2 state. The v2 Akka deploy path (
StartDeployment) was subsequently wired to callDraftValidator, so it is no longer dead code:src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/AdminOperations/AdminOperationsActor.cs:181—DraftSnapshotFactory.FromConfigDbAsync(db):182—DraftValidator.Validate(draft)(hard pre-seal reject gate):208—DraftValidator.ValidateClusterTopology(cluster, nodes)Reached live from AdminUI:
POST /api/deployments→AdminOperationsClient.StartDeploymentAsync→StartDeploymentmsg →HandleStartDeploymentAsync. Any validation error rejects the deploy.Corollary (the inversion): it is now
sp_ValidateDraft/sp_PublishGenerationthat have no C# caller — the generation-publish SQL path is dormant in the v2 Akka architecture, and the C#DraftValidatoris the live publish gate. So the framing "the DB proc is what actually runs" is reversed.The four "unique" rules are genuinely load-bearing (deletion would lose them):
ValidatePathLength (<=200)— enforced NOWHERE else; the OPC UA path budget would go unchecked.UnsTreeServicecreate/update applies no regex to them (only Equipment has a bypassable client-side[RegularExpression]onEquipmentPage.razor). DraftValidator is the sole publish-time backstop.CK_ServerCluster_RedundancyMode_NodeCountvalidates the declared(NodeCount, RedundancyMode)pair but cannot seeClusterNode.Enabled; onlyValidateClusterTopologycatches nodes toggled off under Hot/Warm.ValidateEquipmentIdDerivation— redundant-by-construction (write path setsEQ-<12hex>inline atUnsTreeService.cs:522/593), but a cheap backstop against hand-edited/imported rows.The 15
DraftValidatorTeststherefore guard live behavior. Closing as resolved (already wired; nothing to do).One optional future cleanup (not blocking):
DeriveEquipmentIdis duplicated inline atUnsTreeService.cs:522/593rather than calling the canonical method — a de-dup refactor, not a correctness gap.