Commit Graph

2 Commits

Author SHA1 Message Date
Joseph Doherty f02067d295 test: retry OPC UA host start on a port bind race (TOCTOU in AllocateFreePort)
The tests probe a free port (bind 0, release) and start the SDK server later; under a
highly parallel run another test can take the port in between and the SDK fails with
'Failed to establish tcp listener sockets for Ipv4 and IPv6.'. OpcUaHostStart.StartAsync
builds a fresh host + server on a fresh port per attempt (up to 5) when the failure is a
bind failure; all 45 start sites in OpcUaServer.Tests, OpcUaServer.IntegrationTests and
Runtime.Tests use it. Per-attempt GUID ApplicationUris are hoisted out of the host factory
because a changed URI against a reused PKI store fails with 'Cannot access private key'.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
2026-10-08 22:30:55 -04:00
Joseph Doherty 2b945672e9 fix(acl): revalidate event/alarm subscriptions on both triggers; key-usability check on role gates (#562, #563)
#562: direct event (alarm) monitored items are now tracked in a second map
(_eventItems, fed by the SubscribeToEvents override) and re-authorized by
RevalidateMonitoredItems on both triggers (DataPlaneAuthorityState.Changed and
AclRevalidationTimer). A denied item is detached via the SDK's own protected
SubscribeToEvents(unsubscribe: true) - never MonitoringMode.Disabled - and
re-attached on restore; a client delete of a stood-down item is absorbed.
Over-the-wire tests: revoke -> stop (positive control on a still-granted
notifier) -> restore -> resume; clock-driven expiry via the real timer with a
control session; delete-while-stood-down is not resurrected; unexpired
negative control. Server-object (all-events) subscriptions are documented as
outside the ACL (observed over the wire).

#563: DataPlaneAuthorizer.AuthorizeKeyUsable runs the FindUsableKey probe on
the WriteOperate and AlarmAck role gates regardless of Security:Acl:Enabled,
so an expired or deployment-disabled key loses its activation-time roles on
its open session. Anonymous (no key id) is unaffected; reads/subscriptions
stay ungated with the flag off. No new flag.

Docs: docs/security.md and the CLAUDE.md API-key/ACL section.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
2026-10-07 23:10:35 -04:00