feat(cluster): AllowSingleNodeCluster flag — single-seed installs drop the phantom seed

Validator lowers the seed-count floor to 1 when AllowSingleNodeCluster is set,
otherwise still requires 2 and points operators at the flag. The plan's
deploy/wonder-app-vd03/appsettings.Central.json edit is skipped: that production
deploy artifact is not tracked in this repo (only its deployment record doc is).
This commit is contained in:
Joseph Doherty
2026-07-08 16:39:12 -04:00
parent 0e3c1df1a7
commit ce66e194a8
3 changed files with 56 additions and 5 deletions
@@ -69,6 +69,47 @@ public class ClusterOptionsValidatorTests
Assert.Contains("SeedNodes", result.FailureMessage);
}
[Fact]
public void SingleSeed_WithoutAcknowledgement_Fails()
{
var options = ValidOptions();
options.SeedNodes = new List<string> { "akka.tcp://scadabridge@h:8081" };
var result = new ClusterOptionsValidator().Validate(null, options);
Assert.True(result.Failed);
Assert.Contains("AllowSingleNodeCluster", result.FailureMessage);
}
[Fact]
public void SingleSeed_WithAllowSingleNodeCluster_Passes()
{
// Review 01 [Low]: the shipped single-node artifact satisfied the 2-seed
// rule with a phantom seed the node dials forever. An explicit
// acknowledgement flag replaces the fiction.
var options = ValidOptions();
options.SeedNodes = new List<string> { "akka.tcp://scadabridge@h:8081" };
options.AllowSingleNodeCluster = true;
var result = new ClusterOptionsValidator().Validate(null, options);
Assert.True(result.Succeeded, result.FailureMessage);
}
[Fact]
public void EmptySeeds_FailsEvenWithFlag()
{
// Zero seeds is always invalid — the flag lowers the floor to 1, not 0.
var options = ValidOptions();
options.SeedNodes = new List<string>();
options.AllowSingleNodeCluster = true;
var result = new ClusterOptionsValidator().Validate(null, options);
Assert.True(result.Failed);
Assert.Contains("SeedNodes", result.FailureMessage);
}
[Fact]
public void SingleSeedNode_FailsValidation()
{