Auto: focas-f4a — write infrastructure + per-tag opt-in

Closes #268
This commit is contained in:
Joseph Doherty
2026-04-26 04:32:43 -04:00
parent 6f1657b1c0
commit 1bfe8fba0e
13 changed files with 521 additions and 11 deletions

View File

@@ -73,7 +73,10 @@ public static class FocasDriverFactoryExtensions
Address: t.Address ?? throw new InvalidOperationException(
$"FOCAS tag '{t.Name}' in '{driverInstanceId}' missing Address"),
DataType: ParseDataType(t.DataType, t.Name!, driverInstanceId),
Writable: t.Writable ?? true,
// Per-tag Writable defaults to false post-F4-a (issue #268). A config-DB row
// with Writable null means "not opted in" — operators must explicitly flip
// the flag per tag before writes flow.
Writable: t.Writable ?? false,
WriteIdempotent: t.WriteIdempotent ?? false))]
: [],
Probe = new FocasProbeOptions
@@ -83,6 +86,13 @@ public static class FocasDriverFactoryExtensions
Timeout = TimeSpan.FromMilliseconds(dto.Probe?.TimeoutMs ?? 2_000),
},
Timeout = TimeSpan.FromMilliseconds(dto.TimeoutMs ?? 2_000),
// Driver-level write opt-in (issue #268, plan PR F4-a). Default false — config rows
// that omit the section keep the safer-by-default read-only posture; flipping it on
// requires an explicit deployment-time choice.
Writes = new FocasWritesOptions
{
Enabled = dto.Writes?.Enabled ?? false,
},
};
var clientFactory = BuildClientFactory(dto, driverInstanceId);
@@ -170,6 +180,12 @@ public static class FocasDriverFactoryExtensions
public List<FocasDeviceDto>? Devices { get; init; }
public List<FocasTagDto>? Tags { get; init; }
public FocasProbeDto? Probe { get; init; }
public FocasWritesDto? Writes { get; init; }
}
internal sealed class FocasWritesDto
{
public bool? Enabled { get; init; }
}
internal sealed class FocasDeviceDto