fix(transport): Overwrite resolution now syncs child collections (2 findings)

Transport-001: template Overwrite now diff-and-merges the bundle's
Attributes / Alarms / Scripts onto the target template via three private
helpers (SyncTemplateAttributesAsync / SyncTemplateAlarmsAsync /
SyncTemplateScriptsAsync). Each helper emits one audit row per detected
add / update / delete and feeds the post-merge state into the existing
ResolveAlarmScriptLinks and ResolveCompositionEdges passes.

Transport-002: external-system Overwrite now syncs the Methods collection
via a parallel SyncExternalSystemMethodsAsync helper mirroring the T-001
shape, with ExternalSystemMethodAdded / Updated / Deleted audit rows.

Both fixes are covered by new integration tests in BundleImporterApplyTests.
README regenerated — open findings dropped from 146 to 136; all 10 open
High findings are now closed (0 Critical, 0 High, 46 Medium, 90 Low
remaining).
This commit is contained in:
Joseph Doherty
2026-05-28 05:54:03 -04:00
parent ac96b83b08
commit e3ca9af1be
4 changed files with 758 additions and 35 deletions
+25 -10
View File
@@ -53,9 +53,23 @@ entry-count / per-entry decompression cap).
|--|--|
| Severity | High |
| Category | Correctness & logic bugs |
| Status | Open |
| Status | Resolved |
| Location | `src/ScadaLink.Transport/Import/BundleImporter.cs:844-851` |
**Resolution** — Extended `ApplyTemplatesAsync`'s Overwrite branch with three
new private diff-and-merge helpers (`SyncTemplateAttributesAsync`,
`SyncTemplateAlarmsAsync`, `SyncTemplateScriptsAsync`) that compare the bundle
DTO's children against the tracked existing template's collections by name and
stage add / update / delete via the audited repository methods. Each detected
change emits one of the per-field audit events the design doc enumerates
(`TemplateAttributeAdded` / `TemplateAttributeUpdated` /
`TemplateAttributeDeleted` and the alarm / script analogues); the existing
`ResolveAlarmScriptLinksAsync` and `ResolveCompositionEdgesAsync` passes rewire
the alarm→script FK and composition graph against the post-merge state with no
changes — Overwrite-on-alarms resets `OnTriggerScriptId` so Pass A is
authoritative. Regression test:
`BundleImporterApplyTests.ApplyAsync_Overwrite_synchronises_attributes_alarms_and_scripts_to_bundle`.
**Description**
The `ResolutionAction.Overwrite` branch in `ApplyTemplatesAsync` only writes
@@ -80,19 +94,24 @@ composition rewire passes against the post-merge state. Emit the per-field audit
rows the design doc enumerates. Add an integration test that overwrites a
template whose Scripts / Attributes / Alarms differ.
**Resolution**
_Unresolved._
### Transport-002 — ExternalSystem Overwrite never syncs methods
| | |
|--|--|
| Severity | High |
| Category | Correctness & logic bugs |
| Status | Open |
| Status | Resolved |
| Location | `src/ScadaLink.Transport/Import/BundleImporter.cs:1213-1221` |
**Resolution** — Added a private `SyncExternalSystemMethodsAsync` helper to
`BundleImporter` modeled on the T-001 `SyncTemplate*Async` helpers (dictionary-
by-name diff, repo Add / Update / Delete, scalar-field-compare gating, one
audit row per change). The `ApplyExternalSystemsAsync` Overwrite branch now
calls it after the parent scalar update; the helper emits
`ExternalSystemMethodAdded` / `ExternalSystemMethodUpdated` /
`ExternalSystemMethodDeleted` per change. Covered by
`ApplyAsync_Overwrite_synchronises_external_system_methods_to_bundle`.
**Description**
`ApplyExternalSystemsAsync` Overwrite path writes `EndpointUrl`, `AuthType`, and
@@ -111,10 +130,6 @@ diff classification in `ArtifactDiff.CompareExternalSystem`) and emit the
per-method audit rows. Add a test that overwrites an external system whose
methods differ.
**Resolution**
_Unresolved._
### Transport-003 — Unlock lockout is enforced only client-side; server session is never marked Locked
| | |