Merge branch 'fix/standby-secret-mirror-status' (M1: standby mirror failures on the health report)
# Conflicts: # CLAUDE.md # docs/plans/2026-09-28-site-secrets-artifact-deploy-design.md
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
/// <summary>
|
||||
/// One site node's latest deployed-secrets mirror outcome, as carried on
|
||||
/// <see cref="SiteHealthReport.SecretMirrorStatuses"/> (review finding M1).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Every site node runs its own <c>DeployedSecretsMirror</c> and records its current
|
||||
/// failure set in the LocalDb-replicated <c>secret_mirror_status</c> table, keyed by node
|
||||
/// name; the ACTIVE node reads every row and ships them on its health report, so a
|
||||
/// STANDBY node's failures (most importantly a master-key mismatch that stops a deployed
|
||||
/// secret decrypting there) reach central before a failover exposes them. Carries names
|
||||
/// and human-readable messages only — never a secret value or ciphertext.
|
||||
/// </remarks>
|
||||
/// <param name="NodeName">The reporting node's semantic name (<c>node-a</c>/<c>node-b</c>), or its host name when unconfigured.</param>
|
||||
/// <param name="CheckedAtUtc">When that node last recorded a CHANGE in its failure set (or its first pass after start-up) — not the time of its latest pass.</param>
|
||||
/// <param name="Failures">That node's current mirror failures; empty when the node's mirror is healthy.</param>
|
||||
public sealed record SecretMirrorNodeStatus(
|
||||
string NodeName,
|
||||
DateTimeOffset CheckedAtUtc,
|
||||
IReadOnlyList<SecretMirrorFailure> Failures);
|
||||
|
||||
/// <summary>A single deployed secret that failed to apply and/or decrypt on one site node.</summary>
|
||||
/// <param name="SecretName">The secret's name.</param>
|
||||
/// <param name="Message">A human-readable failure message — never includes the secret's value.</param>
|
||||
public sealed record SecretMirrorFailure(string SecretName, string Message);
|
||||
@@ -173,6 +173,20 @@ public record SiteHealthReport(
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public bool? StartupReconcilerActive { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Every site node's latest deployed-secrets mirror outcome (review finding M1) — one
|
||||
/// entry per node that has recorded a row in the replicated <c>secret_mirror_status</c>
|
||||
/// table, including the STANDBY node, whose own health report is never sent.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <b>Null = no data</b>: a central self-report, a pre-M1 site build, a site whose
|
||||
/// reporter has not run yet, or a failed read. An EMPTY list means the feature is wired
|
||||
/// but no node has recorded a status yet. A node entry with an empty
|
||||
/// <see cref="SecretMirrorNodeStatus.Failures"/> list is a healthy mirror. Names and
|
||||
/// messages only — never secret values or ciphertext.
|
||||
/// </remarks>
|
||||
public IReadOnlyList<SecretMirrorNodeStatus>? SecretMirrorStatuses { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user