fix(code-review): resolve Batch 2 open findings (AbCip, AbLegacy, Galaxy, FOCAS)

- Driver.AbCip.Contracts-001: parse 'writable' from TagConfig JSON (default true) instead of hardcoding
- Driver.AbCip.Contracts-002/-003: Dt type comment; drop dead [Display]/[Range] annotations
- Driver.AbCip.Contracts-004: dedicated AbCipEquipmentTagParser test class (+15)
- Driver.AbCip-017: document Tick severity Low-fallback on Bad severity read
- Driver.AbLegacy.Contracts-002/-003/-004: isArray-scalar remarks (+tests), MaxTagBytes/ForFamily docs
- Driver.Galaxy.Browser-003 + Driver.Galaxy.Contracts-003: extract ResolveApiKey -> GalaxySecretRef (dedup)
- Driver.Galaxy-019: cache buffered-interval only on Ok + ILogger warnings + ClassifyIntervalReply (+tests)
- Driver.FOCAS.Contracts-002: thread WriteIdempotent through DiscoverAsync (+test)
This commit is contained in:
Joseph Doherty
2026-06-20 22:43:36 -04:00
parent 3cc6a5f30d
commit ab57e53b92
26 changed files with 577 additions and 220 deletions
@@ -116,6 +116,39 @@ public sealed class FocasDriverMediumFindingsTests
.ShouldBe(SecurityClassification.ViewOnly);
}
// ---- Driver.FOCAS.Contracts-002: WriteIdempotent threaded through DiscoverAsync ----
/// <summary>
/// Verifies that a tag authored with <c>WriteIdempotent: true</c> surfaces
/// <c>WriteIdempotent == true</c> on its discovered <see cref="DriverAttributeInfo"/>,
/// and that a tag with the default <c>WriteIdempotent: false</c> surfaces <c>false</c>.
/// Resolves Driver.FOCAS.Contracts-002 — the field was previously hardcoded to
/// <c>false</c> in <c>DiscoverAsync</c> and had no runtime effect.
/// </summary>
[Fact]
public async Task DiscoverAsync_surfaces_WriteIdempotent_from_tag_definition()
{
var builder = new RecordingBuilder();
var drv = new FocasDriver(new FocasDriverOptions
{
Devices = [new FocasDeviceOptions("focas://10.0.0.5:8193")],
Tags =
[
new FocasTagDefinition("Idempotent", "focas://10.0.0.5:8193", "R100", FocasDataType.Int16, WriteIdempotent: true),
new FocasTagDefinition("NonIdempotent", "focas://10.0.0.5:8193", "R200", FocasDataType.Int16, WriteIdempotent: false),
],
Probe = new FocasProbeOptions { Enabled = false },
}, "drv-1", new FakeFocasClientFactory());
await drv.InitializeAsync("{}", CancellationToken.None);
await drv.DiscoverAsync(builder, CancellationToken.None);
builder.Variables.Single(v => v.BrowseName == "Idempotent").Info.WriteIdempotent
.ShouldBeTrue("a tag declared WriteIdempotent:true must surface true on DriverAttributeInfo");
builder.Variables.Single(v => v.BrowseName == "NonIdempotent").Info.WriteIdempotent
.ShouldBeFalse("a tag declared WriteIdempotent:false (the default) must surface false");
}
// ---- Driver.FOCAS-005: Volatile-guarded _health survives concurrent reads ----
/// <summary>Verifies that GetHealth reflects state updated from concurrent reads.</summary>