fix(transport): validate MaxConcurrentImportSessions at startup — a zero cap no longer bricks imports silently (plan R2-05 T8)

This commit is contained in:
Joseph Doherty
2026-07-13 10:05:31 -04:00
parent db623c1435
commit 9b4890326e
2 changed files with 20 additions and 0 deletions
@@ -48,6 +48,10 @@ public sealed class TransportOptionsValidator : OptionsValidatorBase<TransportOp
$"ScadaBridge:Transport:MaxUnlockAttemptsPerSession must be positive " +
$"(was {options.MaxUnlockAttemptsPerSession}); it caps failed passphrase attempts before a session locks.");
builder.RequireThat(options.MaxConcurrentImportSessions > 0,
$"ScadaBridge:Transport:MaxConcurrentImportSessions must be positive " +
$"(was {options.MaxConcurrentImportSessions}); a zero/negative cap rejects every import session forever.");
builder.RequireThat(options.MaxUnlockAttemptsPerIpPerHour > 0,
$"ScadaBridge:Transport:MaxUnlockAttemptsPerIpPerHour must be positive " +
$"(was {options.MaxUnlockAttemptsPerIpPerHour}); it caps unlock attempts per IP address per hour.");
@@ -38,6 +38,22 @@ public class TransportOptionsValidatorTests
Assert.Contains("MaxBundleSizeMb", result.FailureMessage);
}
[Fact]
public void ZeroMaxConcurrentImportSessions_IsRejected()
{
var result = Validate(new TransportOptions { MaxConcurrentImportSessions = 0 });
Assert.True(result.Failed);
Assert.Contains("MaxConcurrentImportSessions", result.FailureMessage); // FAILS today: validates clean
}
[Fact]
public void NegativeMaxConcurrentImportSessions_IsRejected()
{
var result = Validate(new TransportOptions { MaxConcurrentImportSessions = -1 });
Assert.True(result.Failed);
Assert.Contains("MaxConcurrentImportSessions", result.FailureMessage);
}
[Fact]
public void ZeroPbkdf2Iterations_IsRejected()
{