docs: source-verified deferment register + correct 17 drifted docs
v2-ci / build (push) Successful in 4m52s
v2-ci / unit-tests (push) Failing after 15m58s

Adds deferment.md — a source-verified inventory of new-driver status, all 17
open issues, in-code deferrals, open live gates and plan bookkeeping. Every
claim was checked against src/ and git, not against documentation.

Headline finding: three subsystems are authored, persisted and shipped but
never executed —
  * Node ACLs: IPermissionEvaluator/TriePermissionEvaluator have zero
    production consumers and OtOpcUaNodeManager never references them, yet
    ClusterAcls.razor authors NodeAcl rows and ConfigComposer.cs:51 ships them
    in every artifact. An authored deny rule has no effect.
  * IRediscoverable / IHostConnectivityProbe raise into the void (#518/#507);
    nothing ever writes a DriverHostStatus row.
  * DriverTypeRegistry is vestigial, so no factory passes a tier and every
    driver runs Tier A with the Tier-C protections dormant.

Also records the Calculation driver as picker-visible but unauthorable
(DriverConfigModal has no case) — the "registered but unauthorable" class
recurring after the Sql picker defect — and notes that no parity test guards
DriverConfigModal/DeviceModal, which is why it survived review.

Documentation corrections (source-verified):
  * ReadWriteOperations.md claimed "a denied read never hits the driver" via
    four types that do not exist in src/. Bannered + struck through; a security
    review reading that page would have concluded a per-node ACL gate exists.
  * CLAUDE.md: the Change Detection sentence was false (DriverHost consumes
    nothing); the mesh Phase 4 and Phase 5 live gates and the auto-down 1-vs-1
    gate had all PASSED; the ScriptedAlarmState table was already dropped.
  * driver-expansion tracking: Modbus RTU and SQL poll are merged, not
    pending — its command table would have made someone rebuild two shipped
    drivers in a fresh worktree.
  * drivers/README.md: dead DriverTypeRegistry paragraph, retired
    SystemPlatform namespace kind, missing Sql + Calculation rows, missing
    Modbus RTU-over-TCP transport.
  * TwinCAT.md/Galaxy.md promised an address-space rebuild that never happens.
  * Historian.md gained the #491 unproven-value-capture pointer.
  * IncrementalSync.md and AddressSpace.md bannered as wholesale v2-era (the
    rewrite is recorded as still owed, not done here); four v2 status docs
    bannered as historical; three wrong-name-for-a-live-type fixes.

Left deliberately untouched: the secrets NoOpSecretReplicator line, which
makes a security claim and needs the real behaviour identified rather than a
rename.
This commit is contained in:
Joseph Doherty
2026-07-27 17:26:20 -04:00
parent 90bdaa4437
commit e08855fb9d
18 changed files with 547 additions and 45 deletions
+22
View File
@@ -1,5 +1,27 @@
# Address Space
> ⚠️ **Accuracy warning (audited 2026-07-27) — this page is v2-era and contradicts the shipped v3
> address space.** Corrections, in order of how badly they mislead:
>
> - **There is no "single custom namespace".** v3 exposes **two**:
> `https://zb.com/otopcua/raw` (`s=<RawPath>`) and `https://zb.com/otopcua/uns`
> (`s=<Area>/<Line>/<Equipment>/<EffectiveName>`), registered together at
> `OtOpcUaNodeManager.cs:45`. Identity authority is `V3NodeIds` + `AddressSpaceRealm`. The retired
> `https://zb.com/otopcua/ns` survives only in a comment marking it retired (`V3NodeIds.cs:17`).
> - **`Phase7Applier` / `Phase7Composer` / `GalaxyTagPlan` do not exist**, nor do the file paths cited
> for them. Renamed by `40e8a23e` to `AddressSpaceApplier` / `AddressSpaceComposer`
> (`src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/`); the composition result type is
> `AddressSpaceComposition` (`AddressSpaceComposer.cs:13`).
> - **The `SystemPlatform` namespace kind is retired** — Galaxy is a standard Equipment-kind driver.
> - **`GenericDriverNodeManager` is test scaffolding**, not a production dispatch path
> (`GenericDriverNodeManager.cs:71`).
> - **The §Rediscovery section is wrong**: nothing consumes `OnRediscoveryNeeded`
> ([#518](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/518)), and the driver list is stale
> (MQTT and MTConnect now raise it too).
>
> For the current design see the "v3 OPC UA Address Space (Batch 4)" section of `CLAUDE.md`,
> `docs/Raw.md`, and `docs/Uns.md`.
Address-space construction is a two-layer system. The **driver-facing layer** is the streaming builder: a driver implements `ITagDiscovery.DiscoverAsync` (`src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ITagDiscovery.cs`) and emits `Folder` / `Variable` / `AddProperty` calls into an `IAddressSpaceBuilder` as it walks its backend — no buffering of the whole tree. `GenericDriverNodeManager` (`src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/GenericDriverNodeManager.cs`) wraps that builder to capture alarm-condition sinks and routes alarm events from the driver to them. The **SDK materialization layer** turns the resulting node descriptions into live OPC UA nodes: `OpcUaPublishActor` drives the write-only `IOpcUaAddressSpaceSink`, whose production binding `SdkAddressSpaceSink` (`src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkAddressSpaceSink.cs`) forwards to `OtOpcUaNodeManager` (`src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OtOpcUaNodeManager.cs`), a `CustomNodeManager2` subclass that owns the `FolderState` / `BaseDataVariableState` instances. The same code path serves Galaxy object hierarchies, Modbus PLC registers, AB CIP tags, TwinCAT symbols, FOCAS CNC parameters, and OPC UA Client aggregations — Galaxy is one driver of seven, not the driver.
## Root folder