Twelfth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Depends on PR B.1 (EventPump
dispatch, merged) and PR E.2 (.NET SDK alarm methods, merged).
Restores the v1 IAlarmSource capability that PR 7.2 retired with the
legacy Galaxy.Host / Galaxy.Proxy projects.
GalaxyDriver gains:
- IAlarmSource on the class declaration → eight capabilities total
(IDriver / ITagDiscovery / IReadable / IWritable / ISubscribable /
IRediscoverable / IHostConnectivityProbe / IAlarmSource).
- SubscribeAlarmsAsync — returns a sentinel handle and starts the
shared EventPump (alarm wiring is lazy on first sub).
Multiple handles share the same gateway stream; the server-side
AlarmConditionService dispatches per-source-node downstream.
- UnsubscribeAlarmsAsync — symmetric handle removal; rejects
handles not issued by this driver.
- AcknowledgeAsync — issues one gateway RPC per acknowledgement
through IGalaxyAlarmAcknowledger. ConditionId carries the alarm
full reference; falls back to SourceNodeId when empty.
- OnAlarmEvent — bridges EventPump.OnAlarmTransition (B.1) onto
AlarmEventArgs. Suppressed when no alarm subscription is active so
untracked transitions don't leak through.
New runtime types:
- IGalaxyAlarmAcknowledger — test seam.
- GatewayGalaxyAlarmAcknowledger — production wrapper around
MxGatewayClient.AcknowledgeAlarmAsync (PR E.2). Maps native
MxStatus failures to a logged warning rather than a thrown
exception so a transient MxAccess hiccup doesn't fail the
operator's Acknowledge.
- GalaxyAlarmSubscriptionHandle — driver-side IAlarmSubscriptionHandle.
Production runtime construction in BuildProductionRuntimeAsync wires
the acknowledger when not pre-injected; tests inject a fake via the
internal ctor.
Tests:
- 7 new tests in GalaxyDriverAlarmSourceTests — subscribe → event
fire path, suppress without subscription, unsubscribe stops flow,
foreign-handle rejection, ack routes per-request, ack falls back
to SourceNodeId, ack throws NotSupported without acknowledger.
- Full Driver.Galaxy.Tests: 203 passed (was 196; 7 new).
Operates as a "stub-ready" surface — runtime ack calls will return
PERMISSION_DENIED until A.3 ships the gateway-side dispatch, and no
alarm transitions will arrive until A.2 adds the worker MxAccess
subscription. Both will activate this code path automatically when
the gateway side lands.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>