Phase 3 PR 20 — lmx-followups.md #19
106
docs/v2/lmx-followups.md
Normal file
106
docs/v2/lmx-followups.md
Normal file
@@ -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.
|
||||
Reference in New Issue
Block a user