Design review 2026-08-01: (1) MES relevance = dedicated severity band 900-999 (script constants, real IsFlaggedForMES predicate); (2) MESReceiver version DROPPED — CvdReactor is the only implementation, router returns a clean not-supported error elsewhere; (3) Description = Message else AlarmTypeName; (4) enrich the native mirror NOW with an additive AckTime (proto + native_alarm_state + DCL stamping); (5) script names match the endpoints; (6) shared ReactorAlarms on both sides, suffix behavior as planned; (7) existing MES API key, no new roles. Plan is now ready to execute.
26 KiB
MES Alarm-Status API — Implementation Plan
Date: 2026-06-30 Status: Ready to execute — all §6 open questions DECIDED 2026-08-01 (design review with user). Not yet implemented. Component touchpoints: Inbound API (#14), Script Analysis (#25), Site Runtime (#3), Template Engine (#1) — plus deployed config (inbound methods + CvdReactor template scripts).
1. Goal
Port the legacy WWSupport / APIServer MES alarm-status endpoints onto ScadaBridge's Inbound API, mirroring how MesMoveIn / MesMoveOut were ported:
- Update the existing
SimpleAlarmStatusRequestinbound method (currently a stub) to do real work. - Create a new
AlarmStatusinbound method (the full, filtered endpoint). - Both inbound methods forward to site scripts (
SAPID → BTDB machine lookup → Route.To(code).Call(...)), exactly likeMesMoveIn. The generic version on theDROPPED (Q2, 2026-08-01): no MESReceiver version ships — a config-only answer with no live state was judged not worth having. Machines whose template doesn't implement the scripts get a cleanMESReceivertemplate queries the BTDBMachineAlarmtable.WasSuccessful=false"not supported on this machine" error from the inbound router.- The
CvdReactortemplate provides the (only) implementation, reading the alarms actually defined on the CvdReactor object (its 7 native alarm-source bindings) directly — noMachineAlarmlookup anywhere.
Legacy spec being mirrored: docs/former-api-specs/mes/Alarm-API.md.
2. Legacy contract recap (target parity)
Two endpoints, one response shape (AlarmStatusResponse):
| Legacy route | New inbound method | Request |
|---|---|---|
POST /mes/simplealarmstatus |
SimpleAlarmStatusRequest (exists, id 9) |
{ "SAPID": "..." } |
POST /mes/alarmstatus |
AlarmStatus (NEW) |
{ MachineFilter, AlarmFilter } |
AlarmStatusResponse = { WasSuccessful: bool, ErrorText: string, Alarms: AlarmInfo[] }; on failure WasSuccessful=false and Alarms is cleared (all-or-nothing).
AlarmInfo = Name, HierarchicalName ({Code}.{Name}), Description, IsFlaggedForMES, Severity (0–999), StatusCode ("Triggered" / "Triggered.Acked"), TriggeredDT, AckDT?, AckComment.
Behaviors to preserve:
- Only triggered alarms returned (
InAlarm == true). No "all configured" mode.IncludeTriggeredis a no-op (legacy declared-but-unused). /simplealarmstatus: always flagged-only, ack filtering ignored (acked alarms always included, taggedTriggered.Acked)./alarmstatus:MachineFilterprecedenceSAPID → Code → ZTag → MachineID;AlarmFilterorderFlaggedOnly → MinSeverity → MaxSeverity → NameFilter(substring, case-insensitive; severity bounds inclusive);IncludeAcked=falseexcludes acked.
3. Current state in ScadaBridge (verified 2026-06-30 against wonder-app-vd03)
Inbound methods (api-method list):
SimpleAlarmStatusRequest(id 9) — stub:return new { WasSuccessful = true, Alarms = Array.Empty<Object>() };. Param:SAPID(string). Return definition already shaped toAlarmInfo(Name/HierarchicalName/Description/IsFlaggedForMES/Severity/StatusCode/TriggeredDT/AckDT/AckComment). ✅ no return-contract change needed.- No
AlarmStatusmethod yet. - Reference pattern (
MesMoveIn, id 2):SAPID → Database.QuerySingleAsync<string>("BTDB", "SELECT TOP 1 Code FROM dbo.Machine WHERE SAPID=@s") → Route.To(code).Call("MesMoveIn", {...}).
Templates (template list / template get):
CvdReactor(id 1, parent=none): root scriptsIpsenMoveIn,ProcessRecipeDownload,MesMoveIn,MesMoveOut; 7 native alarm sources (all overMxGateway):ReactorAlarms(Z28061.),LeftSideAlarms(Left_002.),RightSideAlarms(Right_002.),LeftLeakTestAlarms(LeakTest_003.),RightLeakTestAlarms(LeakTest_004.),LeftTableAlarms(TableAlarms_003.),RightTableAlarms(TableAlarms_004.); composes templates 5,6,8,9,13,14,26. No computedTemplateAlarms.MESReceiver(id 3, parent=none): root scriptsMoveIn,MoveOut(scope-bound to the composed receiver, bareAttributes);Left/RightMESReceiver(5/6) derive from it and are composed into CvdReactor. No alarms, no native sources.
Established override pattern (MoveIn): CvdReactor.MesMoveIn (root) does side-dispatch off the SAPID suffix and writes directly into Children["LeftMESReceiver"|"RightMESReceiver"].Attributes via WriteBatchAndWaitAsync — it does not CallScript the base. MESReceiver.MoveIn is the generic scope-bound implementation. So "override" here = CvdReactor supplies its own root-level script that Route.Call resolves for CvdReactor instances; the MESReceiver version is the reusable/generic one. (CvdReactor does not inherit MESReceiver — it composes it — so this is parallel-definition, not inheritance-override.)
4. The blocking gap (drives most of the code work)
Site call-type scripts currently have NO public API to read alarm condition state.
From the site-script API map:
- The runtime context is
ScriptRuntimeContext(src/.../SiteRuntime/Scripts/ScriptRuntimeContext.cs); compile-time mirror isScriptCompileSurface(src/.../ScriptAnalysis/ScriptCompileSurface.cs). Members today:Attributes,Children,Parent,Instance(GetAttribute/SetAttribute/CallScript),Database,ExternalSystem,Notify,Scripts,Tracking,Parameters,Alarm(on-trigger only),CancellationToken. - Computed alarm state is only exposed via the
Alarmglobal passed into on-trigger scripts. Native alarm state (AlarmConditionState) lives in the Instance Actor's_latestAlarmEvents; no script-facing query method exists.
⇒ The CvdReactor override ("read the defined alarms directly") cannot be written as a script today. It requires a new enabling capability: a script-facing Alarms read accessor.
Good news — the data already exists and is local. DebugViewSnapshot (Commons/Messages/DebugView/DebugViewSnapshot.cs) carries IReadOnlyList<AlarmStateChanged> AlarmStates, and the M7 Alarm Summary page already fans this out per instance. AlarmStateChanged (Commons/Messages/Streaming/AlarmStateChanged.cs) carries everything we need: AlarmName, Condition (AlarmConditionState: Active/Acknowledged/Confirmed/Shelve/Suppressed/Severity), Priority, Level, Message, Kind, SourceReference, AlarmTypeName, Category, OperatorUser, OperatorComment, OriginalRaiseTime, Timestamp, NativeSourceCanonicalName, IsConfiguredPlaceholder. The script runs inside the Instance Actor's context, so an Alarms accessor reads this via a local Ask — same mechanism as GetAttribute, no cross-cluster hop.
5. Target architecture (three layers)
INBOUND (central) ENABLING CODE (repo) SITE TEMPLATE SCRIPTS (deployed config)
───────────────── ──────────────────── ───────────────────────────────────────
SimpleAlarmStatusRequest ─┐ Alarms script accessor
├─ Route.To(code).Call(...) ─────────► CvdReactor.SimpleAlarmStatus (native sources)
AlarmStatus (new) ─┘ + AckTime mirror enrichment ──► CvdReactor.AlarmStatus (native sources)
(ScriptRuntimeContext +
ScriptCompileSurface) (no MESReceiver version — Q2 DECIDED: dropped)
5.1 Layer A — Inbound API methods (deployed config; central)
Thin routers, identical shape to MesMoveIn. They own machine resolution (the MachineFilter precedence) against BTDB, then Route.To(code).Call(<siteScript>, <filters>) and return the site result verbatim.
SimpleAlarmStatusRequest (update id 9): extract the numeric SAP id for the BTDB lookup, but forward the raw SAPID (with _A/_B[_LT] suffix) to the site so the CvdReactor override can resolve the side — exactly as MesMoveIn does.
try {
var raw = ((Parameters.ContainsKey("SAPID") ? Parameters["SAPID"]?.ToString() : null) ?? "").Trim();
var m = System.Text.RegularExpressions.Regex.Match(raw, @"^(\d+)");
if (!m.Success)
return new { WasSuccessful = false, ErrorText = $"SAPID does not contain a numeric SAP id: '{raw}'", Alarms = Array.Empty<object>() };
var sap = m.Groups[1].Value; // numeric SAP for the DB lookup
var code = await Database.QuerySingleAsync<string>("BTDB",
"SELECT TOP 1 Code FROM dbo.Machine WHERE SAPID=@s", new { s = sap });
if (string.IsNullOrEmpty(code))
return new { WasSuccessful = false, ErrorText = $"Failed to find machine with SAPID '{sap}'", Alarms = Array.Empty<object>() };
// SimpleAlarmStatus semantics: flagged-only, acked always included. Pass RAW SAPID for side routing.
return await Route.To(code).Call("SimpleAlarmStatus", new { SAPID = raw, MachineCode = code });
} catch (Exception ex) {
return new { WasSuccessful = false, ErrorText = "SimpleAlarmStatus failed: " + ex.Message, Alarms = Array.Empty<object>() };
}
AlarmStatus (new method): nested MachineFilter + AlarmFilter params (Inbound API extended type system supports Object). Resolve machine via precedence (all selectors come from dbo.Machine), then forward the filter to the site script.
- Param definition (object):
MachineFilter { MachineID:int?, SAPID:string, ZTag:string, Code:string },AlarmFilter { NameFilter:string, MinSeverity:int?, MaxSeverity:int?, IncludeTriggered:bool, IncludeAcked:bool, FlaggedOnly:bool }. - Return definition: same
AlarmInfo[]shape as id 9. - Body: resolve
codebySAPID → Code → ZTag → MachineID(each its ownSELECT TOP 1 Code FROM dbo.Machine WHERE ...), selector-specific error text on unmatched, thenRoute.To(code).Call("AlarmStatus", new { MachineCode = code, SAPID = <raw MachineFilter.SAPID or "">, ...AlarmFilter fields... }). The rawMachineFilter.SAPID(suffix included) is forwarded so the CvdReactor override can scope by side; when the machine was selected byCode/ZTag/MachineID(no SAPID suffix), side scoping is skipped and all sources are returned (see §6.6).
Note: Machine resolution stays on the inbound side (central) because it is environment/SQL-shaped and identical for both endpoints; site scripts receive an already-resolved
MachineCodeplus the alarm filter.
Unsupported machines (Q2 DECIDED): since only CvdReactor implements the site scripts,
Route.Callon any other machine fails script-not-found. Both routers catch that case specifically and return{ WasSuccessful=false, ErrorText = $"Alarm status is not supported on machine '{code}'" }instead of the raw exception text (verify during impl what exception/messageRoute.Callyields for a missing script so the catch can distinguish it).
5.2 Layer B — Enabling code change: script-facing Alarms accessor (repo)
New read-only accessor on the site script surface so scripts can enumerate the instance's current alarms.
Proposed shape (final names TBD in review):
// On ScriptRuntimeContext (runtime) + ScriptCompileSurface (compile-time stub):
public AlarmsAccessor Alarms { get; }
public sealed class AlarmsAccessor {
// Snapshot of the instance's CURRENT alarm conditions (computed + native),
// read locally from the Instance Actor (same Ask path as attribute reads).
Task<IReadOnlyList<ScriptAlarm>> CurrentAsync(CancellationToken ct = default);
}
public sealed record ScriptAlarm(
string Name, string SourceReference, string NativeSourceCanonicalName,
bool Active, bool Acknowledged, bool? Confirmed, bool Shelved, bool Suppressed,
int Severity, string Kind, // "Computed" | "NativeOpcUa" | "NativeMxAccess"
string Message, string AlarmTypeName, string Category,
string OperatorUser, string OperatorComment,
DateTimeOffset? OriginalRaiseTime, DateTimeOffset Timestamp,
DateTimeOffset? AckTime, // Q4 DECIDED: real ack timestamp from the enriched mirror
string CurrentValue, string LimitValue, bool IsConfiguredPlaceholder);
Ack-timestamp enrichment (Q4 DECIDED 2026-08-01 — enrich the mirror now, not a follow-up):
- Add an additive
AckTime(DateTimeOffset?) toAlarmStateChanged, the vendoredAlarmStateUpdateproto (additive field number, never reuse — manual toggle-build-copy-untoggle regen), and the sitenative_alarm_statepersistence so it survives failover. - Semantics: when the underlying source supplies a true ack time (OPC UA A&C ack transitions do), use it; when it doesn't (MxGateway events without one), stamp the observation time of the ack transition at the DCL — accurate to when the system saw the ack, never fabricated. Null while unacked; cleared on re-raise.
Implementation:
- Runtime:
Alarms.CurrentAsync()Asks the Instance Actor for its alarm snapshot (reuse the existing internal alarm-state map that feedsDebugViewSnapshot.AlarmStates; project eachAlarmStateChanged→ScriptAlarm). New internal request/response message (or reuseDebugSnapshotRequestand project offAlarmStates). - Compile surface: matching stub returning
Task.FromResult(empty)so design-time compile + Test Run pass. ScriptTrustPolicy(#25): no new forbidden surface;Alarmsis an allow-listed context member likeAttributes. Confirm the validator's allow-list includes it.- Additive message-contract evolution only.
5.3 Layer C — Site template scripts (deployed config)
MESReceiver version — DROPPED (Q2 DECIDED 2026-08-01). With no native alarm sources, MESReceiver has no live "triggered" signal; a configured-catalog-only answer was judged misleading rather than useful. No BTDB MachineAlarm read ships anywhere in this feature. Machines without the CvdReactor-style scripts get the router's "not supported on machine" error (§5.1).
CvdReactor (the only implementation — reads native sources directly, no DB): SimpleAlarmStatus and AlarmStatus (Q5 DECIDED: names match the endpoints, template-agnostic contract) as root-level scripts (mirrors MesMoveIn).
The override routes left vs right off the SAPID suffix — _A ⇒ Left, _B ⇒ Right — and scopes the returned alarms to that side's native sources plus the shared reactor-wide source. The _LT (leak-test) suffix is ignored for scoping: it is stripped before reading the side, and both the side's run and leak-test sources are included. Source → side map (the 7 CvdReactor native sources):
Side (_A/_B) |
Native sources included |
|---|---|
Left (_A) |
LeftSideAlarms, LeftLeakTestAlarms, LeftTableAlarms, + shared ReactorAlarms |
Right (_B) |
RightSideAlarms, RightLeakTestAlarms, RightTableAlarms, + shared ReactorAlarms |
// CvdReactor.SimpleAlarmStatus (sketch)
// Q1 DECIDED: MES relevance = dedicated severity band. Galaxy alarm priorities for
// MES-relevant alarms are configured into 900-999; nothing else may use that band.
const int MesBandMin = 900;
const int MesBandMax = 999;
try {
var raw = (Parameters["SAPID"] as string) ?? "";
var code = Parameters["MachineCode"]?.ToString() ?? "";
// Side routing from the SAPID suffix: _A => Left, _B => Right. _LT (leak test) is ignored.
var core = raw.EndsWith("_LT") ? raw.Substring(0, raw.Length - 3) : raw;
var side = core.EndsWith("_A") ? "Left" : core.EndsWith("_B") ? "Right" : null;
if (side == null)
return new { WasSuccessful = false, ErrorText = "SAPID missing _A/_B side suffix", Alarms = Array.Empty<object>() };
// Keep this side's sources (Left*/Right*) + the shared reactor-wide source; drop the other side's.
System.Func<string,bool> InScope = src =>
string.IsNullOrEmpty(src) // computed/unbound — keep
|| src.StartsWith(side, System.StringComparison.OrdinalIgnoreCase) // Left* or Right*
|| src.StartsWith("Reactor", System.StringComparison.OrdinalIgnoreCase); // shared ReactorAlarms
var alarms = await Alarms.CurrentAsync(); // native + computed, all 7 sources
var infos = alarms
.Where(a => a.Active && !a.IsConfiguredPlaceholder) // only triggered
.Where(a => InScope(a.NativeSourceCanonicalName)) // _A => Left*, _B => Right*, + ReactorAlarms
// SimpleAlarmStatus semantics: flagged-only (= MES band, Q1) + acked always included
.Where(a => a.Severity >= MesBandMin && a.Severity <= MesBandMax)
.Select(a => new {
Name = a.Name,
HierarchicalName = code + "." + a.Name,
Description = string.IsNullOrEmpty(a.Message) ? a.AlarmTypeName : a.Message, // Q3 DECIDED
IsFlaggedForMES = a.Severity >= MesBandMin && a.Severity <= MesBandMax, // Q1 DECIDED: real predicate
Severity = a.Severity,
StatusCode = a.Acknowledged ? "Triggered.Acked" : "Triggered",
TriggeredDT = (a.OriginalRaiseTime ?? a.Timestamp),
AckDT = a.AckTime, // Q4 DECIDED: enriched mirror
AckComment = a.OperatorComment,
}).ToList();
return new { WasSuccessful = true, ErrorText = (string)null, Alarms = infos };
} catch (Exception ex) {
return new { WasSuccessful = false, ErrorText = "SimpleAlarmStatus failed: " + ex.Message, Alarms = Array.Empty<object>() };
}
CvdReactor.AlarmStatus is the same — same side parsing + InScope filter, WITHOUT the always-on band filter — but applies the passed AlarmFilter (NameFilter/MinSeverity/MaxSeverity/FlaggedOnly/IncludeAcked) over the scoped native list; FlaggedOnly=true means the MES-band predicate (Q1). IsFlaggedForMES is always reported per-row from the band predicate. (When AlarmStatus was selected by Code/ZTag/MachineID with no SAPID suffix, side == null; in that case return all sources instead of erroring — Q6b DECIDED.)
Shared
ReactorAlarms(Z28061.) is included on both sides — Q6a DECIDED 2026-08-01: reactor-wide faults apply regardless of which side MES asks about.
6. Key design decisions — ALL DECIDED 2026-08-01 (design review with user)
-
IsFlaggedForMESfor native alarms — DECIDED: severity band. MES relevance is encoded in the alarm severity itself: MES-relevant alarms are configured (in the Galaxy alarm priority) into a dedicated band 900–999 reserved exclusively for MES-relevant alarms, so it cannot collide with ordinary criticality tuning. Scripts carryMesBandMin = 900/MesBandMax = 999as named constants;IsFlaggedForMES = (Severity in band)is reported honestly per row;SimpleAlarmStatus(always flagged-only) andAlarmStatuswithFlaggedOnly=truefilter by the band predicate. SinceSeverityis returned verbatim, MES's ownMinSeverity/MaxSeverityfilters compose naturally with the band. No new tables, code flags, or allow-lists. Operational prerequisite: the Galaxy alarm priorities for MES-relevant CvdReactor alarms must be set into 900–999 before the endpoints are meaningful. -
MESReceiver version — DECIDED: dropped entirely. With no native alarm sources there is no live state; a config-only catalog answer was judged not worth shipping. Only CvdReactor implements the scripts; other machines get the router's clean "not supported on machine" error (§5.1). No BTDB
MachineAlarmdependency remains. -
Descriptionmapping — DECIDED:Message, falling back toAlarmTypeNamewhenMessageis empty. -
AckDTmapping — DECIDED: enrich the native mirror now. AdditiveAckTimeonAlarmStateChanged+ vendored proto +native_alarm_state(survives failover). True source ack time where available (OPC UA A&C); DCL observation time of the ack transition where the source lacks one (MxGateway); null while unacked; cleared on re-raise. See §5.2. -
Script naming — DECIDED:
SimpleAlarmStatus/AlarmStatus(match the endpoint names; template-agnostic contract any future machine template can implement). With the MESReceiver version dropped there is no parallel definition, so no override-resolution concern remains. -
Side scoping — DECIDED (all parts). CvdReactor-only:
_A⇒ Left,_B⇒ Right;_LTstripped before reading the side (leak-test sources still included). (a) sharedReactorAlarms(Z28061.) included on both sides — reactor-wide faults apply regardless of side. (b) missing suffix:SimpleAlarmStatuserrors on a SAPID without_A/_B(matchesMesMoveIn);AlarmStatusselected byCode/ZTag/MachineID(no SAPID) returns all sources; a SAPID selector without a suffix errors. -
Roles / auth — DECIDED: no new roles; create
AlarmStatusas Designer via CLI; authorize the existing MES API key (the one already callingMesMoveIn/MesMoveOut) for both alarm endpoints — one key per external system.
7. Implementation task breakdown (ordered)
Two artifact classes: [repo] = source/tests/docs committed to git; [deployed] = inbound methods / template scripts pushed to the cluster via CLI/UI (not in repo). The user said "don't execute yet" — this is the ordered plan only.
Phase 1 — Enabling Alarms script API + AckTime mirror enrichment [repo]
- AckTime enrichment (§6.4): additive
AckTimeonAlarmStateChanged, the vendoredAlarmStateUpdateproto (manual regen),native_alarm_statepersistence, and the DCL ack-transition stamping (source ack time where supplied, else observation time). - Add
AlarmsAccessor+ScriptAlarmto the runtime context (ScriptRuntimeContext) — local Ask to the Instance Actor; projectAlarmStateChanged→ScriptAlarm(incl.AckTime). Add internal request/response message if not reusingDebugSnapshotRequest. - Mirror the stub on
ScriptCompileSurface(and confirmTriggerCompileSurfacenot needed — trigger expressions don't read alarms). - Confirm/extend
ScriptTrustPolicyallow-list soAlarmsis permitted; no new forbidden APIs. - Unit tests: runtime accessor projection (active/acked/severity/timestamps/AckTime), AckTime stamping + failover persistence, compile-surface compiles a representative
Alarms.CurrentAsync()script, trust-policy accepts it. - Doc: update
Component-SiteRuntime.md+Component-DataConnectionLayer.md(native-mirror AckTime) + Script Analysis #25 surface list; note the accessor inComponent-InboundAPI.mdrouting examples.
Phase 2 — Inbound methods [deployed] + doc [repo]
7. Update SimpleAlarmStatusRequest (id 9) body to the §5.1 router incl. the not-supported-machine catch (validate via design page first to avoid the stale-handler trap — see memory inbound-noncompiling-update-keeps-old-handler).
8. Create AlarmStatus method (params/return/script per §5.1); authorize the existing MES API key for both methods (§6.7).
9. Doc the two endpoints in docs/requirements/Component-InboundAPI.md (or a dedicated MES-integration note) cross-referencing the legacy spec.
Phase 3 — Site template scripts [deployed] (MESReceiver task removed — §6.2 decided dropped)
10. Add SimpleAlarmStatus + AlarmStatus to CvdReactor (native sources via Alarms.CurrentAsync(), MES band constants), per §5.3.
11. template validate (script compilation gate) before redeploy; redeploy affected instances.
Phase 4 — Verify
12. Build affected projects + run targeted tests (per memory targeted-tests-not-full-suite).
13. Live smoke against a real reactor instance (see §8) — both endpoints, success + machine-not-found + not-supported-machine + filtered. Requires the Galaxy MES-band priorities (§6.1) to be set for a meaningful flagged-only result.
8. Testing & verification
- Unit [repo]:
Alarmsaccessor projection; compile-surface acceptance; trust-policy allow; inbound param/return validation forAlarmStatus(nested objects). - Design-page [deployed]: paste both site scripts into the api-method/template design pages; confirm no CS errors and Test Run executes (this is the gate that catches
Database.QuerySingle-style mistakes pre-deploy). - Live smoke [deployed]:
curlsimplealarmstatusandalarmstatusagainst the deployed reactor; cross-check returned alarms against the CLI debug snapshot (debug snapshot --id <instance>) alarm table for the same instance; verify onlyActivealarms appear, ack mapping, severity filtering, and machine-not-found error text. - Caveat: native MxGateway alarms need a real gateway; the docker cluster can't fully exercise the CvdReactor native path (cf. memory on no-local-gateway). Validate the native-read path on the wonder-app-vd03 / real-gateway environment; unit-test the projection in isolation.
9. Out of scope / follow-ups
True— resolved by the §6.1 severity-band decision (no follow-up needed).IsFlaggedForMESallow-listPrecise— pulled INTO scope by §6.4 (mirror enriched now).AckDTfollow-up- A live/aggregated central alarm store or stream (the M7 follow-up) — these endpoints stay pull-based, per-instance, like the Alarm Summary page.
- Alarm-status support for non-CvdReactor machine types (any future template just implements
SimpleAlarmStatus/AlarmStatusroot scripts against the same contract).
10. Summary of changes
| Artifact | Type | Change |
|---|---|---|
AlarmStateChanged + vendored AlarmStateUpdate proto + native_alarm_state + DCL stamping |
[repo] | Additive AckTime enrichment (§6.4) |
ScriptRuntimeContext |
[repo] | New Alarms accessor + ScriptAlarm (incl. AckTime); local alarm-snapshot Ask |
ScriptCompileSurface |
[repo] | Mirror Alarms stub |
ScriptTrustPolicy (#25) |
[repo] | Allow Alarms member (verify) |
Internal alarm-snapshot message (or reuse DebugSnapshotRequest) |
[repo] | Additive |
| Site Runtime + DCL + Script Analysis + Inbound API docs | [repo] | Document Alarms accessor, AckTime, endpoints |
| Unit tests (SiteRuntime / ScriptAnalysis / InboundAPI) | [repo] | New |
SimpleAlarmStatusRequest (id 9) |
[deployed] | Stub → real router (+ not-supported catch) |
AlarmStatus (new) |
[deployed] | New inbound method, existing MES key authorized |
CvdReactor.SimpleAlarmStatus / .AlarmStatus |
[deployed] | New native-source scripts (MES band 900–999) |
| Galaxy alarm priorities | [external] | MES-relevant CvdReactor alarms configured into 900–999 (§6.1 prerequisite) |