Add opt-in managed GUID alarm-ack path #160

Closed
dohertj2 wants to merge 0 commits from feat/managed-guid-alarm-ack into main
Owner

Adds a managed acknowledge path over AVEVA's modern alarm client so GUID acks carry full operator identity (domain + full name) and work on builds where the wnwrap COM AlarmAckByGUID is E_NOTIMPL.

Default off — opt in with MXGATEWAY_USE_MANAGED_ALARM_ACK=1; wnwrap behavior is unchanged otherwise.

Changes

  • AaManagedAlarmAckConsumer — reflection wrapper over aaAlarmManagedClient.AlarmClient (InitializeConsumer/RegisterConsumer/Subscribe/AlarmAckByGUID). EnvGatedFactory degrades to the wnwrap path if the DLL can't load, so alarm reads never break.
  • IManagedAlarmAckClient seam. AlarmDispatcher takes an optional client and routes GUID acks to it (subscribing + disposing it alongside the reader).
  • AlarmCommandHandler gains an optional managedAckFactory; WorkerPipeSession wires AaManagedAlarmAckConsumer.EnvGatedFactory at the production sites.
  • WnalNativeAckConsumer — confirmed native alarmlst.dll WNAL submit layer (WNALalarmReqSetText/WNALUserRequest/WNALUserRequestEx + lpAlmAck layout). List acquisition is intentionally not hand-rolled: the alarm-record layout and selection semantics are provider-defined and not recoverable from alarmlst.dll, so inferring them would risk acking the wrong alarm.
  • AlarmManagedGuidAckLiveSmokeTests — skip-gated live smoke that pulls a real (non-degraded) alarm GUID and asserts the ack applies (Acknowledge transition / acked snapshot), not merely rc=0.

By-name acks stay on wnwrap (AlarmClient has no AlarmAckByName).

Validation

  • x86 Worker + Worker.Tests build clean (0 warnings, TreatWarningsAsErrors).
  • 200 alarm unit tests pass (6 live-rig skips).

Notes / runtime confirmation still needed

  • RegisterConsumer's trailing bool is passed false (meaning unconfirmed).
  • Whether Subscribe is strictly required before AlarmAckByGUID.
  • For a secured (MxSecurityOperate) alarm the ack must run under an authenticated operator; rc=0 means accepted, not applied. The new smoke test is the harness for this.

Grounded in static RE of alarmlst.dll, aaAlarmManagedClient.dll, and alarmmgr.exe.

🤖 Generated with Claude Code

Adds a managed acknowledge path over AVEVA's modern alarm client so GUID acks carry full operator identity (domain + full name) and work on builds where the wnwrap COM `AlarmAckByGUID` is `E_NOTIMPL`. **Default off** — opt in with `MXGATEWAY_USE_MANAGED_ALARM_ACK=1`; wnwrap behavior is unchanged otherwise. ## Changes - **`AaManagedAlarmAckConsumer`** — reflection wrapper over `aaAlarmManagedClient.AlarmClient` (`InitializeConsumer`/`RegisterConsumer`/`Subscribe`/`AlarmAckByGUID`). `EnvGatedFactory` degrades to the wnwrap path if the DLL can't load, so alarm reads never break. - **`IManagedAlarmAckClient`** seam. `AlarmDispatcher` takes an optional client and routes GUID acks to it (subscribing + disposing it alongside the reader). - **`AlarmCommandHandler`** gains an optional `managedAckFactory`; **`WorkerPipeSession`** wires `AaManagedAlarmAckConsumer.EnvGatedFactory` at the production sites. - **`WnalNativeAckConsumer`** — confirmed native `alarmlst.dll` WNAL submit layer (`WNALalarmReqSetText`/`WNALUserRequest`/`WNALUserRequestEx` + `lpAlmAck` layout). List acquisition is intentionally **not** hand-rolled: the alarm-record layout and selection semantics are provider-defined and not recoverable from `alarmlst.dll`, so inferring them would risk acking the wrong alarm. - **`AlarmManagedGuidAckLiveSmokeTests`** — skip-gated live smoke that pulls a real (non-degraded) alarm GUID and asserts the ack **applies** (Acknowledge transition / acked snapshot), not merely `rc=0`. By-name acks stay on wnwrap (`AlarmClient` has no `AlarmAckByName`). ## Validation - x86 Worker + Worker.Tests build clean (0 warnings, `TreatWarningsAsErrors`). - 200 alarm unit tests pass (6 live-rig skips). ## Notes / runtime confirmation still needed - `RegisterConsumer`'s trailing `bool` is passed `false` (meaning unconfirmed). - Whether `Subscribe` is strictly required before `AlarmAckByGUID`. - For a secured (`MxSecurityOperate`) alarm the ack must run under an authenticated operator; `rc=0` means accepted, not applied. The new smoke test is the harness for this. Grounded in static RE of `alarmlst.dll`, `aaAlarmManagedClient.dll`, and `alarmmgr.exe`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dohertj2 added 1 commit 2026-10-18 13:00:23 -04:00
feat(worker): add opt-in managed GUID alarm-ack path
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m19s
ci / java (push) Successful in 2m8s
ci / portable (push) Failing after 2m23s
ci / nightly-windev (pull_request) Has been skipped
ci / windows-x86 (pull_request) Successful in 1m18s
ci / java (pull_request) Successful in 2m3s
ci / portable (pull_request) Failing after 2m17s
6affbd57ea
Adds a managed acknowledge path over AVEVA's modern alarm client so GUID
acks carry full operator identity (domain + full name) and work on builds
where the wnwrap COM AlarmAckByGUID is E_NOTIMPL. Default off; opt in with
MXGATEWAY_USE_MANAGED_ALARM_ACK=1 (wnwrap behavior unchanged otherwise).

- AaManagedAlarmAckConsumer: reflection wrapper over
  aaAlarmManagedClient.AlarmClient (InitializeConsumer/RegisterConsumer/
  Subscribe/AlarmAckByGUID); EnvGatedFactory degrades to null (wnwrap) if the
  DLL can't load, so alarm reads never break.
- IManagedAlarmAckClient seam. AlarmDispatcher takes an optional client and
  routes GUID acks to it (subscribing + disposing it alongside the reader).
- AlarmCommandHandler gains an optional managedAckFactory; WorkerPipeSession
  wires AaManagedAlarmAckConsumer.EnvGatedFactory at the production sites.
- WnalNativeAckConsumer: confirmed native alarmlst.dll WNAL submit layer
  (WNALalarmReqSetText / WNALUserRequest / WNALUserRequestEx + lpAlmAck
  layout). List acquisition is intentionally not hand-rolled: the alarm-record
  layout and selection semantics are provider-defined and not recoverable from
  alarmlst.dll, so inferring them risks acking the wrong alarm.
- AlarmManagedGuidAckLiveSmokeTests: skip-gated live smoke that pulls a real
  (non-degraded) alarm GUID and asserts the ack APPLIES (Acknowledge
  transition / acked snapshot), not merely rc=0.

By-name acks stay on wnwrap (AlarmClient has no AlarmAckByName). Grounded in
static RE of alarmlst.dll, aaAlarmManagedClient.dll and alarmmgr.exe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dohertj2 added 1 commit 2026-10-18 13:11:05 -04:00
Keep subtag acks and alarm reads safe on the managed ack path
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (pull_request) Successful in 2m0s
ci / nightly-windev (pull_request) Has been skipped
ci / java (pull_request) Successful in 2m16s
ci / java (push) Successful in 2m19s
ci / portable (push) Failing after 2m31s
ci / portable (pull_request) Failing after 2m36s
ci / windows-x86 (push) Successful in 3m11s
6f4c7c3bf1
Review fixes for the opt-in managed GUID ack:

- Subtag-mode GUID acks (forced subtag, or failover on the standby) stay on
  the consumer; their GUIDs are synthetic and only the subtag consumer can
  resolve them. Forced-subtag sessions no longer build a managed client.
- A failed managed Initialize/Register/Subscribe drops back to the wnwrap
  ack path instead of failing the alarm subscription.
- Drop stale crefs to a nonexistent Unverified member in
  WnalNativeAckConsumer.
- Unit tests for routing, fallback, and disposal; document
  MXGATEWAY_USE_MANAGED_ALARM_ACK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Merged into main as 6c82de55c6 (with review fix commit 6f4c7c3: subtag-mode acks stay on the subtag consumer, managed lifecycle failure falls back to wnwrap, stale crefs removed, tests + docs). x86 Worker.Tests on windev: 533 passed, 0 failed.

Merged into main as 6c82de55c6a700c9da69015f9084c69b4429eb42 (with review fix commit 6f4c7c3: subtag-mode acks stay on the subtag consumer, managed lifecycle failure falls back to wnwrap, stale crefs removed, tests + docs). x86 Worker.Tests on windev: 533 passed, 0 failed.
dohertj2 closed this pull request 2026-10-18 13:13:51 -04:00
Some checks are pending
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (pull_request) Successful in 2m0s
ci / nightly-windev (pull_request) Has been skipped
ci / java (pull_request) Successful in 2m16s
ci / java (push) Successful in 2m19s
ci / portable (push) Failing after 2m31s
ci / portable (pull_request) Failing after 2m36s
ci / windows-x86 (push) Successful in 3m11s

Pull request closed

Sign in to join this conversation.