docs(otopcua-history): #880 SDK2 clients force legacy UserName encryption for 65-char keys vs SDK 1.5 servers (be28aa44), consumer impact

Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
Joseph Doherty
2026-11-12 11:15:37 -05:00
parent 23693ef66c
commit d5de462f19
@@ -486,3 +486,8 @@ its Galaxy acks fail against mxaccessgw `2b13564e` did not apply to this box's d
- **ScadaBridge consumer impact: none.** ScadaBridge does no HistoryRead. A generic OPC UA history client reading folder event history gets more rows per folder: attribute alarms appear alongside object events.
- **Production caveat, #886 (open):** a folder's historian source is its RawPath or EquipmentId, never a Galaxy `tag_name`. AVEVA's own A&E history therefore reaches a folder only where those names coincide (the #801 harness names the folder after the object). AVEVA `priority` and `alarm_id` are not mapped either, so Severity is 1 and ConditionName is null on AVEVA rows.
- **Live check:** re-ran the #801 gate read-only against vd03 HistorianGateway `ea9f21c`. 221 of 225 cases are identical to the #801 baseline; the 4 that differ are exactly the `DevWinPlatform` event cases. Record: OtOpcUa `docs/plans/evidence/2026-11-10-opcua2/aveva-history-801.md` § "#882 re-run".
- **2026-11-12 master `be28aa44` (#880, not deployed): SDK 2 OtOpcUa clients log in to SDK 1.5 servers with production API keys again.** SDK 2.0.1's UserName handler sends any password over 64 bytes as an `RsaEncryptedSecret` (`EncryptionAlgorithm` null). The 64-byte threshold is a private constant with no setting, and it is unchanged in 2.0.2 and on upstream master. SDK 1.5.378 (.106 and .182) decrypts only the legacy RSA-OAEP format and answers a null algorithm with `BadIdentityTokenInvalid` before any key check. Every API key is 65 characters, so the SDK 2 CLI/UI, the OpcUaClient driver and the AdminUI browse could not log in to QA vq03/vq04 (`b8b4c18f`) or a rolled-back node.
- **The fix:** `LegacyRsaUserNameIdentityTokenHandler`, plugged in through `UserIdentity(IUserIdentityTokenHandler)` and exposed as `OpcUaUserIdentityFactory.UserName`, always sends the legacy format under an RSA policy. That is what SDK 2 already sends for 64 bytes or less and what 1.5 clients always send. An SDK 2 server reads both formats. Client.Shared now references `Driver.OpcUaClient.Session`.
- **Cross-version matrix (#782):** it now uses the 65-character key shape. The old 55-character `otua_matrix_` key had hidden the bug. The matrix adds a wrong-key case and an SDK-default negative-control case (`2ad72130`). Evidence for the fixed and mutated runs is in `e5b26f37`. The same run exposed #888: the matrix fixture's UNS folder has had no ACL placement since #808, so UNS cases are denied against master for every client.
- **ScadaBridge consumer impact: none.** ScadaBridge is an SDK 1.5 client and always sent the legacy format. Generic SDK 2 tools that use the SDK's default handler are still refused by SDK 1.5 servers when the key is 65 characters.