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
@@ -4706,6 +4706,37 @@ public class ManagementActorTests : TestKit, IDisposable
_templateRepo.ReceivedWithAnyArgs(1).SaveChangesAsync(default);
}
/// <summary>Gitea #59: the instance override command carries IsMesReportableOverride onto the persisted row.</summary>
[Fact]
public void SetInstanceNativeAlarmSourceOverride_CarriesIsMesReportableOverride()
{
var pipeline = Substitute.For<IFlatteningPipeline>();
var flattened = new FlattenedConfiguration
{
NativeAlarmSources = new List<ResolvedNativeAlarmSource>
{
new() { CanonicalName = "Pressure", IsLocked = false, Source = "Template" }
}
};
pipeline.FlattenAndValidateAsync(1, Arg.Any<CancellationToken>(), Arg.Any<bool>())
.Returns(Result<FlatteningPipelineResult>.Success(
new FlatteningPipelineResult(flattened, "hash", ValidationResult.Success())));
_services.AddScoped(_ => pipeline);
InstanceNativeAlarmSourceOverride? added = null;
_templateRepo
.When(r => r.AddInstanceNativeAlarmSourceOverrideAsync(Arg.Any<InstanceNativeAlarmSourceOverride>(), Arg.Any<CancellationToken>()))
.Do(ci => added = ci.Arg<InstanceNativeAlarmSourceOverride>());
CreateActor().Tell(Envelope(
new SetInstanceNativeAlarmSourceOverrideCommand(1, "Pressure", null, null, null, IsMesReportableOverride: true),
"Deployer"));
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
Assert.NotNull(added);
Assert.True(added!.IsMesReportableOverride);
}
/// <summary>Verifies that set instance native alarm source override, when with design role, returns unauthorized.</summary>
[Fact]
public void SetInstanceNativeAlarmSourceOverride_WithDesignRole_ReturnsUnauthorized()