fix(cluster): T7's post-overlay guard was structurally unreachable — compare live Cluster:Roles, not the PostConfigured options.Roles (review finding, R3-04)
options.Roles is unconditionally overwritten by AddOtOpcUaCluster's PostConfigure to equal EffectiveRoles.Gossiped (T2's own structural-identity fix), so comparing options.Roles against Gossiped could never observe a divergence — an overlay setting Cluster:Roles was silently ignored, not fail-start. The validator now injects IConfiguration and re-reads the raw Cluster:Roles section LIVE (reflecting any overlay applied after EffectiveRoles was first resolved), normalized through EffectiveRoles.Resolve for reuse of its own validation. AddOtOpcUaCluster now TryAddSingleton(configuration) so a bare ServiceCollection test harness (not just WebApplicationBuilder) can supply IConfiguration to the validator. Both guard tests rewritten to go through the real AddOtOpcUaCluster + PostConfigure pipeline over a live ConfigurationManager, simulating an overlay as a second provider added AFTER EffectiveRoles was resolved off the same object — exactly Program.cs's own sequencing. Confirmed red beforehand: the "changes" test failed to throw against the pre-fix validator.
This commit is contained in:
@@ -45,6 +45,15 @@ public static class ServiceCollectionExtensions
|
||||
// TryAddSingleton keeps this usable from a harness that registers its own EffectiveRoles first.
|
||||
services.TryAddSingleton(_ => EffectiveRoles.Resolve(configuration));
|
||||
|
||||
// Review finding (2026-08-20): AkkaClusterOptionsValidator's post-overlay guard needs to
|
||||
// re-read Cluster:Roles LIVE, off the current (possibly overlay-mutated) configuration — not
|
||||
// off the pre-overlay EffectiveRoles snapshot above, and not off the bound AkkaClusterOptions
|
||||
// (the PostConfigure two lines below makes that equal to the snapshot BY CONSTRUCTION, so
|
||||
// comparing the guard against it could never observe a divergence). A bare ServiceCollection
|
||||
// (unlike WebApplicationBuilder, which auto-registers IConfiguration) never registers this
|
||||
// otherwise; TryAddSingleton is a no-op on a real host, where it is already registered.
|
||||
services.TryAddSingleton(configuration);
|
||||
|
||||
// Gitea #532 (superseded by R3-04): apply the OTOPCUA_ROLES fallback the Roles property has
|
||||
// always DOCUMENTED, in the one place every consumer reads through. Before this, a node
|
||||
// configured only through the env var — the knob that drives all of Program.cs's role wiring —
|
||||
|
||||
Reference in New Issue
Block a user