fix(commons): resolve Commons-008 — replace ValueTuple in SetConnectionBindingsCommand with named ConnectionBinding record (CLI, ManagementService, TemplateEngine, CentralUI)

This commit is contained in:
Joseph Doherty
2026-05-16 23:54:31 -04:00
parent c583598888
commit b1f4251d75
8 changed files with 97 additions and 23 deletions

View File

@@ -8,7 +8,7 @@
| Last reviewed | 2026-05-16 |
| Reviewer | claude-agent |
| Commit reviewed | `9c60592` |
| Open findings | 1 |
| Open findings | 0 |
## Summary
@@ -357,7 +357,7 @@ carve-out makes these types compliant by design.
|--|--|
| Severity | Low |
| Category | Akka.NET conventions |
| Status | Open |
| Status | Resolved |
| Location | `src/ScadaLink.Commons/Messages/Management/InstanceCommands.cs:10` |
**Description**
@@ -379,18 +379,26 @@ Replace the tuple with a small named record, e.g.
**Resolution**
_Open — deferred to a coordinated multi-module change._ The finding is confirmed valid:
the `ValueTuple` is the only positional/tuple element in `Messages/` and is unfriendly to
REQ-COM-5a additive evolution. However, `SetConnectionBindingsCommand.Bindings` is not a
Commons-internal type — its `IReadOnlyList<(string,int)>` shape is part of a cross-module
contract consumed by `ScadaLink.CLI` (`InstanceCommands.TryParseBindings` builds a
`List<(string,int)>` and passes it to the constructor), `ScadaLink.ManagementService`
(`ManagementActor` forwards `cmd.Bindings`), and `ScadaLink.TemplateEngine`
(`InstanceService.SetConnectionBindingsAsync` takes an `IReadOnlyList<(string AttributeName,
int DataConnectionId)>` parameter). Introducing a `ConnectionBinding` record therefore
requires editing those three modules in lock-step, which is outside the scope of this
Commons-only review pass (the constraint forbids touching other modules' source). Left
Open and flagged for a follow-up cross-module change; the fix itself is unambiguous.
Resolved 2026-05-16 (commit `<pending>`) — confirmed against the source: the `ValueTuple`
was the only positional/tuple element in `Messages/` and `System.Text.Json` serializes it
as `Item1`/`Item2`, unfriendly to REQ-COM-5a additive evolution. Introduced a named record
`ConnectionBinding(string AttributeName, int DataConnectionId)` in
`Messages/Management/InstanceCommands.cs` (alongside the command, matching the existing
record-per-file convention) and changed `SetConnectionBindingsCommand.Bindings` to
`IReadOnlyList<ConnectionBinding>`. All consumers were updated in lock-step: `ScadaLink.CLI`
(`InstanceCommands.TryParseBindings` now builds a `List<ConnectionBinding>`),
`ScadaLink.TemplateEngine` (`InstanceService.SetConnectionBindingsAsync` parameter),
`ScadaLink.ManagementService` (`ManagementActor` forwards `cmd.Bindings` unchanged — the
new element type flows through), and one consumer the finding did not list,
`ScadaLink.CentralUI` (`InstanceConfigure.razor`'s `SaveBindings` built a `List<(string,int)>`).
A repo-wide `src/` scan confirms no other references remain. Regression tests added in
`ConnectionBindingSerializationTests` (`ConnectionBinding_SerializesWithNamedProperties`
asserts named `AttributeName`/`DataConnectionId` JSON properties and the absence of
`Item1`/`Item2`; `SetConnectionBindingsCommand_RoundTripsThroughJson` asserts a full
JSON round-trip); existing parse/forward tests (`ParseBindings_ValidJson_ReturnsPairs`,
`SetConnectionBindings_BulkAssignment_Success`) were updated to the new type. Affected
suites are green (Commons 226, CLI 77, ManagementService 55, TemplateEngine 287) and
`dotnet build ScadaLink.slnx` is clean.
### Commons-009 — `Component-Commons.md` is stale relative to the actual file set