Commit Graph

2 Commits

Author SHA1 Message Date
Joseph Doherty f0d807e7b7 fix(opcuaclient): review r0 minors m1-m10
- m1: the form hint now says ProbeTimeoutSeconds can only shorten Test Connect's
  10 s budget (passing the configured value as the button's budget is shared code -
  follow-up).
- m2: a superseded init no longer overwrites _options (generation-checked under
  _probeLock) or the cert-validation handler (handed back and published with the
  session; detached when not installed; a previous one detached on replace).
- m3: an ack none of whose condition ids resolves throws BadNodeIdUnknown + Warning.
- m4: an ack with no reply (transport failure / non-caller timeout) degrades.
- m5: no session before the gate is the same ServiceResultException(BadNotConnected).
- m6: the caller-cancelled-write deviation is documented.
- m7: a reply during a published outage advances the stamp but does not write
  Healthy; the keep-alive recovery ends the outage.
- m8: test for a non-caller OperationCanceledException write -> Degraded.
- m9: the browse session owns and disposes the user certificate it loaded
  (OpcUaUserIdentityFactory.LoadCertificate; a key-less cert is disposed before the
  throw); AdminUI-host certificate path documented.
- m10: a subscribe overtaken by a shutdown / re-init removes its half-built
  subscription instead of registering it (data and alarm).
- Sync Dispose drains each gate for 500 ms (was 2 s).

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 16:42:29 -04:00
Joseph Doherty fcdc44f9f7 feat(opcuaclient-browser): real AttributesAsync + certificate-auth browse (R06:O-5)
- AttributesAsync was a stub returning nothing; it now reads NodeClass /
  DisplayName / DataType / ValueRank / UserAccessLevel in one request and maps them
  through UpstreamAttributeMapping, the same mapping discovery registers with (moved
  into the shared .Session leaf; the driver forwards to it). Objects have no value
  attributes.
- Certificate auth was refused "in v1". The browse now builds its identity through
  OpcUaUserIdentityFactory (shared .Session leaf, the driver forwards to it),
  including the secret: resolution of Password / UserCertificatePassword through the
  host's ISecretResolver (optional ctor param, DI-injected). Fail-closed: a secret:
  ref with no store throws instead of being sent as the literal (the browse used to
  send a secret: Password verbatim). The identity is built before any network I/O.

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 15:33:08 -04:00