diff --git a/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json b/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json
index b50deccb..eb478c82 100644
--- a/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json
+++ b/archreview/plans/R2-06-serverhistorian-failfast-plan.md.tasks.json
@@ -5,7 +5,7 @@
{
"id": "T1",
"subject": "RED: misconfig repro test — HistorianGatewayClientAdapter.Create with empty/malformed Endpoint must throw a named InvalidOperationException (currently UriFormatException; test MUST fail on current code)",
- "status": "pending",
+ "status": "completed",
"blockedBy": []
},
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs
index 08dcc002..1a86a92e 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/HistorianGatewayClientAdapterTests.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
+using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Runtime.Historian;
@@ -21,6 +22,38 @@ public sealed class HistorianGatewayClientAdapterTests
Assert.NotNull(adapter);
}
+ ///
+ /// archreview 06/S-11 — an enabled historian with an empty Endpoint must fail with a
+ /// named, config-key-carrying (defense-in-depth for any
+ /// caller that bypasses the Host's ServerHistorianOptionsValidator), not the raw
+ /// that new Uri("") throws deep in the factory. Current
+ /// code throws → this is the failing-first (RED) repro.
+ ///
+ [Fact]
+ public void Create_with_empty_endpoint_throws_named_config_error()
+ {
+ var opts = new ServerHistorianOptions { Enabled = true, Endpoint = "", ApiKey = "histgw_x_y" };
+
+ var ex = Should.Throw(
+ () => HistorianGatewayClientAdapter.Create(opts, NullLoggerFactory.Instance));
+ ex.Message.ShouldContain("ServerHistorian:Endpoint");
+ }
+
+ ///
+ /// archreview 06/S-11 companion — a non-empty but unparseable / non-absolute Endpoint must
+ /// also fail with the same named , not a raw
+ /// . RED on current code.
+ ///
+ [Fact]
+ public void Create_with_malformed_endpoint_throws_named_config_error()
+ {
+ var opts = new ServerHistorianOptions { Enabled = true, Endpoint = "not a uri", ApiKey = "histgw_x_y" };
+
+ var ex = Should.Throw(
+ () => HistorianGatewayClientAdapter.Create(opts, NullLoggerFactory.Instance));
+ ex.Message.ShouldContain("ServerHistorian:Endpoint");
+ }
+
[Fact]
public void Factory_builds_GatewayHistorianDataSource()
{