fix(host): resolve Host-003,004 — replace plaintext secrets with env placeholders, validate site seed-node ports; re-triage Host-002

This commit is contained in:
Joseph Doherty
2026-05-16 21:22:01 -04:00
parent 016bdf9c3c
commit 6563511b5f
9 changed files with 297 additions and 18 deletions

View File

@@ -254,6 +254,62 @@ public class StartupValidatorTests
Assert.Null(ex);
}
[Fact]
public void Site_SeedNodeOnGrpcPort_FailsValidation()
{
// Host-004 regression: a site seed node must reference an Akka remoting
// endpoint, never the Kestrel HTTP/2 gRPC port. A seed node whose port
// equals this node's GrpcPort would make a joining node attempt an
// Akka.Remote TCP association against the gRPC listener and fail.
var values = ValidSiteConfig();
values["ScadaLink:Node:GrpcPort"] = "8083";
values["ScadaLink:Cluster:SeedNodes:1"] = "akka.tcp://scadalink@site-a-node1:8083";
var config = BuildConfig(values);
var ex = Assert.Throws<InvalidOperationException>(() => StartupValidator.Validate(config));
Assert.Contains("must not target the gRPC port", ex.Message);
}
[Fact]
public void Site_SeedNodeOnDefaultGrpcPort_FailsValidation()
{
// GrpcPort is absent here, so the NodeOptions default of 8083 applies.
// A seed node on 8083 must still be rejected.
var values = ValidSiteConfig();
values["ScadaLink:Cluster:SeedNodes:1"] = "akka.tcp://scadalink@site-a-node2:8083";
var config = BuildConfig(values);
var ex = Assert.Throws<InvalidOperationException>(() => StartupValidator.Validate(config));
Assert.Contains("must not target the gRPC port", ex.Message);
}
[Fact]
public void Site_SeedNodesOnRemotingPort_PassesValidation()
{
// Two distinct site nodes, both seed entries on the remoting port (8082).
var values = ValidSiteConfig();
values["ScadaLink:Node:GrpcPort"] = "8083";
values["ScadaLink:Cluster:SeedNodes:0"] = "akka.tcp://scadalink@site-a-node1:8082";
values["ScadaLink:Cluster:SeedNodes:1"] = "akka.tcp://scadalink@site-a-node2:8082";
var config = BuildConfig(values);
var ex = Record.Exception(() => StartupValidator.Validate(config));
Assert.Null(ex);
}
[Fact]
public void Central_SeedNodeOnPort8083_PassesValidation()
{
// The gRPC-port rule applies to Site nodes only. A Central node has no
// GrpcPort, so a seed node on 8083 must not be rejected.
var values = ValidCentralConfig();
values["ScadaLink:Cluster:SeedNodes:1"] = "akka.tcp://scadalink@central-node2:8083";
var config = BuildConfig(values);
var ex = Record.Exception(() => StartupValidator.Validate(config));
Assert.Null(ex);
}
[Fact]
public void MultipleErrors_AllReported()
{