Files
lmxopcua/docs/plans/2026-07-15-v3-batch1-PR.md
Joseph Doherty 080e958d94
v2-ci / build (pull_request) Successful in 3m31s
v2-ci / unit-tests (pull_request) Failing after 11m16s
docs(v3): Batch 1 schema/identity note in Configuration.md + PR description
2026-07-15 22:05:19 -04:00

69 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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**
(`<Folder/…>/<Driver>/<Device>/<TagGroup/…>/<Tag>`). 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<TDef>` 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 24 (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 24 land.
- Live driver IntegrationTests + one pre-existing `AbCip_Green_AgainstSim` fixture-probe failure
(AB CIP sim handshake — environment/fixture gate, untouched).