The consumer matrix minted a 55-character otua_matrix_ key, which stays
under SDK 2's 64-byte RsaEncryptedSecret threshold and so could not show
lmxopcua#880 from the consumer side. It now uses the ApiKeySecret.Generate
shape (65 characters), as opcua-sdk-compatibility already does.
README records the 2026-11-12 run with ScadaBridge on SDK 2.0.1
(a2e9d718): matrix 11/11 x3 modes on 83ed880e and 412da27c, ACL off and
on; 8/8 trust controls fail closed; failover 8/8; a mutation with the SDK
default UserName handler fails every baseline leg with
BadIdentityTokenInvalid.
Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
Since #808 an UNS folder with no placement in the generation is denied (fail
closed), so the matrix's ad hoc "Eq" folder made every UNS case fail with
BadUserAccessDenied on the candidate server. The fixture now supplies
unsFolderScopes (+ the alarm's tagReferencingEquipment) as a deployed
generation does. An unplaced "Unplaced" UNS folder is kept as a negative
control: the Shared client leg requires it denied against a #808+ server with
the ACL on. No server authorization code changed.
Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
Probe 'failover <primary> <backup> <mode> <dir>' drives ScadaBridge's own DataConnectionActor
(production primary/backup machine, real DataConnectionFactory, default DataConnectionOptions,
FailoverRetryCount 3) against two servers; run.py loses the primary (SIGKILL or SIGSTOP) once the
probe reports a steady primary, and the probe requires Bad quality on loss, "Connected to backup",
the backup's own value, a fresh ConditionRefresh replaying the native condition, and a write via the
backup. rig-failover.sh runs the same probe against the local docker-dev central pair.
Matrix legs gain a UNS subscription case and a Server-object alarm subscription on the reconnected
session whose ConditionRefresh must replay the active condition (11 cases). run.py gains --versions,
--suites, --failover-modes and --failover-loss.
Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi