diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeNames.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeNames.cs
new file mode 100644
index 00000000..2e166a21
--- /dev/null
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeNames.cs
@@ -0,0 +1,68 @@
+namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
+
+///
+/// Single source of truth for the driver-type identifier strings the runtime
+/// dispatches on. Each constant's value is the exact DriverTypeName
+/// that the corresponding driver factory registers under in the process
+/// DriverFactoryRegistry — the string the deploy pipeline stores in
+/// DriverInstance.DriverType and every dispatch map keys by.
+///
+///
+///
+/// Historically several dispatch maps hand-authored these strings and drifted from
+/// the authoritative factory names (e.g. "TwinCat" vs the real
+/// "TwinCAT", "Focas" vs "FOCAS"). Consumers should reference
+/// these constants instead of literals so the drift can never recur.
+///
+///
+/// The reflection guard test
+/// (DriverTypeNamesGuardTests) asserts bidirectional parity between these
+/// constants and the set the driver factories actually register, so a rename on
+/// either side breaks the build's test gate. Only constants for
+/// currently-registered factories belong here — a not-yet-registered driver
+/// (e.g. the Calculation driver landing in a later Batch 2 package) adds its own
+/// constant when its factory is wired in.
+///
+///
+public static class DriverTypeNames
+{
+ /// Modbus TCP / RTU-over-TCP driver.
+ public const string Modbus = "Modbus";
+
+ /// Siemens S7 driver.
+ public const string S7 = "S7";
+
+ /// Allen-Bradley CIP (ControlLogix / CompactLogix) driver.
+ public const string AbCip = "AbCip";
+
+ /// Allen-Bradley legacy (PCCC / DF1-over-TCP) driver.
+ public const string AbLegacy = "AbLegacy";
+
+ /// Beckhoff TwinCAT ADS driver.
+ public const string TwinCAT = "TwinCAT";
+
+ /// FANUC FOCAS CNC driver.
+ public const string FOCAS = "FOCAS";
+
+ /// OPC UA client (upstream-server) driver.
+ public const string OpcUaClient = "OpcUaClient";
+
+ /// AVEVA System Platform (Wonderware) Galaxy driver, via the mxaccessgw gateway.
+ public const string Galaxy = "GalaxyMxGateway";
+
+ ///
+ /// Every driver-type string declared above, for callers that need to enumerate
+ /// the full set (e.g. validation of an authored DriverType).
+ ///
+ public static IReadOnlyCollection All { get; } =
+ [
+ Modbus,
+ S7,
+ AbCip,
+ AbLegacy,
+ TwinCAT,
+ FOCAS,
+ OpcUaClient,
+ Galaxy,
+ ];
+}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeNamesGuardTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeNamesGuardTests.cs
new file mode 100644
index 00000000..d5b12aaf
--- /dev/null
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/DriverTypeNamesGuardTests.cs
@@ -0,0 +1,97 @@
+using System.Reflection;
+using Shouldly;
+using Xunit;
+using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
+using ZB.MOM.WW.OtOpcUa.Core.Hosting;
+
+namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests;
+
+///
+/// Guards against drift from the driver factories that are the
+/// authority for these strings. The test builds the real registered-factory set the way
+/// production does — it drives each driver assembly's *DriverFactoryExtensions.Register
+/// entry point into a live , exactly as the Host's
+/// DriverFactoryBootstrap.Register does — then asserts bidirectional parity with the
+/// constants. If a factory renames its DriverTypeName (or a constant is added/removed
+/// without a matching factory), this fails, forcing the constant and the factory back in sync.
+///
+public sealed class DriverTypeNamesGuardTests
+{
+ ///
+ /// Build the authoritative registered-factory set by invoking every driver assembly's
+ /// registration extension against a fresh registry — the same set of calls, in the same
+ /// spirit, as DriverFactoryBootstrap.Register on a driver-role node.
+ ///
+ private static IReadOnlyCollection RegisteredDriverTypeNames()
+ {
+ var registry = new DriverFactoryRegistry();
+
+ // loggerFactory is optional on every extension; the factory func is never invoked here,
+ // so null is fine — we only need the type-name key each Register call installs.
+ Driver.AbCip.AbCipDriverFactoryExtensions.Register(registry);
+ Driver.AbLegacy.AbLegacyDriverFactoryExtensions.Register(registry, loggerFactory: null);
+ Driver.FOCAS.FocasDriverFactoryExtensions.Register(registry);
+ Driver.Galaxy.GalaxyDriverFactoryExtensions.Register(registry, loggerFactory: null);
+ Driver.Modbus.ModbusDriverFactoryExtensions.Register(registry, loggerFactory: null);
+ Driver.OpcUaClient.OpcUaClientDriverFactoryExtensions.Register(registry, loggerFactory: null);
+ Driver.S7.S7DriverFactoryExtensions.Register(registry);
+ Driver.TwinCAT.TwinCATDriverFactoryExtensions.Register(registry);
+
+ return registry.RegisteredTypes;
+ }
+
+ /// Reflect every public const string declared on .
+ private static IReadOnlyCollection DeclaredConstantValues() =>
+ typeof(DriverTypeNames)
+ .GetFields(BindingFlags.Public | BindingFlags.Static)
+ .Where(f => f.IsLiteral && !f.IsInitOnly && f.FieldType == typeof(string))
+ .Select(f => (string)f.GetRawConstantValue()!)
+ .ToArray();
+
+ [Fact]
+ public void Every_registered_factory_has_a_matching_constant()
+ {
+ var constants = DeclaredConstantValues();
+
+ foreach (var registered in RegisteredDriverTypeNames())
+ {
+ constants.ShouldContain(registered,
+ $"driver factory registers '{registered}' but no DriverTypeNames constant has that value — " +
+ "add/rename the constant so dispatch maps can reference it instead of a drifting literal");
+ }
+ }
+
+ [Fact]
+ public void Every_constant_matches_a_registered_factory()
+ {
+ var registered = RegisteredDriverTypeNames();
+
+ foreach (var constant in DeclaredConstantValues())
+ {
+ registered.ShouldContain(constant,
+ $"DriverTypeNames has '{constant}' but no registered driver factory uses it — " +
+ "remove the constant or wire the factory (do not add constants for unregistered drivers)");
+ }
+ }
+
+ [Fact]
+ public void Constants_and_registered_factories_are_exactly_the_same_set()
+ {
+ DeclaredConstantValues()
+ .OrderBy(s => s, StringComparer.Ordinal)
+ .ShouldBe(
+ RegisteredDriverTypeNames().OrderBy(s => s, StringComparer.Ordinal),
+ "DriverTypeNames must be exactly the set of registered driver-type strings — no drift, no extras, no gaps");
+ }
+
+ [Fact]
+ public void All_collection_equals_the_declared_constants()
+ {
+ // Keeps the convenience `All` collection honest against the individual consts.
+ DriverTypeNames.All
+ .OrderBy(s => s, StringComparer.Ordinal)
+ .ShouldBe(
+ DeclaredConstantValues().OrderBy(s => s, StringComparer.Ordinal),
+ "DriverTypeNames.All must list every declared constant exactly once");
+ }
+}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests.csproj b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests.csproj
index daf8a0f2..f11c7282 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests.csproj
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests.csproj
@@ -21,6 +21,18 @@
+
+
+
+
+
+
+
+
+
+