Actual ScadaBridge consumer compatibility
This isolated process references the real ScadaBridge OpcUaDataConnection and
RealOpcUaClient, with their own dependency graph. It never loads the candidate
SDK into that process. The verified consumer source is
0e89966da670e289bd875166295bb0e85d8cf8b2, pinned to SDK 1.5.378.106.
Build with an explicit clean consumer checkout:
dotnet build scripts/validation/scadabridge-sdk-compatibility/Probe.csproj \
-c Release -p:ScadaBridgeSourceRoot=/absolute/ScadaBridge
First build the separate application hosts with the parent
scripts/e2e/test-opcua-sdk-compatibility.ps1 harness. Then choose a new output
directory and pass its original and candidate ProcessHost.dll paths:
python3 scripts/validation/scadabridge-sdk-compatibility/run.py \
--baseline-host /absolute/matrix/build-baseline/bin/Release/net10.0/ProcessHost.dll \
--candidate-host /absolute/matrix/build-candidate/bin/Release/net10.0/ProcessHost.dll \
--probe scripts/validation/scadabridge-sdk-compatibility/bin/Release/net10.0/Probe.dll \
--results /absolute/fresh-consumer-evidence
The helper runs each application version with None, Sign and SignAndEncrypt,
plus two trust negative controls per secure profile (server does not trust the
client, client does not trust the server) that must fail closed. None and Sign
are enabled only in their own test fixtures (OPCUA_MATRIX_SERVER_SECURITY=none|sign);
the ordinary compatibility host remains strict SignAndEncrypt. Before each secure
leg the probe's prepare step provisions the consumer identity through
ScadaBridge's own certificate code and exports only its public certificate, which
the runner places in the server's trusted store before the server starts.
OPCUA_MATRIX_ACL=off disables the server's node-ACL check; with it on, masters
after lmxopcua#808 deny the three UNS cases because this fixture creates the Eq
folder without a deployed generation (fixture limitation, see lmxopcua#782). The task key is
generated per process pair, issuer/trusted/rejected stores are task-local, and
server public certificates are explicitly copied. Autoaccept remains false.
Never commit an entire output directory: it contains the fixture's private PKI.
The consumed subset covers API-key activation, raw/UNS scalar and Int32[] roundtrips, durable hierarchical browse including the native alarm, data quality and timestamps, alarm filter/ConditionRefresh and disconnect/reconnect. History and Part 9 acknowledgment are not exposed by the inspected consumer interfaces; the parent Shared/CLI matrix covers those application services instead.
ScadaBridge#121 (consumer never configured an application certificate) is
fixed in ScadaBridge ff835447/36c64a6b. Re-run 2026-11-12 with ScadaBridge
424db155: None, Sign and SignAndEncrypt 9/9 against the SDK 1.5.378 baseline
(83ed880e), the SDK 2.0.1 candidate (ebdc5892) and master 182fb353 with
ACL off; all trust negative controls failed closed. The runner retains the
nonzero result and each actual failure; it does not loosen trust or change
expected results to return success. No ScadaBridge production source or user PKI is modified.