fix(secrets): share the central connstr validation with the Layer-A expander

The blank/${secret:} pre-checks lived only in AddScadaBridgeSecrets, but on
a real central boot the Layer-A expander runs FIRST and would hand a bad
value to SqlConnection, burying the designed message under a generic
'initialization string' format error. Extracted both checks into
EnsureCentralSharedStoreConnectionString — one definition, called by the
expander (earliest point) and by registration (covers embedded/test
composition) — same single-source lesson as the UsesGrpcHub predicate.

Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1
This commit is contained in:
Joseph Doherty
2026-08-07 10:36:13 -04:00
parent 43e87a7492
commit a358244d9e
2 changed files with 64 additions and 44 deletions
+6 -5
View File
@@ -60,18 +60,19 @@ var configuration = new ConfigurationBuilder()
// scadaproj#4) — an expander left on SQLite there would resolve pre-host ${secret:} references
// from a stale/empty local store, silently diverging from what the node's own hub serves. Every
// other case (sites, SqlServer mode, replication off) keeps the local SQLite path exactly as it
// always was. Central+Grpc with a BLANK connection string deliberately falls through to the
// SQLite path too: that boot is about to fail in AddScadaBridgeSecrets with the message naming
// Secrets:SqlServer:ConnectionString, so the throw is not duplicated here.
// always was. A blank or ${secret:}-valued connection string fails HERE, through the same
// EnsureCentralSharedStoreConnectionString check AddScadaBridgeSecrets runs — this is the
// earliest code that would otherwise hand the bad value to SqlConnection, whose generic
// "initialization string" format error would bury the designed message.
var expanderUsesSharedSqlStore =
string.Equals(
configuration["ScadaBridge:Node:Role"], "Central", StringComparison.OrdinalIgnoreCase)
&& SecretsRegistration.UsesGrpcHub(configuration)
&& !string.IsNullOrWhiteSpace(configuration[SecretsRegistration.HubConnectionStringKey]);
&& SecretsRegistration.UsesGrpcHub(configuration);
var expanderServices = new ServiceCollection();
if (expanderUsesSharedSqlStore)
{
SecretsRegistration.EnsureCentralSharedStoreConnectionString(configuration);
expanderServices.AddZbSecretsSqlServerStore(configuration, "Secrets");
}
else