From 860deb8e0d081bb4371bdf94de49fc8171ce851f Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 18 Apr 2026 11:43:15 -0400 Subject: [PATCH] =?UTF-8?q?Phase=203=20PR=2020=20=E2=80=94=20lmx-followups?= =?UTF-8?q?.md:=20track=20remaining=20Galaxy-bridge=20tasks=20after=20PR?= =?UTF-8?q?=2019=20(HistoryReadAtTime/Events=20Proxy=20wiring,=20write-gat?= =?UTF-8?q?ing=20by=20role,=20Admin=20UI=20cert=20trust,=20live-LDAP=20int?= =?UTF-8?q?egration=20test,=20full-stack=20Galaxy=20smoke,=20multi-driver?= =?UTF-8?q?=20test,=20per-host=20dashboard).=20Documents=20what=20each=20i?= =?UTF-8?q?tem=20depends=20on,=20the=20shipped=20surface=20it=20builds=20o?= =?UTF-8?q?n,=20and=20the=20minimal=20to-do=20so=20a=20future=20session=20?= =?UTF-8?q?can=20pick=20any=20one=20off=20in=20isolation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/v2/lmx-followups.md | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 docs/v2/lmx-followups.md diff --git a/docs/v2/lmx-followups.md b/docs/v2/lmx-followups.md new file mode 100644 index 0000000..e16c26f --- /dev/null +++ b/docs/v2/lmx-followups.md @@ -0,0 +1,106 @@ +# LMX Galaxy bridge — remaining follow-ups + +State after PR 19: the Galaxy driver is functionally at v1 parity through the +`IDriver` abstraction; the OPC UA server runs with LDAP-authenticated +Basic256Sha256 endpoints and alarms are observable through +`AlarmConditionState.ReportEvent`. The items below are what remains LMX- +specific before the stack can fully replace the v1 deployment, in +rough priority order. + +## 1. Proxy-side `IHistoryProvider` for `ReadAtTime` / `ReadEvents` + +**Status**: Host-side IPC shipped (PR 10 + PR 11). Proxy consumer not written. + +PR 10 added `HistoryReadAtTimeRequest/Response` on the IPC wire and +`MxAccessGalaxyBackend.HistoryReadAtTimeAsync` delegates to +`HistorianDataSource.ReadAtTimeAsync`. PR 11 did the same for events +(`HistoryReadEventsRequest/Response` + `GalaxyHistoricalEvent`). The Proxy +side (`GalaxyProxyDriver`) doesn't call those yet — `Core.Abstractions.IHistoryProvider` +only exposes `ReadRawAsync` + `ReadProcessedAsync`. + +**To do**: +- Extend `IHistoryProvider` with `ReadAtTimeAsync(string, DateTime[], …)` and + `ReadEventsAsync(string?, DateTime, DateTime, int, …)`. +- `GalaxyProxyDriver` calls the new IPC message kinds. +- `DriverNodeManager` wires the new capability methods onto `HistoryRead` + `AtTime` + `Events` service handlers. +- Integration test: OPC UA client calls `HistoryReadAtTime` / `HistoryReadEvents`, + value flows through IPC to the Host's `HistorianDataSource`, back to the client. + +## 2. Write-gating by role + +**Status**: `RoleBasedIdentity.Roles` populated on the session (PR 19) but +`DriverNodeManager.OnWriteValue` doesn't consult it. + +CLAUDE.md defines the role set: `ReadOnly` / `WriteOperate` / `WriteTune` / +`WriteConfigure` / `AlarmAck`. Each `DriverAttributeInfo.SecurityClassification` +maps to a required role for writes. + +**To do**: +- Add a `RoleRequirements` table: `SecurityClassification` → required role. +- `OnWriteValue` reads `context.UserIdentity` → cast to `RoleBasedIdentity` + → check role membership before calling `IWritable.WriteAsync`. Return + `BadUserAccessDenied` on miss. +- Unit test against a fake `ISystemContext` with varying role sets. + +## 3. Admin UI client-cert trust management + +**Status**: Server side auto-accepts untrusted client certs when the +`AutoAcceptUntrustedClientCertificates` option is true (dev default). +Production deployments want operator-controlled trust via the Admin UI. + +**To do**: +- Surface the server's rejected-certificate store in the Admin UI. +- Page to move certs between `rejected` / `trusted`. +- Flip `AutoAcceptUntrustedClientCertificates` to false once Admin UI is the + trust gate. + +## 4. Live-LDAP integration test + +**Status**: PR 19 unit-tested the auth-flow shape; the live bind path is +exercised only by the pre-existing `Admin.Tests/LdapLiveBindTests.cs` which +uses the same Novell library against a running GLAuth at `localhost:3893`. + +**To do**: +- Add `OpcUaServerIntegrationTests.Valid_username_authenticates_against_live_ldap` + with the same skip-when-unreachable guard. +- Assert `session.Identity` on the server side carries the expected role + after bind — requires exposing a test hook or reading identity from a + new `IHostConnectivityProbe`-style "whoami" variable in the address space. + +## 5. Full Galaxy live-service smoke test against the merged v2 stack + +**Status**: Individual pieces have live smoke tests (PR 5 MXAccess, PR 13 +probe manager, PR 14 alarm tracker), but the full loop — OPC UA client → +`OtOpcUaServer` → `GalaxyProxyDriver` (in-process) → named-pipe to +Galaxy.Host subprocess → live MXAccess runtime → real Galaxy objects — has +no single end-to-end smoke test. + +**To do**: +- Test that spawns the full topology, discovers a deployed Galaxy object, + subscribes to one of its attributes, writes a value back, and asserts the + write round-tripped through MXAccess. Skip when ArchestrA isn't running. + +## 6. Second driver instance on the same server + +**Status**: `DriverHost.RegisterAsync` supports multiple drivers; the OPC UA +server creates one `DriverNodeManager` per driver and isolates their +subtrees under distinct namespace URIs. Not proven with two active +`GalaxyProxyDriver` instances pointing at different Galaxies. + +**To do**: +- Integration test that registers two driver instances, each with a distinct + `DriverInstanceId` + endpoint in its own session, asserts nodes from both + appear under the correct subtrees, alarm events land on the correct + instance's condition nodes. + +## 7. Host-status per-AppEngine granularity → Admin UI dashboard + +**Status**: PR 13 ships per-platform/per-AppEngine `ScanState` probing; PR 17 +surfaces the resulting `OnHostStatusChanged` events through OPC UA. Admin +UI doesn't render a per-host dashboard yet. + +**To do**: +- SignalR hub push of `HostStatusChangedEventArgs` to the Admin UI. +- Dashboard page showing each tracked host, current state, last transition + time, failure count.