From 080e958d94218201a4dc1d3da1a2cf13dc0e34b0 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 15 Jul 2026 22:05:19 -0400 Subject: [PATCH] docs(v3): Batch 1 schema/identity note in Configuration.md + PR description --- docs/Configuration.md | 11 +++++ docs/plans/2026-07-15-v3-batch1-PR.md | 68 +++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 docs/plans/2026-07-15-v3-batch1-PR.md diff --git a/docs/Configuration.md b/docs/Configuration.md index e1fdd181..fdcac78c 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -1,5 +1,16 @@ # Configuration Reference +> **v3 in progress (Batch 1 landed — schema + RawPath identity).** The config **DB schema** was +> replaced by the greenfield v3 model: a driver-centric **Raw tree** +> (`Cluster → RawFolder → DriverInstance → Device → TagGroup → Tag`) plus a reference-only **UNS** +> projection (`UnsTagReference`). A tag's identity is now its **RawPath** +> (`////`), not a `TagConfig.FullName` blob; the +> `Namespace`/`NamespaceKind`/`EquipmentImportBatch` entities are retired, and connection endpoints +> moved from `DriverConfig` into each `Device`'s `DeviceConfig`. The two OPC UA namespaces (`ns=Raw` / +> `ns=UNS`) and the `/raw` authoring UI arrive in later v3 batches; **Batch 1 leaves the address space +> deliberately dark** (drivers connect, but no tag variables materialize yet). The `appsettings*.json` +> surface below is unchanged. Full design: `docs/plans/2026-07-15-raw-uns-two-subtree-v3-design.md`. + This is the live configuration reference for the OtOpcUa Host (`src/Server/ZB.MOM.WW.OtOpcUa.Host/`). It enumerates the `appsettings*.json` sections, the bound Options classes, and the `OTOPCUA_*` / sim-endpoint environment variables — every entry grounded in source. Two related concerns get their own dedicated pages and are **only summarised + linked** here, not duplicated: diff --git a/docs/plans/2026-07-15-v3-batch1-PR.md b/docs/plans/2026-07-15-v3-batch1-PR.md new file mode 100644 index 00000000..89d6e7ac --- /dev/null +++ b/docs/plans/2026-07-15-v3-batch1-PR.md @@ -0,0 +1,68 @@ +# v3 Batch 1 — greenfield schema + RawPath identity rewiring + +**Branch:** `v3/batch1-schema-identity` → `master` +**Plan:** `docs/plans/2026-07-15-v3-batch1-schema-identity-plan.md` · **Design:** `docs/plans/2026-07-15-raw-uns-two-subtree-v3-design.md` + +Greenfield, compatibility-breaking. The config schema and every identity seam now speak **RawPath** +(`////`). The full solution builds and all macOS-safe +tests pass; the OPC UA address space is **deliberately dark** (drivers connect, no tag variables +materialize) until Batch 4. + +## What changed + +- **Schema (greenfield):** new `RawFolder` / `TagGroup` / `UnsTagReference`; reshaped `DriverInstance` + (−`NamespaceId`, +`RawFolderId?`), `Tag` (raw-only: req `DeviceId`, +`TagGroupId?`, + −`DriverInstanceId`/`EquipmentId`/`FolderPath`, kept `WriteIdempotent`), `Equipment` (−driver/device + binding); `Namespace` / `NamespaceKind` / `EquipmentImportBatch` retired. Single squashed `V3Initial` + migration (stored procs audited — the vestigial generation-model procs were rewritten to v3-valid + stubs; `sp_ComputeGenerationDiff` diffs the new tables). +- **Identity:** new `Commons/Types/RawPaths.cs` helper; `TagConfigIntent` sheds `FullName`; + `EquipmentTagRefResolver` is byName(RawPath)-only (blob-fallback deleted); new + `RawTagEntry(RawPath, TagConfig, WriteIdempotent, DeviceName)` delivery record. All 8 drivers + re-keyed: the per-driver `*EquipmentTagParser` became `*TagDefinitionFactory.FromTagConfig`, options + `Tags` → `RawTags`, `TagConfig` key normalization (`nodeId` / `attributeRef`; `deviceHostAddress` + dropped). +- **Endpoint → DeviceConfig:** new `DriverDeviceConfigMerger` (Commons) merges DriverConfig + per-device + DeviceConfig; multi-device drivers reconstruct their `Devices[]` from Device rows; the artifact injects + the merged config + `rawTags` at spawn. +- **Pipeline:** `ConfigComposer` snapshots the new tables; `DeploymentArtifact` flattens per-driver + `RawTagEntry` lists keyed by RawPath (via `RawPathResolver`) + emits an empty (dark) equipment-tag + plan set; `AddressSpaceComposer`/walker compose folders + VirtualTags + ScriptedAlarms only; + `DriverHostActor` maps re-keyed to RawPath; `DraftValidator` gains `RawNameInvalid` / + `HistorianTagnameTooLong` / `UnsEffectiveNameCollision`. +- **AdminUI (compile-only stubs):** Namespace pages → retired banners; driver pages dropped the + pre-declared Tags editor + NamespaceId; `UnsTreeService` tag-authoring returns "moved to the Raw tree + (/raw) in v3 Batch 2". (Batch 2/3 build the real `/raw` + reference UI.) + +## Verification gate (all four items) + +1. **Build + test green.** Full solution builds (0 errors). macOS-safe unit suites: Commons 196, + Core 260, Core.Abstractions 134, **Configuration 107**, Runtime 355 (42 dark-Batch-4 skips), + ControlPlane 78, OpcUaServer 335 (4 skips), AdminUI 507 (3 skips), + all 8 driver unit suites + (Modbus 315, S7 264, AbCip 342, AbLegacy 213, TwinCAT 192, FOCAS 272, OpcUaClient 138, Galaxy 313) + and the 6 driver IntegrationTests projects compile. Enum-serialization round-trip coverage preserved. +2. **Fresh-DB migration.** `V3Initial` applies clean to a scratch DB; `SchemaComplianceTests` 8/8. +3. **docker-dev boot (live).** Volume wiped → `V3Initial` applied → both central nodes reached Akka + Up → a seeded Modbus driver **spawned and connected** to the `10.100.0.35:5020` fixture + (`DriverInstance MAIN-modbus: connected`), deployment **sealed (acks=2)**; AdminUI HTTP 200 on + `/`, `/clusters`, `/uns` with 0 unhandled exceptions. +4. **Dark address space (Client.CLI browse).** Recursive browse of `opc.tcp://localhost:4840`: the raw + tag `HR200` and the driver have **0 occurrences**; the custom namespace `ns=2` holds only the empty + `OtOpcUa` root — no authored variables materialize (Batch 4 lights them up). + +## AdminUI Batch-1 stubs (Batch 2/3 replace) + +Namespace pages (`NamespaceEdit`, `ClusterNamespaces`) → banners; the 8 driver pages' pre-declared Tags +editors + Namespace bindings removed; `DriverIdentitySection` Namespace dropdown removed; +`UnsTreeService.CreateTagAsync`/`UpdateTagAsync` return the "moved to /raw" failure; per-equipment tag +lists empty. + +## Deferred (owned by later batches, not regressions) + +- `/raw` project tree + reference-picker UI, dual `ns=Raw`/`ns=UNS` namespaces + tag-variable + materialization, `{{equip}}` reference-relative resolution — Batches 2–4 (address space intentionally + dark now). +- User-facing docs beyond the `Configuration.md` v3 note (they describe the not-yet-built UI/address + space) — updated as Batches 2–4 land. +- Live driver IntegrationTests + one pre-existing `AbCip_Green_AgainstSim` fixture-probe failure + (AB CIP sim handshake — environment/fixture gate, untouched).