fix(secrets): registration and hub mapping share the UsesGrpcHub predicate (review Important)
AddScadaBridgeSecrets now branches on UsesGrpcHub instead of re-deriving the same condition, so the doc's single-predicate claim is enforced rather than aspirational; the role split is a switch with a default-throw so a future third role must choose its hub half explicitly. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1
This commit is contained in:
@@ -187,32 +187,41 @@ public static class SecretsRegistration
|
|||||||
ArgumentNullException.ThrowIfNull(services);
|
ArgumentNullException.ThrowIfNull(services);
|
||||||
ArgumentNullException.ThrowIfNull(config);
|
ArgumentNullException.ThrowIfNull(config);
|
||||||
|
|
||||||
var enabled = config.GetValue<bool>(ReplicationEnabledKey);
|
// UsesGrpcHub is the single predicate shared with MapScadaBridgeSecretsHub — the branch
|
||||||
var mode = ResolveReplicationMode(config);
|
// condition must never be re-derived here, or registration and endpoint mapping could
|
||||||
|
// disagree about whether the hub is on.
|
||||||
if (enabled && mode == SecretsReplicationMode.Grpc)
|
if (UsesGrpcHub(config))
|
||||||
{
|
{
|
||||||
// Neither gRPC extension registers the local store — pull-only means local writes
|
// Neither gRPC extension registers the local store — pull-only means local writes
|
||||||
// never leave the node, so there is nothing to decorate and the store stays exactly as
|
// never leave the node, so there is nothing to decorate and the store stays exactly as
|
||||||
// configured. Register it first; both halves resolve it.
|
// configured. Register it first; both halves resolve it.
|
||||||
services.AddZbSecrets(config, SecretsSectionPath);
|
services.AddZbSecrets(config, SecretsSectionPath);
|
||||||
|
|
||||||
if (role == SecretsNodeRole.Central)
|
switch (role)
|
||||||
{
|
{
|
||||||
// Throws when Secrets:GrpcHub:BearerToken is unset. Deliberately not caught: a hub
|
case SecretsNodeRole.Central:
|
||||||
// that starts and refuses every follower looks like a network fault from the site
|
// Throws when Secrets:GrpcHub:BearerToken is unset. Deliberately not caught: a
|
||||||
// end, and would be discovered as a stale secret rather than as a boot failure.
|
// hub that starts and refuses every follower looks like a network fault from
|
||||||
|
// the site end, and would be discovered as a stale secret rather than as a
|
||||||
|
// boot failure.
|
||||||
services.AddZbSecretsGrpcHub(config, GrpcHubSectionPath);
|
services.AddZbSecretsGrpcHub(config, GrpcHubSectionPath);
|
||||||
}
|
break;
|
||||||
else
|
case SecretsNodeRole.Site:
|
||||||
{
|
|
||||||
// Throws when Secrets:GrpcHub:Endpoint or :BearerToken is unset. Same reasoning.
|
// Throws when Secrets:GrpcHub:Endpoint or :BearerToken is unset. Same reasoning.
|
||||||
services.AddZbSecretsGrpcHubClient(config, GrpcHubSectionPath);
|
services.AddZbSecretsGrpcHubClient(config, GrpcHubSectionPath);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(role), role,
|
||||||
|
"Unknown SecretsNodeRole — a new role must decide explicitly which half " +
|
||||||
|
"of the gRPC hub it composes rather than fall into either branch.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reached with the mode already validated (UsesGrpcHub resolves it on every path), so a
|
||||||
|
// false answer here means SqlServer mode or replication off — never an unvetted mode value.
|
||||||
|
var enabled = config.GetValue<bool>(ReplicationEnabledKey);
|
||||||
var connectionString = config[HubConnectionStringKey];
|
var connectionString = config[HubConnectionStringKey];
|
||||||
|
|
||||||
if (enabled && !string.IsNullOrWhiteSpace(connectionString))
|
if (enabled && !string.IsNullOrWhiteSpace(connectionString))
|
||||||
|
|||||||
Reference in New Issue
Block a user