Task #209 exit gate — seed-creds fix + live Modbus verification (4/5 stages)
Booted the server against the Modbus seed end-to-end to exercise the factory wiring shipped in #216 + #217. Surfaced two real issues with the seeds themselves; fixed both: 1. **Missing ClusterNodeCredential.** `sp_GetCurrentGenerationForCluster` enforces `ClusterNodeCredential.Value = SUSER_SNAME()` and aborts with `RAISERROR('Unauthorized: caller sa is not bound to NodeId')`. All four seed scripts now insert the binding row alongside the ClusterNode row. Without this, the server fails bootstrap with `BootstrapException: Central DB unreachable and no local cache available` (the Unauthorized error gets swallowed on top of the HTTP fallback path). 2. **Config cache gitignore.** Running the server from the repo root writes `config_cache.db` + `config_cache-log.db` next to the cwd, outside the existing `src/.../Server/config_cache.db` pattern. Add a `config_cache*.db` pattern so any future run location is covered. ## Verified live against Modbus Booted server against `seed-modbus-smoke.sql` → pymodbus standard fixture → ran `scripts/e2e/test-modbus.ps1 -BridgeNodeId "ns=2;s=HR200"`: === Modbus e2e summary: 4/5 passed === [PASS] Probe [PASS] Driver loopback [PASS] Server bridge (driver → server → client) [FAIL] OPC UA write bridge (0x801F0000) [PASS] Subscribe sees change The forward direction + subscription delivery are proven working through the server. The reverse-write failure is a seed-or-ACL issue — server log shows no exception on the write path, so the client-side status is coming from the stack's type/ACL guards. Tracking as a follow-up issue so the remaining three factory wirings can be smoke-booted against the same pattern. Note for future runs: two stale v1 `ZB.MOM.WW.LmxOpcUa.Host.exe` processes from `C:\publish\lmxopcua\instance{1,2}\` squat on ports 4840 + 4841 on this dev box; kill them first or bump the seed's DashboardPort. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,14 @@ INSERT dbo.ClusterNode(NodeId, ClusterId, RedundancyRole, Host, OpcUaPort, Dashb
|
||||
VALUES (@NodeId, @ClusterId, 'Primary', 'localhost', 4840, 5000,
|
||||
'urn:OtOpcUa:modbus-smoke-node', 200, 1, 'modbus-smoke');
|
||||
|
||||
-- Bind the SQL login this smoke test connects as to the node identity. The
|
||||
-- sp_GetCurrentGenerationForCluster + sp_UpdateClusterNodeGenerationState
|
||||
-- sprocs raise RAISERROR('Unauthorized: caller %s is not bound to NodeId %s')
|
||||
-- when this row is missing. `Kind='SqlLogin'` / `Value='sa'` matches the
|
||||
-- container's SA user; rotate Value for real deployments using a non-SA login.
|
||||
INSERT dbo.ClusterNodeCredential(NodeId, Kind, Value, Enabled, CreatedBy)
|
||||
VALUES (@NodeId, 'SqlLogin', 'sa', 1, 'modbus-smoke');
|
||||
|
||||
-- 2. Draft generation.
|
||||
DECLARE @Gen bigint;
|
||||
INSERT dbo.ConfigGeneration(ClusterId, Status, CreatedBy)
|
||||
|
||||
Reference in New Issue
Block a user