ADR 0022: Device discovery classifies on the type-definition namespace — a recognized PA-DIM / OPC UA-DI type is a data-plane signal¶
Status: Accepted Date: 2026-07-13 Issue: #934
Context¶
ADR 0020 decided that
Device Discovery classifies each discovered OPC UA node onto a control plane
— data-plane (field device ⇒ template-free ControlModule instance) or
service-plane (module/skid ⇒ Unit + serviceBinding). The signal it
shipped is structural: Methods present ⇒ service-plane; Variables only ⇒
data-plane. ADR 0020 explicitly forecast a stronger signal it did not yet
build — "A PA-DIM (PADIMType) or MTP/PEA type-definition, when present, is
a strong positive signal for the respective plane" — and filed it as
follow-up B (#928).
The structural proxy has a real blind spot. A discovered field device that a
server models as a full PA-DIM object still exposes only Variables, so the
proxy lands it on the data-plane by accident of shape, not by recognition —
and it renders identically to a node the wizard merely defaulted to
ControlModule because it had nothing better to say. The operator cannot see
that the wizard recognized a standards-modeled device versus fell back to a
default. That missing provenance is what makes native PA-DIM ingestion
(#935 — variable roles/units, NE 107 health) hard to build on top: there is
no authoritative "this is a PA-DIM device" bit to key on.
#928 was decomposed (2026-07-13) into #934 (this decision), #935 (PA-DIM ingestion + NE 107 health — CRD surface, blocked on the OPC 30081 spec), and #936 (native MTP service model — blocked on VDI/VDE/NAMUR 2658-4:2022 and the unfinished ISA-88/MTP alignment). This ADR covers only the verifiable, non-blocked slice: recognizing a node's type-definition when it resolves into a public device-model companion namespace.
Two namespace URIs were verified 2026-07-13 against the OPC Foundation online
reference (reference.opcfoundation.org) — not taken from memory, per the #928
caution that a prior companion-spec identifier (OPC 40080) proved
unverifiable:
- PA-DIM —
http://opcfoundation.org/UA/PADIM/(OPC 30081, Annex A.1). - OPC UA for Devices (DI) —
http://opcfoundation.org/UA/DI/(OPC 10000-100;DeviceTypeand subtypes).
Unlike the numeric namespace index (which is assigned per server and
drifts), the namespace URI is stable across servers — so it is the correct
thing to key classification on. The wizard already resolves node namespace
URIs from the server's cached NamespaceArray (the #303 drift-resistant
address work); this reuses that machinery for the type-definition's NodeID.
Decision¶
Device discovery resolves each candidate's type-definition namespace URI and, when it is a recognized device-model companion namespace (PA-DIM or OPC UA-DI), treats that as a strong positive data-plane signal — surfaced to the operator as recognition provenance. The structural Methods-vs-Variables proxy remains the fallback when no recognized type-definition is present.
pkg/opcuaclientresolves the type-definition NodeID's namespace URI (BrowseChild.TypeDefinitionNamespaceURI) via the cachedNamespaceArray, and computes a control-plane hint (BrowseChild.ClassSignal) with a single exported pure function,PlaneSignalFor(uri), returningPlaneSignalData("data") for the two recognized URIs and""otherwise. Both fields ride through toSearchHit(the shape the wizard consumes) as additive,omitemptyJSON.- The wizard (
discover.js) labels a recognized candidate ("PA-DIM device" / "OPC UA device") in the scan list and on its review row. Because every leaf candidate already defaults toControlModule(ADR 0020), the signal does not change the default — it changes the operator's information: a positive classification with visible provenance, distinguished from a bare default. The "Emit as" dropdown stays the manual override. - Recognition is exact-match on the namespace URI, not substring. A
superset URI (a hypothetical
.../PADIM/Extras/) does not match — new companion namespaces must be added deliberately, never absorbed by prefix.
Service-plane (MTP / PEA) type-definition recognition is deliberately out
of scope. Unlike PA-DIM, MTP has no stable public PEAType companion
namespace to key on — its OPC UA runtime binding (VDI/VDE/NAMUR 2658 Blatt
5.1) is not a distinct namespace — so service-plane classification stays
structural until #936. This ADR does not claim PA-DIM conformance: it
recognizes the type-definition namespace only; ingesting the PA-DIM
information model (variable roles/units, NE 107 health) is #935.
Alternatives Considered¶
- Match the numeric namespace index (e.g. "type-def in ns=5 ⇒ PA-DIM"): rejected — the index is server-assigned and unstable; only the URI is portable. This is the same reasoning as the #303 drift-resistant address.
- Match by type-definition BrowseName (e.g.
DeviceType,PADIMType): rejected — a BrowseName is not namespace-qualified in the wire form we hold and collides across vendors; the namespace URI is the authoritative, unambiguous key. - Reintroduce the #348/#857-deleted companion-spec registry to classify
many device types: rejected — ADR 0020 already ruled this out. Only the two
verified namespace URIs are recognized, not a general registry, and one of
the old registry's identifiers (
OPC 40080) was unverifiable. - Flip the default to
Uniton a service-plane type-definition signal: not built here — folded into #936 because there is no reliable PEA type-definition signal to flip on. - Substring/prefix match on the URI (tolerate versioned suffixes): rejected — silent over-recognition of unintended namespaces is worse than requiring a deliberate addition; recognition is exact.
Consequences¶
- Additive API surface, no CRD change. Two
omitemptyfields (typeDefinitionNamespaceURI,classSignal) appear on the/discovery/opcua/search(and/browse) response DTOs. Older clients ignore them; the field is empty for servers that expose no recognizable type-definition, so the structural path is unchanged for them. - A foundation for #935. The authoritative "this is a PA-DIM device" bit now exists at discovery time, which native PA-DIM ingestion keys on.
- Bounded blast radius.
PlaneSignalForis a pure two-case function with exact-match semantics and direct unit tests; adding a future recognized namespace is a one-line, deliberate change. - No conformance claim. Recognition ≠ ingestion ≠ conformance. The wizard says "recognized as a PA-DIM device," not "PA-DIM conformant."
- Reversibility: high — client-side labelling plus two additive backend fields, no schema or persisted-state change.
Related Documentation¶
- ADR 0020: OPC UA discovery classifies each node onto a control plane — the classification decision this ADR sharpens with a type-definition signal
- docs/device-discovery.md — the wizard this ADR extends