fix(transport): transport template NativeAlarmSources — imports no longer amputate native alarm mirrors nor dangle instance overrides

New TemplateNativeAlarmSourceDto + init-only TemplateDto.NativeAlarmSources (empty
default, additive — IsInherited placeholders carried for the collision detector).
Exported in ToBundleContent, consumed in FromBundleContent + BuildTemplate, and a
new SyncTemplateNativeAlarmSourcesAsync runs the Overwrite add/update/delete child
sync with per-change audit rows. ArtifactDiff.CompareTemplate now DiffChildren over
native sources so Preview reports a NativeAlarmSources field change. Proven by an
end-to-end flatten test: an instance native-alarm-source override that dangled
pre-fix now resolves against the re-imported template source.

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-09 16:59:37 -04:00
parent 4df5109742
commit e4136cb920
7 changed files with 589 additions and 3 deletions
@@ -101,6 +101,15 @@ public sealed class ArtifactDiff
"Compositions",
changes);
DiffChildren(
existing.NativeAlarmSources,
incoming.NativeAlarmSources,
e => e.Name,
i => i.Name,
NativeAlarmSourcesEqual,
"NativeAlarmSources",
changes);
return BuildItem("Template", incoming.Name, changes);
}
@@ -665,6 +674,15 @@ public sealed class ArtifactDiff
&& e.ReturnDefinition == i.ReturnDefinition
&& e.IsLocked == i.IsLocked;
private static bool NativeAlarmSourcesEqual(TemplateNativeAlarmSource e, TemplateNativeAlarmSourceDto i) =>
e.Description == i.Description
&& e.ConnectionName == i.ConnectionName
&& e.SourceReference == i.SourceReference
&& e.ConditionFilter == i.ConditionFilter
&& e.IsLocked == i.IsLocked
&& e.IsInherited == i.IsInherited
&& e.LockedInDerived == i.LockedInDerived;
private static bool ExternalSystemMethodsEqual(ExternalSystemMethod e, ExternalSystemMethodDto i) =>
e.HttpMethod == i.HttpMethod
&& e.Path == i.Path