# 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.