feat(native-alarms): per-binding IsMesReportable on native alarm source bindings (ScadaBridge#59)

TemplateNativeAlarmSource.IsMesReportable + tri-state InstanceNativeAlarmSourceOverride
.IsMesReportableOverride flatten onto ResolvedNativeAlarmSource; NativeAlarmActor stamps every
mirrored condition and InstanceActor the quiet-binding placeholder, so ScriptAlarm,
Alarms.MesReportableAsync() and the #60 wire fields carry it. Additive to the 900-999 severity band.
Migration AddNativeAlarmSourceMesReportable. Management commands, CLI --mes-reportable, Central UI
(template dialog checkbox, instance override select), Transport DTOs/importer/diff and the revision
hash (true-only, so existing hashes are unchanged) carry it.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 15:09:54 -05:00
parent 69a2017000
commit f98369a786
38 changed files with 2579 additions and 43 deletions
@@ -65,7 +65,8 @@ public record SetInstanceNativeAlarmSourceOverrideCommand(
string SourceCanonicalName,
string? ConnectionNameOverride,
string? SourceReferenceOverride,
string? ConditionFilterOverride);
string? ConditionFilterOverride,
bool? IsMesReportableOverride = null); // additive trailing optional; null = inherit the binding's flag
public record DeleteInstanceNativeAlarmSourceOverrideCommand(
int InstanceId,
@@ -83,7 +84,8 @@ public record NativeAlarmSourceOverrideEntry(
string SourceCanonicalName,
string? ConnectionNameOverride,
string? SourceReferenceOverride,
string? ConditionFilterOverride);
string? ConditionFilterOverride,
bool? IsMesReportableOverride = null);
/// <summary>
/// Bulk, all-or-nothing apply of per-instance native-alarm-source overrides — the
@@ -49,8 +49,8 @@ public record AddTemplateAlarmCommand(int TemplateId, string Name, string Trigge
public record UpdateTemplateAlarmCommand(int AlarmId, string Name, string TriggerType, int PriorityLevel, string? Description, string? TriggerConfiguration, bool IsLocked, bool IsMesReportable = false);
public record DeleteTemplateAlarmCommand(int AlarmId);
// Native alarm source bindings (read-only mirror of an OPC UA A&C / MxGateway source's alarms)
public record AddTemplateNativeAlarmSourceCommand(int TemplateId, string Name, string ConnectionName, string SourceReference, string? ConditionFilter, string? Description, bool IsLocked);
public record UpdateTemplateNativeAlarmSourceCommand(int NativeAlarmSourceId, string Name, string ConnectionName, string SourceReference, string? ConditionFilter, string? Description, bool IsLocked);
public record AddTemplateNativeAlarmSourceCommand(int TemplateId, string Name, string ConnectionName, string SourceReference, string? ConditionFilter, string? Description, bool IsLocked, bool IsMesReportable = false);
public record UpdateTemplateNativeAlarmSourceCommand(int NativeAlarmSourceId, string Name, string ConnectionName, string SourceReference, string? ConditionFilter, string? Description, bool IsLocked, bool IsMesReportable = false);
public record DeleteTemplateNativeAlarmSourceCommand(int NativeAlarmSourceId);
public record ListTemplateNativeAlarmSourcesCommand(int TemplateId);
// MinTimeBetweenRuns/ExecutionTimeoutSeconds are additive trailing optionals (default null = "unset"):
@@ -116,8 +116,10 @@ public record AlarmStateChanged(
/// <summary>
/// True when the alarm's deployed configuration flags it as MES-reportable
/// (<c>ResolvedAlarm.IsMesReportable</c>). Stamped by the Instance Actor on its alarm
/// snapshot and on every event it relays to the site stream; always false for native
/// conditions, which have no per-alarm config row. Carried to central on
/// snapshot and on every event it relays to the site stream. For a native condition it is
/// the binding-level flag (<c>ResolvedNativeAlarmSource.IsMesReportable</c>, Gitea #59), set by
/// the owning <c>NativeAlarmActor</c> — there is still no per-condition config row; the
/// 900-999 severity band remains an independent, additive signal. Carried to central on
/// <c>AlarmStateUpdate</c> field 25 and <c>DebugAlarmStateDto</c> field 20 (Gitea #60);
/// a pre-#60 site sends the proto3 default. Additive; default false.
/// </summary>