diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/RawPaths.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/RawPaths.cs
new file mode 100644
index 00000000..1b38957f
--- /dev/null
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/RawPaths.cs
@@ -0,0 +1,135 @@
+namespace ZB.MOM.WW.OtOpcUa.Commons.Types;
+
+///
+/// The v3 identity authority. A RawPath is the cluster-scoped, slash-separated raw device
+/// path — <Folder/…>/<Driver>/<Device>/<TagGroup/…>/<Tag> — and is
+/// the single string used at every identity seam: ns=Raw NodeIds, the driver wire-reference
+/// (EquipmentTagRefResolver key), the value fan-out / write-routing maps
+/// (DriverHostActor), the historian default tagname + mux interest key, the native-alarm
+/// ConditionId, and ctx.GetTag script paths.
+///
+/// RawPaths are ALWAYS built through this helper — never string-concatenated ad hoc — so the
+/// separator and the segment charset are enforced in exactly one place. Comparison is
+/// case-sensitive ordinal everywhere (see ).
+///
+///
+public static class RawPaths
+{
+ /// The single path separator character. Forbidden inside any segment.
+ public const char Separator = '/';
+
+ /// The path separator as a string (join/split convenience).
+ public const string SeparatorString = "/";
+
+ /// The one comparer for RawPaths and their segments: case-sensitive ordinal.
+ public static StringComparer Comparer => StringComparer.Ordinal;
+
+ ///
+ /// Validate a single path segment. A segment must be non-empty, contain no
+ /// , and carry no leading/trailing whitespace (the separator and
+ /// surrounding whitespace would corrupt the NodeId / round-trip).
+ ///
+ /// The candidate segment (a folder / driver / device / group / tag name).
+ /// A human-readable error when invalid, or when the segment is valid.
+ public static string? ValidateSegment(string? segment)
+ {
+ if (string.IsNullOrEmpty(segment))
+ return "Name must not be empty.";
+ if (segment.IndexOf(Separator) >= 0)
+ return $"Name must not contain '{Separator}'.";
+ if (char.IsWhiteSpace(segment[0]) || char.IsWhiteSpace(segment[^1]))
+ return "Name must not have leading or trailing whitespace.";
+ return null;
+ }
+
+ /// True when passes .
+ /// The candidate segment.
+ /// when the segment is a legal RawPath segment.
+ public static bool IsValidSegment(string? segment) => ValidateSegment(segment) is null;
+
+ ///
+ /// Build a RawPath from ordered segments (root-first). Every segment is validated via
+ /// ; an invalid or empty segment list throws.
+ ///
+ /// The ordered, non-empty segments (root → leaf).
+ /// The slash-joined RawPath.
+ /// A segment is invalid, or the sequence is empty.
+ public static string Build(IEnumerable segments)
+ {
+ ArgumentNullException.ThrowIfNull(segments);
+ var list = segments as IReadOnlyList ?? segments.ToList();
+ if (list.Count == 0)
+ throw new ArgumentException("A RawPath must have at least one segment.", nameof(segments));
+
+ for (var i = 0; i < list.Count; i++)
+ {
+ var error = ValidateSegment(list[i]);
+ if (error is not null)
+ throw new ArgumentException($"Invalid RawPath segment at index {i} ('{list[i]}'): {error}", nameof(segments));
+ }
+
+ return string.Join(Separator, list);
+ }
+
+ /// Build a RawPath from ordered segments (root-first). See .
+ /// The ordered, non-empty segments (root → leaf).
+ /// The slash-joined RawPath.
+ public static string Build(params string[] segments) => Build((IEnumerable)segments);
+
+ ///
+ /// Append a child segment to an existing (already-built) parent RawPath. The child is
+ /// validated; a blank parent yields the (validated) child alone.
+ ///
+ /// The parent RawPath (assumed already valid), or blank for a root segment.
+ /// The child segment to append.
+ /// The combined RawPath.
+ /// The child segment is invalid.
+ public static string Combine(string? parentPath, string childSegment)
+ {
+ var error = ValidateSegment(childSegment);
+ if (error is not null)
+ throw new ArgumentException($"Invalid RawPath segment ('{childSegment}'): {error}", nameof(childSegment));
+
+ return string.IsNullOrEmpty(parentPath) ? childSegment : parentPath + Separator + childSegment;
+ }
+
+ /// Split a RawPath into its ordered segments (root → leaf).
+ /// The RawPath to split.
+ /// The ordered segments; a single-element array for a one-segment path.
+ public static IReadOnlyList Split(string rawPath)
+ {
+ ArgumentNullException.ThrowIfNull(rawPath);
+ return rawPath.Split(Separator);
+ }
+
+ /// The leaf (last) segment of a RawPath.
+ /// The RawPath.
+ /// The final segment.
+ public static string Leaf(string rawPath)
+ {
+ ArgumentNullException.ThrowIfNull(rawPath);
+ var idx = rawPath.LastIndexOf(Separator);
+ return idx < 0 ? rawPath : rawPath[(idx + 1)..];
+ }
+
+ ///
+ /// Get the parent RawPath (everything up to, not including, the leaf). Returns
+ /// for a single-segment path (no parent).
+ ///
+ /// The RawPath.
+ /// The parent RawPath when this returns .
+ /// when a parent exists.
+ public static bool TryParent(string rawPath, out string parent)
+ {
+ ArgumentNullException.ThrowIfNull(rawPath);
+ var idx = rawPath.LastIndexOf(Separator);
+ if (idx < 0)
+ {
+ parent = string.Empty;
+ return false;
+ }
+
+ parent = rawPath[..idx];
+ return true;
+ }
+}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Device.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Device.cs
index 0fca1d16..58b52274 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Device.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Device.cs
@@ -1,6 +1,12 @@
namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
-/// Per-device row for multi-device drivers (Modbus, AB CIP). Optional for single-device drivers.
+///
+/// v3: a device under a . Now UNIVERSAL — every driver has ≥1 device
+/// (single-endpoint drivers get an auto-created default device). Endpoint/connection settings live
+/// in (the Kepware channel/device split: DriverConfig keeps
+/// protocol/channel-level settings; DeviceConfig carries host/endpoint + per-device
+/// settings). The device name is a RawPath segment.
+///
public sealed class Device
{
///
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/DriverInstance.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/DriverInstance.cs
index 6bc962a2..a63cf0e8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/DriverInstance.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/DriverInstance.cs
@@ -13,12 +13,13 @@ public sealed class DriverInstance
public required string ClusterId { get; set; }
///
- /// Logical FK to . Same-cluster binding enforced by
- /// sp_ValidateDraft: Namespace.ClusterId must equal DriverInstance.ClusterId.
+ /// v3: logical FK to a containing ;
+ /// = the driver sits at the cluster root of the Raw tree. Contributes the leading segments of
+ /// every child tag's RawPath.
///
- public required string NamespaceId { get; set; }
+ public string? RawFolderId { get; set; }
- /// Gets or sets the friendly name of this driver instance.
+ /// Gets or sets the friendly name of this driver instance. A RawPath segment.
public required string Name { get; set; }
/// Galaxy | Modbus | AbCip | AbLegacy | S7 | TwinCat | Focas | OpcUaClient
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Equipment.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Equipment.cs
index e6eef1c8..ce537148 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Equipment.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Equipment.cs
@@ -17,14 +17,9 @@ public sealed class Equipment
/// UUIDv4, IMMUTABLE across all generations of the same EquipmentId. Downstream-consumer join key.
public Guid EquipmentUuid { get; set; }
- ///
- /// Optional logical FK to the driver providing data for this equipment.
- /// null = VirtualTag-only / driver-less equipment (no field driver).
- ///
- public string? DriverInstanceId { get; set; }
-
- /// Optional logical FK to a multi-device driver's device.
- public string? DeviceId { get; set; }
+ // v3: equipment no longer binds a driver or device. It references existing raw tags via
+ // UnsTagReference and hosts VirtualTags + ScriptedAlarms. The old DriverInstanceId / DeviceId
+ // binding columns are retired.
/// Logical FK to .
public required string UnsLineId { get; set; }
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/EquipmentImportBatch.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/EquipmentImportBatch.cs
deleted file mode 100644
index 35c58cf2..00000000
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/EquipmentImportBatch.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
-
-///
-/// Staged equipment-import batch per Phase 6.4 Stream B.2. Rows land in the child
-/// table under a batch header; operator reviews + either
-/// drops (via DropImportBatch) or finalises (via FinaliseImportBatch) in one
-/// bounded transaction. The live Equipment table never sees partial state.
-///
-///
-/// User-scoped visibility: the preview modal only shows batches where
-/// equals the current operator. Prevents accidental
-/// cross-operator finalise during concurrent imports. An admin finalise / drop surface
-/// can override this — tracked alongside the UI follow-up.
-///
-/// stamps the moment the batch promoted from staging
-/// into Equipment. Null = still in staging; non-null = archived / finalised.
-///
-public sealed class EquipmentImportBatch
-{
- /// Gets or sets the unique identifier for this batch.
- public Guid Id { get; set; }
-
- /// Gets or sets the cluster identifier.
- public required string ClusterId { get; set; }
-
- /// Gets or sets the user name who created this batch.
- public required string CreatedBy { get; set; }
-
- /// Gets or sets the UTC timestamp when this batch was created.
- public DateTime CreatedAtUtc { get; set; }
-
- /// Gets or sets the total number of rows staged in this batch.
- public int RowsStaged { get; set; }
-
- /// Gets or sets the number of rows accepted in this batch.
- public int RowsAccepted { get; set; }
-
- /// Gets or sets the number of rows rejected in this batch.
- public int RowsRejected { get; set; }
-
- /// Gets or sets the UTC timestamp when this batch was finalised, or null if still in staging.
- public DateTime? FinalisedAtUtc { get; set; }
-
- /// Gets or sets the collection of staged rows in this batch.
- public ICollection Rows { get; set; } = [];
-}
-
-///
-/// One staged row under an . Mirrors the required
-/// + optional columns from the CSV importer's output + an
-/// flag + a string the preview modal
-/// renders.
-///
-public sealed class EquipmentImportRow
-{
- /// Gets or sets the unique identifier for this row.
- public Guid Id { get; set; }
-
- /// Gets or sets the parent batch identifier.
- public Guid BatchId { get; set; }
-
- /// Gets or sets the line number in the source file.
- public int LineNumberInFile { get; set; }
-
- /// Gets or sets a value indicating whether this row was accepted.
- public bool IsAccepted { get; set; }
-
- /// Gets or sets the reason this row was rejected, if applicable.
- public string? RejectReason { get; set; }
-
- /// Gets or sets the Z tag identifier.
- public required string ZTag { get; set; }
-
- /// Gets or sets the machine code.
- public required string MachineCode { get; set; }
-
- /// Gets or sets the SAP identifier.
- public required string SAPID { get; set; }
-
- /// Gets or sets the equipment identifier.
- public required string EquipmentId { get; set; }
-
- /// Gets or sets the equipment UUID.
- public required string EquipmentUuid { get; set; }
-
- /// Gets or sets the equipment name.
- public required string Name { get; set; }
-
- /// Gets or sets the UNS area name.
- public required string UnsAreaName { get; set; }
-
- /// Gets or sets the UNS line name.
- public required string UnsLineName { get; set; }
-
- /// Gets or sets the manufacturer name.
- public string? Manufacturer { get; set; }
-
- /// Gets or sets the equipment model.
- public string? Model { get; set; }
-
- /// Gets or sets the serial number.
- public string? SerialNumber { get; set; }
-
- /// Gets or sets the hardware revision.
- public string? HardwareRevision { get; set; }
-
- /// Gets or sets the software revision.
- public string? SoftwareRevision { get; set; }
-
- /// Gets or sets the year of construction.
- public string? YearOfConstruction { get; set; }
-
- /// Gets or sets the asset location.
- public string? AssetLocation { get; set; }
-
- /// Gets or sets the manufacturer URI.
- public string? ManufacturerUri { get; set; }
-
- /// Gets or sets the device manual URI.
- public string? DeviceManualUri { get; set; }
-
- /// Gets or sets the parent batch.
- public EquipmentImportBatch? Batch { get; set; }
-}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Namespace.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Namespace.cs
deleted file mode 100644
index f7324fb2..00000000
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Namespace.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
-
-namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
-
-///
-/// OPC UA namespace served by a cluster. Generation-versioned —
-/// namespaces are content (affect what consumers see at the endpoint), not topology.
-///
-public sealed class Namespace
-{
- /// Gets or sets the row identifier for this namespace.
- public Guid NamespaceRowId { get; set; }
-
- /// Stable logical ID, e.g. "LINE3-OPCUA-equipment". Globally unique in v2.
- public required string NamespaceId { get; set; }
-
- /// Gets or sets the cluster identifier.
- public required string ClusterId { get; set; }
-
- /// Gets or sets the namespace kind.
- public required NamespaceKind Kind { get; set; }
-
- /// E.g. "urn:zb:warsaw-west:equipment". Unique fleet-wide per generation.
- public required string NamespaceUri { get; set; }
-
- /// Gets or sets a value indicating whether the namespace is enabled.
- public bool Enabled { get; set; } = true;
-
- /// Gets or sets optional notes about the namespace.
- public string? Notes { get; set; }
-
- /// Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.
- public byte[] RowVersion { get; set; } = Array.Empty();
-
- /// Gets or sets the associated server cluster.
- public ServerCluster? Cluster { get; set; }
-}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/RawFolder.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/RawFolder.cs
new file mode 100644
index 00000000..c3947912
--- /dev/null
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/RawFolder.cs
@@ -0,0 +1,30 @@
+namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
+
+///
+/// v3 Raw-tree driver-organizing folder. Nestable (Kepware-style) directly under a cluster or
+/// under another . Folders group rows; they
+/// contribute the leading segments of a driver's RawPath.
+///
+public sealed class RawFolder
+{
+ /// Gets or sets the database row identifier (PK).
+ public Guid RawFolderRowId { get; set; }
+
+ /// Stable logical ID, unique fleet-wide.
+ public required string RawFolderId { get; set; }
+
+ /// Logical FK to — the folder is cluster-rooted.
+ public required string ClusterId { get; set; }
+
+ /// Logical FK to a parent ; = root under the cluster.
+ public string? ParentRawFolderId { get; set; }
+
+ /// Sibling-unique folder name. A RawPath segment: no /, no lead/trail whitespace.
+ public required string Name { get; set; }
+
+ /// Sibling display ordering.
+ public int SortOrder { get; set; }
+
+ /// Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.
+ public byte[] RowVersion { get; set; } = Array.Empty();
+}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs
index 192964f4..ffcc94b2 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs
@@ -47,6 +47,6 @@ public sealed class ServerCluster
// Navigation
/// Gets or sets the collection of cluster nodes.
public ICollection Nodes { get; set; } = [];
- /// Gets or sets the collection of namespaces in the cluster.
- public ICollection Namespaces { get; set; } = [];
+ /// Gets or sets the collection of root-level Raw-tree folders in the cluster.
+ public ICollection RawFolders { get; set; } = [];
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Tag.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Tag.cs
index 32fefab5..0bc1e25f 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Tag.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Tag.cs
@@ -3,46 +3,34 @@ using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
///
-/// One canonical tag (signal) in a cluster's generation. set ⟺ the
-/// tag participates in the Equipment tree. A GalaxyMxGateway-bound equipment tag is an
-/// ordinary equipment tag (GalaxyMxGateway is a standard Equipment-kind driver) that carries its
-/// Galaxy attribute reference in TagConfig.FullName — there is no separate alias concept.
+/// v3 raw-only tag (signal). A tag is authored ONCE, under a in the Raw
+/// tree; its identity is its RawPath
+/// (<Folder/…>/<Driver>/<Device>/<TagGroup/…>/<Name>). UNS
+/// surfaces it by reference (), never by re-authoring. The tag's
+/// driver-specific address lives inside as an ordinary field (what the
+/// driver dials), not as system identity.
///
public sealed class Tag
{
- ///
- /// Gets or sets the unique database row identifier for the tag.
- ///
+ /// Gets or sets the unique database row identifier for the tag (PK).
public Guid TagRowId { get; set; }
- ///
- /// Gets or sets the tag identifier.
- ///
+ /// Gets or sets the stable logical tag identifier (unique fleet-wide).
public required string TagId { get; set; }
- ///
- /// Gets or sets the driver instance identifier for this tag.
- ///
- public required string DriverInstanceId { get; set; }
+ /// v3: required logical FK to . Every tag lives under a device.
+ public required string DeviceId { get; set; }
///
- /// Gets or sets the device identifier.
+ /// Optional logical FK to a containing ;
+ /// = the tag sits directly under its device. Contributes the middle
+ /// segments of the tag's RawPath.
///
- public string? DeviceId { get; set; }
+ public string? TagGroupId { get; set; }
- ///
- /// Set when the tag belongs to an Equipment; NULL for FolderPath-scoped (namespace-root) tags.
- ///
- public string? EquipmentId { get; set; }
-
- ///
- /// Gets or sets the tag name.
- ///
+ /// Gets or sets the tag name. A RawPath segment: no /, no lead/trail whitespace.
public required string Name { get; set; }
- /// Only used when is NULL (FolderPath-scoped namespace tag).
- public string? FolderPath { get; set; }
-
/// OPC UA built-in type name (Boolean / Int32 / Float / etc.).
public required string DataType { get; set; }
@@ -51,7 +39,7 @@ public sealed class Tag
///
public required TagAccessLevel AccessLevel { get; set; }
- /// Opt-in for write retry eligibility.
+ /// Opt-in for write retry eligibility (R2 resilience contract — retained in v3).
public bool WriteIdempotent { get; set; }
///
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/TagGroup.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/TagGroup.cs
new file mode 100644
index 00000000..cd0a32b4
--- /dev/null
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/TagGroup.cs
@@ -0,0 +1,30 @@
+namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
+
+///
+/// v3 Raw-tree tag-organizing group. Nestable (Kepware-style) directly under a
+/// or under another . Groups contribute the middle
+/// segments of a tag's RawPath (between the device and the tag name).
+///
+public sealed class TagGroup
+{
+ /// Gets or sets the database row identifier (PK).
+ public Guid TagGroupRowId { get; set; }
+
+ /// Stable logical ID, unique fleet-wide.
+ public required string TagGroupId { get; set; }
+
+ /// Logical FK to — the group lives under a device.
+ public required string DeviceId { get; set; }
+
+ /// Logical FK to a parent ; = root under the device.
+ public string? ParentTagGroupId { get; set; }
+
+ /// Sibling-unique group name. A RawPath segment: no /, no lead/trail whitespace.
+ public required string Name { get; set; }
+
+ /// Sibling display ordering.
+ public int SortOrder { get; set; }
+
+ /// Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.
+ public byte[] RowVersion { get; set; } = Array.Empty();
+}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/UnsTagReference.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/UnsTagReference.cs
new file mode 100644
index 00000000..1b8e4fab
--- /dev/null
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/UnsTagReference.cs
@@ -0,0 +1,35 @@
+namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
+
+///
+/// v3 UNS projection row: a reference from an to an existing raw
+/// . UNS authoring is reference-only — equipment no longer authors
+/// TagConfig or binds a driver; it points at raw tags (optionally under a display-name
+/// override). The backing raw tag is the single value source; the UNS node fans out from it.
+///
+public sealed class UnsTagReference
+{
+ /// Gets or sets the database row identifier (PK).
+ public Guid UnsTagReferenceRowId { get; set; }
+
+ /// Stable logical ID, unique fleet-wide.
+ public required string UnsTagReferenceId { get; set; }
+
+ /// Logical FK to — the referencing equipment.
+ public required string EquipmentId { get; set; }
+
+ /// Logical FK to — the backing raw tag (same cluster as the equipment).
+ public required string TagId { get; set; }
+
+ ///
+ /// Optional UNS display-name override; = use the raw tag's Name.
+ /// The effective name must be unique within the equipment across references, VirtualTags, and
+ /// ScriptedAlarms (enforced at authoring and at the deploy gate).
+ ///
+ public string? DisplayNameOverride { get; set; }
+
+ /// Sibling display ordering within the equipment's Tags list.
+ public int SortOrder { get; set; }
+
+ /// Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.
+ public byte[] RowVersion { get; set; } = Array.Empty();
+}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs
deleted file mode 100644
index 41969599..00000000
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NamespaceKind.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace ZB.MOM.WW.OtOpcUa.Configuration.Enums;
-
-/// OPC UA namespace kind. One of each kind per cluster per generation.
-public enum NamespaceKind
-{
- ///
- /// Equipment namespace — raw signals from native-protocol drivers (Modbus, AB CIP, AB Legacy,
- /// S7, TwinCAT, FOCAS, and OpcUaClient when gatewaying raw equipment). UNS 5-level hierarchy
- /// applies.
- ///
- Equipment,
-
- ///
- /// 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
- /// driver lands.
- ///
- Simulated,
-}
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 9d622322..ac3e43fc 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
@@ -84,7 +84,6 @@ public sealed class DriverTypeRegistry
/// Per-driver-type metadata used by the Core, validator, and Admin UI.
/// Driver type name (matches DriverInstance.DriverType column values).
-/// Which namespace kinds this driver type may be bound to.
/// JSON Schema (Draft 2020-12) the driver's DriverConfig column must validate against.
/// JSON Schema for DeviceConfig (multi-device drivers); null if the driver has no device layer.
/// JSON Schema for TagConfig; required for every driver since every driver has tags.
@@ -95,24 +94,11 @@ public sealed class DriverTypeRegistry
/// hybrid-formula constants, and whether process-level MemoryRecycle / scheduled-
/// recycle protections apply (Tier C only). Every registered driver type must declare one.
///
+// v3: AllowedNamespaceKinds retired with the Namespace entity — the two OPC UA namespaces (Raw/UNS)
+// are implicit, so a driver type no longer declares a namespace-kind compatibility bitmask.
public sealed record DriverTypeMetadata(
string TypeName,
- NamespaceKindCompatibility AllowedNamespaceKinds,
string DriverConfigJsonSchema,
string? DeviceConfigJsonSchema,
string TagConfigJsonSchema,
DriverTier Tier);
-
-/// Bitmask of namespace kinds a driver type may populate.
-[Flags]
-public enum NamespaceKindCompatibility
-{
- /// Driver does not populate any namespace (invalid; should never appear in registry).
- None = 0,
-
- /// Driver may populate Equipment-kind namespaces (UNS path, Equipment rows).
- Equipment = 1,
-
- /// Driver may populate the future Simulated namespace (replay driver — not in v2.0).
- Simulated = 4,
-}