Auto: focas-f4d — password / unlock parameter

Closes #271
This commit is contained in:
Joseph Doherty
2026-04-26 05:45:13 -04:00
parent d676b4056d
commit 86f3fc2733
16 changed files with 1016 additions and 40 deletions

View File

@@ -197,12 +197,44 @@ public sealed record FocasFixedTreeOptions
/// <paramref name="OverrideParameters"/> declares the four MTB-specific override
/// <c>cnc_rdparam</c> numbers surfaced under <c>Override/</c>; pass <c>null</c> to
/// suppress the entire <c>Override/</c> subfolder for that device (issue #259).
/// <paramref name="Password"/> (issue #271, plan PR F4-d) is the CNC connection-level
/// password emitted via <c>cnc_wrunlockparam</c> on connect when the controller
/// gates parameter writes / certain reads behind a password switch (16i + some
/// 30i firmwares with parameter-protect on).
/// </summary>
/// <remarks>
/// <para><b>No-log invariant:</b> <see cref="Password"/> is a secret. The driver MUST NOT
/// log it. <c>FocasDeviceOptions.ToString()</c> would include the field by default
/// because it's a positional record member, so the record's auto-generated
/// <c>ToString</c> is overridden via <see cref="PrintMembers"/> below to redact
/// the password. Any new logging surface that touches <see cref="FocasDeviceOptions"/>
/// must continue to redact. See <c>docs/v2/focas-deployment.md</c> § "FOCAS password
/// handling" for the no-log invariant and rotation runbook.</para>
/// </remarks>
public sealed record FocasDeviceOptions(
string HostAddress,
string? DeviceName = null,
FocasCncSeries Series = FocasCncSeries.Unknown,
FocasOverrideParameters? OverrideParameters = null);
FocasOverrideParameters? OverrideParameters = null,
string? Password = null)
{
/// <summary>
/// Issue #271 (plan PR F4-d) — record auto-generated <c>ToString</c> would print
/// <see cref="Password"/> verbatim. Override the printer so the secret is replaced
/// with <c>"***"</c> when the field is non-null. The no-log invariant relies on
/// this — every Serilog destructure that flows a <see cref="FocasDeviceOptions"/>
/// value through <c>{Device}</c> gets redaction for free.
/// </summary>
private bool PrintMembers(System.Text.StringBuilder builder)
{
builder.Append("HostAddress = ").Append(HostAddress);
builder.Append(", DeviceName = ").Append(DeviceName);
builder.Append(", Series = ").Append(Series);
builder.Append(", OverrideParameters = ").Append(OverrideParameters);
builder.Append(", Password = ").Append(Password is null ? "<null>" : "***");
return true;
}
}
/// <summary>
/// One FOCAS-backed OPC UA variable. <paramref name="Address"/> is the canonical FOCAS