diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs
index 74718cdf..cc0f37b9 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs
@@ -10,12 +10,6 @@ public enum NamespaceKind
///
Equipment,
- ///
- /// System Platform namespace — Galaxy / MXAccess processed data (v1 LmxOpcUa folded in).
- /// UNS rules do NOT apply; Galaxy hierarchy preserved as v1 expressed it.
- ///
- SystemPlatform,
-
///
/// Reserved for future replay driver per handoff §"Digital Twin Touchpoints" — not populated
/// in v2.0 but enum value reserved so the schema does not need to change when the replay
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
index aa60242d..3b0e7313 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
@@ -110,9 +110,6 @@ public enum NamespaceKindCompatibility
/// Driver may populate Equipment-kind namespaces (UNS path, Equipment rows).
Equipment = 1,
- /// Driver may populate SystemPlatform-kind namespaces (Galaxy hierarchy, FolderPath).
- SystemPlatform = 2,
-
/// Driver may populate the future Simulated namespace (replay driver — not in v2.0).
Simulated = 4,
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/NamespaceEdit.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/NamespaceEdit.razor
index 68499e88..2b09d13f 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/NamespaceEdit.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/NamespaceEdit.razor
@@ -49,7 +49,6 @@ else
-
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftValidatorTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftValidatorTests.cs
index ef2eeed4..8ca8b1f2 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftValidatorTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftValidatorTests.cs
@@ -136,7 +136,7 @@ public sealed class DraftValidatorTests
DriverInstances = [new DriverInstance { DriverInstanceId = "d-1", ClusterId = "c", NamespaceId = "ns-1", Name = "drv", DriverType = "GalaxyMxGateway", DriverConfig = "{}" }],
};
- DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "DriverNamespaceKindMismatch");
+ DraftValidator.Validate(draft).ShouldBeEmpty();
}
/// Verifies that all validation errors are reported simultaneously.
@@ -165,32 +165,15 @@ public sealed class DraftValidatorTests
// ------------------------------------------------------------------------------------
/// Probe for the deploy-path gate activation: a full, realistic config modelling
- /// the REAL deployed shape (a SystemPlatform namespace + GalaxyMxGateway driver + SystemPlatform
- /// Tags with EquipmentId=null from the OtOpcUa seed, PLUS an Equipment namespace + Modbus driver
- /// + UNS area/line + canonical Equipment rows + VirtualTags from the company overlay) must
+ /// the REAL deployed shape. Galaxy is now a standard Equipment-kind driver (the SystemPlatform
+ /// namespace split is retired), so the GalaxyMxGateway driver + its Galaxy-hierarchy Tags
+ /// (EquipmentId=null from the seed) live in the Equipment namespace alongside a Modbus driver
+ /// + UNS area/line + canonical Equipment rows + VirtualTags from the company overlay. This must
/// produce ZERO validation errors so the reject-on-any-error gate is safe to activate.
[Fact]
public void Full_realistic_config_passes_all_rules()
{
- // SystemPlatform side (OtOpcUa seed shape): Galaxy hierarchy, no Equipment, Tags carry EquipmentId=null.
- var spNamespace = new Namespace
- {
- NamespaceId = "MAIN-OPCUA-systemplatform",
- ClusterId = "MAIN",
- Kind = NamespaceKind.SystemPlatform,
- NamespaceUri = "urn:zb:main:systemplatform",
- };
- var spDriver = new DriverInstance
- {
- DriverInstanceId = "main-galaxy",
- ClusterId = "MAIN",
- NamespaceId = spNamespace.NamespaceId,
- Name = "Galaxy",
- DriverType = "GalaxyMxGateway",
- DriverConfig = "{}",
- };
-
- // Equipment side (company overlay): Modbus driver in an Equipment namespace + UNS + canonical equipment.
+ // Equipment side: Galaxy + Modbus drivers in a single Equipment namespace + UNS + canonical equipment.
var eqNamespace = new Namespace
{
NamespaceId = "MAIN-OPCUA-equipment",
@@ -198,6 +181,18 @@ public sealed class DraftValidatorTests
Kind = NamespaceKind.Equipment,
NamespaceUri = "urn:zb:main:equipment",
};
+
+ // Galaxy hierarchy (OtOpcUa seed shape): GalaxyMxGateway driver, Tags carry EquipmentId=null.
+ var spDriver = new DriverInstance
+ {
+ DriverInstanceId = "main-galaxy",
+ ClusterId = "MAIN",
+ NamespaceId = eqNamespace.NamespaceId,
+ Name = "Galaxy",
+ DriverType = "GalaxyMxGateway",
+ DriverConfig = "{}",
+ };
+
var eqDriver = new DriverInstance
{
DriverInstanceId = "main-modbus",
@@ -242,14 +237,14 @@ public sealed class DraftValidatorTests
GenerationId = 0,
ClusterId = string.Empty, // global snapshot — matches DraftSnapshotFactory.FromConfigDbAsync
// Enterprise/Site left null — matches the deploy path's conservative fallback
- Namespaces = [spNamespace, eqNamespace],
+ Namespaces = [eqNamespace],
DriverInstances = [spDriver, eqDriver],
UnsAreas = [area],
UnsLines = [line],
Equipment = [rinser, filler],
Tags =
[
- // SystemPlatform tags from the seed: EquipmentId null, Galaxy folder hierarchy.
+ // Galaxy-hierarchy tags from the seed: EquipmentId null, Galaxy folder hierarchy.
BuildTag(equipmentId: null, name: "PV", folderPath: "Area.Tank01"),
BuildTag(equipmentId: null, name: "SP", folderPath: "Area.Tank01"),
],
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeRegistryTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeRegistryTests.cs
index d9bbc8a4..bbd9990f 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeRegistryTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeRegistryTests.cs
@@ -118,7 +118,7 @@ public sealed class DriverTypeRegistryTests
var registry = new DriverTypeRegistry();
registry.Register(SampleMetadata("Modbus"));
registry.Register(SampleMetadata("S7"));
- registry.Register(SampleMetadata("Galaxy", NamespaceKindCompatibility.SystemPlatform));
+ registry.Register(SampleMetadata("Galaxy", NamespaceKindCompatibility.Equipment));
var all = registry.All();
@@ -132,12 +132,14 @@ public sealed class DriverTypeRegistryTests
[Fact]
public void NamespaceKindCompatibility_FlagsAreBitmask()
{
- // Per decision #111 — driver types like OpcUaClient may be valid for multiple namespace kinds.
- var both = NamespaceKindCompatibility.Equipment | NamespaceKindCompatibility.SystemPlatform;
+ // Per decision #111 — driver types may be valid for multiple namespace kinds.
+ var both = NamespaceKindCompatibility.Equipment | NamespaceKindCompatibility.Simulated;
both.HasFlag(NamespaceKindCompatibility.Equipment).ShouldBeTrue();
- both.HasFlag(NamespaceKindCompatibility.SystemPlatform).ShouldBeTrue();
- both.HasFlag(NamespaceKindCompatibility.Simulated).ShouldBeFalse();
+ both.HasFlag(NamespaceKindCompatibility.Simulated).ShouldBeTrue();
+
+ // A single-flag value does not carry the other flag — proves these are real bitmask bits.
+ NamespaceKindCompatibility.Equipment.HasFlag(NamespaceKindCompatibility.Simulated).ShouldBeFalse();
}
///
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceTagTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceTagTests.cs
index 68183c7e..99f9e9ee 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceTagTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceTagTests.cs
@@ -29,14 +29,14 @@ public sealed class UnsTreeServiceTagTests
///
/// Seeds an area→line→equipment path in . The equipment id is
/// always EQ-1. Optionally seeds an Equipment-kind driver (DRV-EQ) in the equipment's
- /// cluster, a SystemPlatform-kind driver (DRV-SP) in the equipment's cluster, and an
- /// Equipment-kind driver (DRV-OTHER) in .
+ /// cluster, a non-Equipment-kind (Simulated) driver (DRV-SP) in the equipment's cluster, and
+ /// an Equipment-kind driver (DRV-OTHER) in .
///
private static void SeedHierarchyAndDrivers(
string dbName,
string equipmentCluster,
bool seedEquipmentDriver = false,
- bool seedSystemPlatformDriver = false,
+ bool seedNonEquipmentDriver = false,
string? otherCluster = null)
{
using var db = UnsTreeTestDb.CreateNamed(dbName);
@@ -59,12 +59,12 @@ public sealed class UnsTreeServiceTagTests
Kind = NamespaceKind.Equipment,
NamespaceUri = "urn:zb:eq",
});
- // SystemPlatform-kind namespace in the equipment's cluster.
+ // Non-Equipment-kind (Simulated) namespace in the equipment's cluster.
db.Namespaces.Add(new Namespace
{
NamespaceId = "NS-SP",
ClusterId = equipmentCluster,
- Kind = NamespaceKind.SystemPlatform,
+ Kind = NamespaceKind.Simulated,
NamespaceUri = "urn:zb:sp",
});
@@ -81,15 +81,15 @@ public sealed class UnsTreeServiceTagTests
});
}
- if (seedSystemPlatformDriver)
+ if (seedNonEquipmentDriver)
{
db.DriverInstances.Add(new DriverInstance
{
DriverInstanceId = "DRV-SP",
ClusterId = equipmentCluster,
NamespaceId = "NS-SP",
- Name = "galaxy driver",
- DriverType = "Galaxy",
+ Name = "non-equipment driver",
+ DriverType = "ModbusTcp",
DriverConfig = "{}",
});
}
@@ -187,12 +187,12 @@ public sealed class UnsTreeServiceTagTests
db.Tags.Any(t => t.TagId == "TAG-1").ShouldBeFalse();
}
- /// Binding a tree tag to a driver in a SystemPlatform-kind namespace is blocked.
+ /// Binding a tree tag to a driver in a non-Equipment-kind namespace is blocked.
[Fact]
- public async Task CreateTag_driver_systemplatform_namespace_blocked()
+ public async Task CreateTag_driver_non_equipment_namespace_blocked()
{
var (service, dbName) = Fresh();
- SeedHierarchyAndDrivers(dbName, equipmentCluster: "MAIN", seedSystemPlatformDriver: true);
+ SeedHierarchyAndDrivers(dbName, equipmentCluster: "MAIN", seedNonEquipmentDriver: true);
var result = await service.CreateTagAsync("EQ-1", Input("TAG-1", "speed", "DRV-SP"));
@@ -340,7 +340,7 @@ public sealed class UnsTreeServiceTagTests
///
/// The driver loader returns only Equipment-kind drivers in the equipment's cluster — excluding
- /// SystemPlatform-kind drivers in the same cluster and Equipment-kind drivers in other clusters.
+ /// non-Equipment-kind drivers in the same cluster and Equipment-kind drivers in other clusters.
///
[Fact]
public async Task LoadTagDriversForEquipment_returns_only_equipment_kind_drivers_in_cluster()
@@ -350,7 +350,7 @@ public sealed class UnsTreeServiceTagTests
dbName,
equipmentCluster: "MAIN",
seedEquipmentDriver: true,
- seedSystemPlatformDriver: true,
+ seedNonEquipmentDriver: true,
otherCluster: "SITE-A");
var drivers = await service.LoadTagDriversForEquipmentAsync("EQ-1");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactAliasParityTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactAliasParityTests.cs
index feb93c79..846cd3fa 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactAliasParityTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactAliasParityTests.cs
@@ -15,8 +15,8 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
/// EquipmentId) bound to a GalaxyMxGateway driver in an Equipment-kind namespace —
/// into the decoded EquipmentTags with byte-parity to the live-edit composer path: same FullName,
/// EquipmentId, DriverInstanceId, Name, DataType. Both data-contract sites gate purely on the namespace
-/// Kind being Equipment (no Galaxy/DriverType exception — the SystemPlatform-mirror contract is
-/// retired), so they agree on which tags qualify.
+/// Kind being Equipment (no Galaxy/DriverType exception — Galaxy is an ordinary Equipment-kind
+/// driver), so they agree on which tags qualify.
///
public sealed class DeploymentArtifactAliasParityTests
{
@@ -64,34 +64,34 @@ public sealed class DeploymentArtifactAliasParityTests
tag.FullName.ShouldBe("TestMachine_020.TestChangingInt");
}
- /// An equipment-scoped GalaxyMxGateway tag in a SystemPlatform-kind namespace must NOT surface
- /// in EquipmentTags — byte-parity with the composer's pure ns.Kind == NamespaceKind.Equipment
- /// predicate. The retired SystemPlatform-mirror contract no longer carried a DriverType exception, so a
+ /// An equipment-scoped tag in a non-Equipment (Simulated) namespace must NOT surface in
+ /// EquipmentTags — byte-parity with the composer's pure ns.Kind == NamespaceKind.Equipment
+ /// predicate. The gate keys off the namespace Kind alone, with no DriverType exception, so a
/// non-Equipment namespace excludes the tag regardless of driver type.
[Fact]
- public void ParseComposition_excludes_galaxy_tag_in_non_equipment_namespace()
+ public void ParseComposition_excludes_tag_in_non_equipment_namespace()
{
var blob = JsonSerializer.SerializeToUtf8Bytes(new
{
Namespaces = new[]
{
- new { NamespaceId = "ns-sp", Kind = 1 }, // NamespaceKind.SystemPlatform
+ new { NamespaceId = "ns-sim", Kind = 1 }, // NamespaceKind.Simulated (non-Equipment)
},
DriverInstances = new[]
{
- new { DriverInstanceId = "drv-galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}", NamespaceId = "ns-sp" },
+ new { DriverInstanceId = "drv-sim", DriverType = "Modbus", DriverConfig = "{}", NamespaceId = "ns-sim" },
},
Tags = new object[]
{
new
{
TagId = "tag-x",
- DriverInstanceId = "drv-galaxy",
+ DriverInstanceId = "drv-sim",
EquipmentId = "eq-1",
Name = "Source",
FolderPath = (string?)null,
DataType = "Int32",
- TagConfig = "{\"FullName\":\"TestMachine_020.Source\"}",
+ TagConfig = "{\"FullName\":\"40001\"}",
},
},
});
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactTests.cs
index 832af534..2ab2001c 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DeploymentArtifactTests.cs
@@ -193,10 +193,10 @@ public sealed class DeploymentArtifactTests
///
/// Verifies ParseComposition surfaces Equipment-namespace tags (non-null EquipmentId in an
/// Equipment-kind namespace) as EquipmentTags, with FullName extracted
- /// from the tag's TagConfig blob. A tag in a non-Equipment (SystemPlatform) namespace with a
+ /// from the tag's TagConfig blob. A tag in a non-Equipment (Simulated) namespace with a
/// null EquipmentId must NOT surface in EquipmentTags — byte-parity with the composer's pure
- /// ns.Kind == NamespaceKind.Equipment predicate (the SystemPlatform-mirror contract is
- /// retired, so such a tag routes nowhere).
+ /// ns.Kind == NamespaceKind.Equipment predicate (only Equipment-kind namespaces route
+ /// into EquipmentTags, so such a tag routes nowhere).
///
[Fact]
public void ParseComposition_reads_EquipmentTags_from_equipment_namespace()
@@ -206,12 +206,12 @@ public sealed class DeploymentArtifactTests
Namespaces = new[]
{
new { NamespaceId = "ns-eq", Kind = 0 }, // NamespaceKind.Equipment
- new { NamespaceId = "ns-sp", Kind = 1 }, // NamespaceKind.SystemPlatform
+ new { NamespaceId = "ns-sim", Kind = 1 }, // NamespaceKind.Simulated (non-Equipment)
},
DriverInstances = new[]
{
new { DriverInstanceId = "drv-modbus", DriverType = "Modbus", DriverConfig = "{}", NamespaceId = "ns-eq" },
- new { DriverInstanceId = "drv-galaxy", DriverType = "Galaxy", DriverConfig = "{}", NamespaceId = "ns-sp" },
+ new { DriverInstanceId = "drv-sim", DriverType = "Modbus", DriverConfig = "{}", NamespaceId = "ns-sim" },
},
Tags = new object[]
{
@@ -227,8 +227,8 @@ public sealed class DeploymentArtifactTests
},
new
{
- TagId = "tag-gx",
- DriverInstanceId = "drv-galaxy",
+ TagId = "tag-sim",
+ DriverInstanceId = "drv-sim",
EquipmentId = (string?)null,
Name = "Temp",
FolderPath = "area",
@@ -248,9 +248,9 @@ public sealed class DeploymentArtifactTests
tag.DataType.ShouldBe("Float");
tag.FullName.ShouldBe("40001"); // extracted from TagConfig, not the raw blob
- // The SystemPlatform tag (null EquipmentId, non-Equipment namespace) does NOT leak into
- // EquipmentTags — byte-parity with the composer's pure ns.Kind == Equipment predicate.
- c.EquipmentTags.ShouldNotContain(t => t.TagId == "tag-gx");
+ // The tag in the non-Equipment (Simulated) namespace, with null EquipmentId, does NOT leak
+ // into EquipmentTags — byte-parity with the composer's pure ns.Kind == Equipment predicate.
+ c.EquipmentTags.ShouldNotContain(t => t.TagId == "tag-sim");
}
///