diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
index 5854613..860b900 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
@@ -44,6 +44,7 @@ internal sealed class CliArguments
/// Returns whether the named flag was present in the arguments.
/// The flag name (without '--' prefix).
+ /// true if the flag was present; otherwise, false.
public bool HasFlag(string name)
{
return _flags.Contains(name);
@@ -51,6 +52,7 @@ internal sealed class CliArguments
/// Returns the value for a named argument, or null if absent.
/// The argument name (without '--' prefix).
+ /// The argument value, or null if the argument is absent.
public string? GetOptional(string name)
{
return _values.TryGetValue(name, out string? value)
@@ -60,6 +62,7 @@ internal sealed class CliArguments
/// Returns the value for a required named argument, or throws if absent.
/// The argument name (without '--' prefix).
+ /// The argument value.
public string GetRequired(string name)
{
string? value = GetOptional(name);
@@ -74,6 +77,7 @@ internal sealed class CliArguments
/// Parses and returns an int32 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent; if null, the argument is required.
+ /// The parsed int32 value.
public int GetInt32(string name, int? defaultValue = null)
{
string? value = GetOptional(name);
@@ -93,6 +97,7 @@ internal sealed class CliArguments
/// Parses and returns a uint32 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed uint32 value.
public uint GetUInt32(string name, uint defaultValue)
{
string? value = GetOptional(name);
@@ -104,6 +109,7 @@ internal sealed class CliArguments
/// Parses and returns a uint64 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed uint64 value.
public ulong GetUInt64(string name, ulong defaultValue)
{
string? value = GetOptional(name);
@@ -115,6 +121,7 @@ internal sealed class CliArguments
/// Parses and returns a TimeSpan argument, or the default value if absent. Supports "ms", "s", and standard TimeSpan format.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed duration.
public TimeSpan GetDuration(string name, TimeSpan defaultValue)
{
string? value = GetOptional(name);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
index 568ad8c..2db83b2 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
@@ -108,7 +108,8 @@ internal sealed class MxGatewayCliClientAdapter : IMxGatewayCliClient
return _galaxyClient.Value.BrowseChildrenRawAsync(request, cancellationToken);
}
- ///
+ /// Disposes the adapted gateway client and, if created, the lazily-initialized Galaxy Repository client.
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
if (_galaxyClient.IsValueCreated)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
index d4e3003..b692eaa 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
@@ -6,6 +6,7 @@ internal static class MxGatewayCliSecretRedactor
/// Replaces occurrences of the API key in the value with a redacted placeholder.
/// The message text to redact.
/// The API key to remove; no redaction if null or empty.
+ /// The value with any occurrences of replaced by a redacted placeholder.
public static string Redact(string value, string? apiKey)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(apiKey))
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
index e8d56a8..0e47d8d 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
@@ -22,6 +22,7 @@ public static class MxGatewayClientCli
/// Command-line arguments (command name followed by options).
/// TextWriter for command output.
/// TextWriter for error messages.
+ /// The process exit code: 0 on success, 1 on error.
public static int Run(
string[] args,
TextWriter standardOutput,
@@ -38,6 +39,7 @@ public static class MxGatewayClientCli
/// TextWriter for error messages.
/// Optional factory to create the gateway client; defaults to MxGatewayClient.Create.
/// Optional TextReader for batch-mode stdin; defaults to .
+ /// A task producing the process exit code: 0 on success, 1 on error.
public static Task RunAsync(
string[] args,
TextWriter standardOutput,
@@ -155,9 +157,6 @@ public static class MxGatewayClientCli
}
catch (Exception exception) when (exception is not OperationCanceledException)
{
- // Client.Dotnet-028: redact the *effective* key — from --api-key or the
- // --api-key-env environment variable — so an env-var-sourced key echoed
- // in a transport error never reaches stderr unredacted.
string? apiKey = TryResolveApiKey(arguments);
string message = MxGatewayCliSecretRedactor.Redact(exception.Message, apiKey);
@@ -303,7 +302,7 @@ public static class MxGatewayClientCli
/// MXGATEWAY_API_KEY), returning when neither
/// is set. Unlike this never throws, so the
/// error-redaction catch block can strip the env-var-sourced key from
- /// output (Client.Dotnet-028) without re-raising on the absent-key path.
+ /// output without re-raising on the absent-key path.
///
private static string? TryResolveApiKey(CliArguments arguments)
{
@@ -744,7 +743,6 @@ public static class MxGatewayClientCli
/// (e.g. -1, an easy copy-paste mistake for "unbounded") is
/// rejected loudly rather than silently wrapped to ~49.7 days,
/// which would park one worker thread per pending tag for hours.
- /// Resolves Client.Dotnet-021.
///
private static uint ParseTimeoutMs(CliArguments arguments, int defaultValue)
{
@@ -766,7 +764,6 @@ public static class MxGatewayClientCli
/// its absence must not silently fall through to
/// ReturnValue.Int32Value (which would be 0 for an empty
/// reply, driving the rest of the bench against an invalid handle).
- /// Resolves Client.Dotnet-019.
///
private static int RequireRegisterServerHandle(MxCommandReply reply, string sessionId)
{
@@ -891,11 +888,6 @@ public static class MxGatewayClientCli
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
- // Client.Dotnet-020: never swallow OperationCanceledException
- // here. A bare `catch` would let Ctrl+C / parent CTS /
- // wall-clock timeouts keep spinning until --duration-seconds
- // elapsed, burning CPU and skewing the p99/max latency numbers
- // with hundreds of immediate-OCE iterations.
sw.Stop();
failedCalls++;
latencyMillis.Add(sw.Elapsed.TotalMilliseconds);
@@ -1122,8 +1114,6 @@ public static class MxGatewayClientCli
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
- // Client.Dotnet-017: graceful end-of-window completion mode for a
- // finite-window event collector. Emit aggregate JSON below and exit 0.
}
if (json && !jsonLines)
@@ -1193,10 +1183,6 @@ public static class MxGatewayClientCli
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
- // Mirrors stream-events (Client.Dotnet-017): the supplied token covers
- // the user's --timeout wall-clock budget and external Ctrl+C / parent
- // CTS cancellation. All are graceful completion modes for a
- // finite-window alarm-feed collector: emit what arrived and exit 0.
}
if (json && !jsonLines)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
index dd5f48e..943a106 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
@@ -14,6 +14,7 @@ public sealed class BrowseChildrenSmokeTests
/// Verifies that BrowseChildren returns a non-zero cache sequence and
/// a consistent children/child-has-children count from a live gateway.
///
+ /// A task that represents the asynchronous operation.
[Fact(Skip = "Set MXGATEWAY_API_KEY and MXGATEWAY_ENDPOINT to enable.")]
public async Task BrowseChildren_LiveGateway_ReturnsRootsWithCacheSequence()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
index a71d74c..4560929 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
@@ -8,14 +8,10 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
///
internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions options) : IGalaxyRepositoryClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
- ///
- /// Gets the raw gRPC client; always null for the fake.
- ///
+ ///
public GalaxyRepository.GalaxyRepositoryClient? RawClient => null;
///
@@ -66,11 +62,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
///
public Queue DiscoverHierarchyExceptions { get; } = new();
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The TestConnectionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task TestConnectionAsync(
TestConnectionRequest request,
CallOptions callOptions)
@@ -84,11 +76,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
return Task.FromResult(TestConnectionReply);
}
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The GetLastDeployTimeRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task GetLastDeployTimeAsync(
GetLastDeployTimeRequest request,
CallOptions callOptions)
@@ -102,11 +90,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
return Task.FromResult(GetLastDeployTimeReply);
}
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The DiscoverHierarchyRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task DiscoverHierarchyAsync(
DiscoverHierarchyRequest request,
CallOptions callOptions)
@@ -141,11 +125,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
///
public Func? BrowseChildrenGate { get; set; }
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The BrowseChildrenRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public async Task BrowseChildrenAsync(
BrowseChildrenRequest request,
CallOptions callOptions)
@@ -187,11 +167,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
///
public Func? WatchDeployEventsBeforeYield { get; set; }
- ///
- /// Records the request and streams events, checking for queued exceptions and calling WatchDeployEventsBeforeYield before each event.
- ///
- /// The WatchDeployEventsRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
index 7e81274..cb677fc 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
@@ -11,14 +11,10 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
private readonly Queue _invokeReplies = new();
private readonly List _events = [];
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
- ///
- /// Gets null, since this is a test fake without a real gRPC client.
- ///
+ ///
public MxAccessGateway.MxAccessGatewayClient? RawClient => null;
///
@@ -102,11 +98,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
///
public Queue InvokeExceptions { get; } = new();
- ///
- /// Verifies that the OpenSessionAsync call is recorded and returns the configured reply.
- ///
- /// The OpenSessionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task OpenSessionAsync(
OpenSessionRequest request,
CallOptions callOptions)
@@ -120,11 +112,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(OpenSessionReply);
}
- ///
- /// Verifies that the CloseSessionAsync call is recorded and returns the configured reply.
- ///
- /// The CloseSessionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task CloseSessionAsync(
CloseSessionRequest request,
CallOptions callOptions)
@@ -138,11 +126,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(CloseSessionReply);
}
- ///
- /// Verifies that the InvokeAsync call is recorded and returns the next enqueued reply.
- ///
- /// The MxCommandRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task InvokeAsync(
MxCommandRequest request,
CallOptions callOptions)
@@ -156,11 +140,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(_invokeReplies.Dequeue());
}
- ///
- /// Verifies that the StreamEventsAsync call is recorded and yields all enqueued events.
- ///
- /// The StreamEventsRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
CallOptions callOptions)
@@ -193,11 +173,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
_events.Add(gatewayEvent);
}
- ///
- /// Records the acknowledge call and returns the next enqueued reply (or default).
- ///
- /// The acknowledge alarm request.
- /// Call options specifying RPC behavior.
+ ///
public Task AcknowledgeAlarmAsync(
AcknowledgeAlarmRequest request,
CallOptions callOptions)
@@ -218,11 +194,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
});
}
- ///
- /// Records the query call and yields each enqueued snapshot.
- ///
- /// The query active alarms request.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable QueryActiveAlarmsAsync(
QueryActiveAlarmsRequest request,
CallOptions callOptions)
@@ -251,11 +223,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
_activeAlarmSnapshots.Add(snapshot);
}
- ///
- /// Records the stream-alarms call and yields each enqueued feed message.
- ///
- /// The stream alarms request.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable StreamAlarmsAsync(
StreamAlarmsRequest request,
CallOptions callOptions)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
index 351a9d2..184bde7 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
@@ -9,6 +9,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync attaches the API key in request metadata and returns the Ok flag.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_AttachesApiKeyMetadataAndReturnsOkFlag()
{
@@ -27,6 +28,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync returns false when the server reports NotOk.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_ReturnsFalseWhenServerReportsNotOk()
{
@@ -42,6 +44,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that GetLastDeployTimeAsync returns null when the server reports not present.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetLastDeployTimeAsync_ReturnsNullWhenNotPresent()
{
@@ -58,6 +61,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that GetLastDeployTimeAsync returns the timestamp when the server reports it present.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetLastDeployTimeAsync_ReturnsTimestampWhenPresent()
{
@@ -79,6 +83,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync returns the objects from the server reply.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_ReturnsObjectsFromReply()
{
@@ -141,6 +146,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync propagates cancellation tokens to the transport.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_PropagatesCancellationToTransport()
{
@@ -161,6 +167,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_WithRepeatedPageToken_ThrowsProtocolError()
{
@@ -184,6 +191,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync maps typed filter options correctly to the request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_WithOptions_MapsTypedFilters()
{
@@ -218,6 +226,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_RetriesOnTransientGrpcFailure()
{
@@ -235,6 +244,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_RetriesOnTransientGrpcFailure()
{
@@ -251,6 +261,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync delivers the bootstrap event.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_DeliversBootstrapEvent()
{
@@ -287,6 +298,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync delivers multiple events in order.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_DeliversMultipleEventsInOrder()
{
@@ -325,6 +337,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync stops iteration cleanly when cancelled.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_CancellationStopsIterationCleanly()
{
@@ -369,6 +382,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync throws ObjectDisposedException after the client is disposed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_ThrowsAfterDisposal()
{
@@ -384,6 +398,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync throws ObjectDisposedException after the client is disposed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_ThrowsAfterDisposal()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
index 875c9fa..448debf 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
@@ -12,6 +12,7 @@ public sealed class LazyBrowseNodeTests
/// Verifies that calling BrowseAsync with no parent returns the root nodes
/// from the first BrowseChildren reply and surfaces the per-child has-children hint.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Browse_NoParent_ReturnsRoots()
{
@@ -36,6 +37,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ExpandAsync populates Children and marks the node expanded after one RPC.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_PopulatesChildrenAndMarksExpanded()
{
@@ -62,6 +64,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that a second ExpandAsync call is a no-op and issues no additional RPC.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_CalledTwice_NoSecondRpc()
{
@@ -86,6 +89,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that an RPC failure (NotFound) during expand is wrapped in MxGatewayException.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_UnknownParent_ThrowsMxGatewayException()
{
@@ -113,6 +117,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ExpandAsync drains multi-page sibling replies and forwards the page token.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_MultiPageSiblings_GathersAllPages()
{
@@ -147,6 +152,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ten concurrent ExpandAsync calls issue exactly one RPC, not ten.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_CalledConcurrently_OnlyFiresOneRpc()
{
@@ -179,8 +185,9 @@ public sealed class LazyBrowseNodeTests
/// Verifies that reading Children/IsExpanded concurrently with an in-flight ExpandAsync
/// never throws (no torn enumeration of a mid-append list) and, once IsExpanded flips to
/// true, the published Children snapshot is fully populated. Pins the safe-publication
- /// contract on the lock-free readers (Client.Dotnet-025).
+ /// contract on the lock-free readers.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_ConcurrentReadOfChildren_NeverTearsAndPublishesAtomically()
{
@@ -268,6 +275,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that BrowseChildrenOptions filter fields are forwarded to the BrowseChildren request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Browse_WithFilter_ForwardsToRequest()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
index b178944..61582b6 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayClientAlarmsTests
{
/// AcknowledgeAlarmAsync records request and returns reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_RecordsRequestShapeAndReturnsReply()
{
@@ -48,6 +49,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// AcknowledgeAlarmAsync honors cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_HonorsCancellation()
{
@@ -72,6 +74,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// AcknowledgeAlarmAsync maps unauthenticated RPC exception to typed exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_MapsUnauthenticated_RpcException_ToTypedException()
{
@@ -97,6 +100,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync streams enqueued snapshots.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_StreamsEnqueuedSnapshots()
{
@@ -122,6 +126,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync passes filter prefix.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_PassesFilterPrefix()
{
@@ -142,6 +147,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync honors cancellation during enumeration.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_HonorsCancellationDuringEnumeration()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
index bd39120..27f6fe8 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
@@ -24,6 +24,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that the version command with --json flag prints JSON protocol versions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_VersionJson_PrintsJsonProtocolVersions()
{
@@ -38,6 +39,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that the write command builds a write request and prints JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Write_BuildsWriteCommandAndPrintsJsonReply()
{
@@ -83,7 +85,7 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-030: advise-supervisory was present in the command
+ /// advise-supervisory was present in the command
/// dispatch table but absent from 's
/// IsKnownGatewayCommand guard, so the guard intercepted it first and
/// returned exit code 2 "Unknown command" before dispatch could run. This
@@ -91,6 +93,7 @@ public sealed class MxGatewayClientCliTests
/// "Unknown command") and reaches the dispatch handler (exit 0, reply written
/// to stdout).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AdviseSupervisory_IsRecognizedAndReachesDispatch()
{
@@ -130,6 +133,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that error output redacts sensitive API key values.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_ErrorOutput_RedactsApiKey()
{
@@ -154,12 +158,13 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-028: when the API key is sourced from the env var
+ /// When the API key is sourced from the env var
/// (--api-key-env path, no --api-key flag), the error-redaction
/// catch block must still resolve and redact the effective key. Regression
/// guard for the catch block reverting to GetOptional("api-key") only,
/// which is null on the env-var path and leaves the key unredacted.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_ErrorOutput_RedactsApiKey_WhenSourcedFromEnvironmentVariable()
{
@@ -196,6 +201,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that stream-events with max-events limit stops output in non-JSON format.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_StreamEvents_WithMaxEventsStopsNonJsonOutput()
{
@@ -238,6 +244,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies that stream-alarms with --max-events stops output and distinguishes payload cases.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_StreamAlarms_WithMaxEventsStopsAndDistinguishesPayloadCases()
{
@@ -277,6 +284,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that acknowledge-alarm builds a request and prints the JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AcknowledgeAlarm_BuildsRequestAndPrintsJsonReply()
{
@@ -319,6 +327,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that smoke command closes opened session when a command fails.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Smoke_WhenCommandFails_ClosesOpenedSession()
{
@@ -350,6 +359,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-test-connection command prints JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyTestConnection_PrintsJsonReply()
{
@@ -380,6 +390,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-discover command prints hierarchy summary.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyDiscover_PrintsHierarchySummary()
{
@@ -453,6 +464,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies galaxy-browse walks root objects and eagerly expands one further
/// level when --depth 1 is passed, printing an indented tree.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyBrowse_TextTreeExpandsToDepth()
{
@@ -509,6 +521,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies galaxy-browse --json emits a nested JSON document and forwards
/// the filter flags onto the BrowseChildren request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyBrowse_JsonForwardsFilters()
{
@@ -553,6 +566,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies galaxy-browse --parent fetches exactly one level of children for
/// the supplied gobject id via a parent-scoped BrowseChildren request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyBrowse_ParentFetchesSingleLevel()
{
@@ -590,6 +604,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-watch command prints text output for deploy events.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyWatch_PrintsTextOutputForEvents()
{
@@ -644,6 +659,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-watch with --json emits one JSON object per event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyWatch_JsonEmitsOneObjectPerEvent()
{
@@ -679,6 +695,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that batch mode dispatches a single version command and emits the EOR sentinel.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Batch_DispatchesVersionAndWritesEndOfRecord()
{
@@ -705,6 +722,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that batch mode routes per-command errors to stdout as JSON between EOR markers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Batch_WritesErrorsToStdoutAsJson()
{
@@ -739,7 +757,7 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-018: the README CLI examples for the alarm subcommands at
+ /// The README CLI examples for the alarm subcommands at
/// `clients/dotnet/README.md` must drive cleanly through the production
/// CLI argument parser. The previous text used non-existent flags
/// (`--session-id`, `--max-messages`, `--alarm-reference`) that would
@@ -749,6 +767,7 @@ public sealed class MxGatewayClientCliTests
/// against exit code 0.
///
/// The alarm subcommand to validate (e.g. "stream-alarms", "acknowledge-alarm").
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("stream-alarms")]
[InlineData("acknowledge-alarm")]
@@ -797,12 +816,13 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-019: `BenchReadBulkAsync` previously fell back to
+ /// `BenchReadBulkAsync` previously fell back to
/// reply.ReturnValue.Int32Value when the register reply had no
/// typed Register payload, silently driving the rest of the bench
/// against a zero server handle. The fix must fail loudly with a
/// descriptive .
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_BenchReadBulk_WhenRegisterReplyMissingTypedPayload_FailsLoudly()
{
@@ -810,9 +830,6 @@ public sealed class MxGatewayClientCliTests
using var error = new StringWriter();
FakeCliClient fakeClient = new();
// Successful protocol + MX status but no typed `Register` payload.
- // Before the Client.Dotnet-019 fix this silently became serverHandle=0
- // and the bench proceeded through SubscribeBulk / warmup / steady-state
- // against an invalid handle, producing a misleading zero-result summary.
fakeClient.InvokeReplies.Enqueue(new MxCommandReply
{
SessionId = "session-fixture",
@@ -847,12 +864,13 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-020: the steady-state loop in `BenchReadBulkAsync` had a
+ /// The steady-state loop in `BenchReadBulkAsync` had a
/// bare `catch { failedCalls++; continue; }` that swallowed
/// , so token-driven cancellation
/// kept spinning until --duration-seconds elapsed. After the fix
/// the bench must exit promptly when the supplied token cancels.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_BenchReadBulk_WhenSteadyStateLoopReceivesCancellation_ExitsPromptly()
{
@@ -941,12 +959,13 @@ public sealed class MxGatewayClientCliTests
}
///
- /// Client.Dotnet-021: both `ReadBulkAsync` and `BenchReadBulkAsync` cast
+ /// Both `ReadBulkAsync` and `BenchReadBulkAsync` cast
/// the user-supplied --timeout-ms to without
/// bounds checking, so a negative value (e.g. -1) silently wraps
/// to ~49.7 days. The fix must reject negatives with a clear error.
///
/// The bulk-read subcommand to validate (e.g. "read-bulk", "bench-read-bulk").
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("read-bulk")]
[InlineData("bench-read-bulk")]
@@ -1109,7 +1128,8 @@ public sealed class MxGatewayClientCliTests
/// Optional per-call handler that overrides queue-based behaviour.
public Func>? InvokeHandler { get; init; }
- ///
+ /// Disposes the fake client. No-op; there are no unmanaged resources to release.
+ /// A task that represents the asynchronous operation.
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
index d827be1..2d135c6 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
@@ -7,6 +7,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayClientSessionTests
{
/// Verifies that open session attaches API key metadata and cancellation token.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionRawAsync_AttachesApiKeyMetadataAndCancellation()
{
@@ -22,6 +23,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that open session returns a session with the raw open reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_ReturnsSessionWithRawOpenReply()
{
@@ -37,6 +39,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that register builds a register command and returns server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RegisterAsync_BuildsRegisterCommandAndReturnsServerHandle()
{
@@ -62,6 +65,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that add item 2 builds a command with the specified context.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddItem2Async_BuildsAddItem2CommandWithContext()
{
@@ -87,6 +91,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write raw builds a write command with the raw value.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteRawAsync_BuildsWriteCommandWithRawValue()
{
@@ -118,6 +123,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write 2 raw builds a write 2 command with value and timestamp.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Write2RawAsync_BuildsWrite2CommandWithValueAndTimestamp()
{
@@ -146,6 +152,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that subscribe bulk builds one command and returns per-item results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeBulkAsync_BuildsOneBulkCommandAndReturnsPerItemResults()
{
@@ -185,6 +192,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that stream events yields events in the order received from the gateway.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_YieldsEventsInGatewayOrder()
{
@@ -216,6 +224,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that close is explicit and idempotent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseAsync_IsExplicitAndIdempotent()
{
@@ -232,6 +241,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke retries safe diagnostic commands on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_RetriesSafeDiagnosticCommandOnTransientGrpcFailure()
{
@@ -256,6 +266,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that open session does not retry on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_DoesNotRetryTransientGrpcFailure()
{
@@ -269,6 +280,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke does not retry write commands on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_DoesNotRetryWriteCommand()
{
@@ -284,6 +296,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke helpers pass cancellation token to the transport.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeHelpers_PassCancellationTokenToTransport()
{
@@ -330,6 +343,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that WriteArrayElementsAsync builds a write command whose value is a SparseArrayValue.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteArrayElementsAsync_BuildsWriteCommandWithSparseArrayValue()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
index 95fdd89..7c1593a 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
@@ -3,6 +3,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayGeneratedContractTests
{
/// Verifies that the generated gRPC client can be instantiated from the client factory.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GeneratedGrpcClient_CanBeConstructedFromClientFactory()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
index 7d05638..ee19b21 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
@@ -337,6 +337,9 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
cancellationToken);
}
+ /// Builds a BrowseChildren request from the caller-supplied filter options.
+ /// The browse-children filter options.
+ /// The populated request.
internal static BrowseChildrenRequest BuildBrowseChildrenRequest(BrowseChildrenOptions options)
{
ArgumentNullException.ThrowIfNull(options);
@@ -424,6 +427,7 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
///
/// Closes the gRPC channel and releases resources.
///
+ /// A task that represents the asynchronous operation.
public ValueTask DisposeAsync()
{
if (_disposed)
@@ -493,6 +497,9 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
private static HttpMessageHandler CreateHttpHandler(MxGatewayClientOptions options) =>
CreateHttpHandlerForTests(options);
+ /// Creates the used for gRPC calls, exposed for test configuration.
+ /// The client options supplying TLS and timeout settings.
+ /// The configured HTTP handler.
internal static SocketsHttpHandler CreateHttpHandlerForTests(MxGatewayClientOptions options)
{
SocketsHttpHandler handler = new()
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
index e51337e..e533db2 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
@@ -10,9 +10,7 @@ internal sealed class GrpcGalaxyRepositoryClientTransport(
MxGatewayClientOptions options,
GalaxyRepository.GalaxyRepositoryClient rawClient) : IGalaxyRepositoryClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
///
@@ -91,7 +89,16 @@ internal sealed class GrpcGalaxyRepositoryClientTransport(
}
}
- ///
+ ///
+ /// Watches for deployment events from the Galaxy Repository server.
+ ///
+ /// The watch deploy events request.
+ /// gRPC call options (timeout, cancellation, etc.).
+ ///
+ /// A cancellation token distinct from 's; when cancelable, it
+ /// takes precedence over the token carried by .
+ ///
+ /// An asynchronous stream of deploy events.
public async IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions,
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
index 5ff4e75..2198041 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
@@ -10,9 +10,7 @@ internal sealed class GrpcMxGatewayClientTransport(
MxGatewayClientOptions options,
MxAccessGateway.MxAccessGatewayClient rawClient) : IMxGatewayClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
///
@@ -74,7 +72,13 @@ internal sealed class GrpcMxGatewayClientTransport(
}
}
- ///
+ ///
+ /// Streams events from the session.
+ ///
+ /// The stream events request.
+ /// gRPC call options.
+ /// Cancellation token; falls back to 's token when not cancelable.
+ /// An async enumerable of events.
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
CallOptions callOptions,
@@ -133,7 +137,14 @@ internal sealed class GrpcMxGatewayClientTransport(
}
}
- ///
+ ///
+ /// Streams a snapshot of all alarms currently in Active or ActiveAcked state — the
+ /// ConditionRefresh equivalent for the gateway.
+ ///
+ /// The query request, optionally scoped by alarm-reference prefix.
+ /// gRPC call options.
+ /// Cancellation token; falls back to 's token when not cancelable.
+ /// An async enumerable of active-alarm snapshots.
public async IAsyncEnumerable QueryActiveAlarmsAsync(
QueryActiveAlarmsRequest request,
CallOptions callOptions,
@@ -175,7 +186,14 @@ internal sealed class GrpcMxGatewayClientTransport(
return QueryActiveAlarmsAsync(request, callOptions);
}
- ///
+ ///
+ /// Attaches to the gateway's central alarm feed — the current active-alarm
+ /// snapshot followed by live transitions.
+ ///
+ /// The stream request, optionally scoped by alarm-reference prefix.
+ /// gRPC call options.
+ /// Cancellation token; falls back to 's token when not cancelable.
+ /// An async enumerable of alarm feed messages.
public async IAsyncEnumerable StreamAlarmsAsync(
StreamAlarmsRequest request,
CallOptions callOptions,
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
index ddc5dcc..c5454b7 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
@@ -15,6 +15,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Tests the connection to the Galaxy Repository server.
/// The test connection request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// The test connection reply.
Task TestConnectionAsync(
TestConnectionRequest request,
CallOptions callOptions);
@@ -22,6 +23,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Gets the last deploy time from the Galaxy Repository server.
/// The get last deploy time request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// The last deploy time reply.
Task GetLastDeployTimeAsync(
GetLastDeployTimeRequest request,
CallOptions callOptions);
@@ -29,6 +31,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Discovers the object hierarchy in the Galaxy Repository.
/// The discover hierarchy request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// The discovered hierarchy reply.
Task DiscoverHierarchyAsync(
DiscoverHierarchyRequest request,
CallOptions callOptions);
@@ -36,6 +39,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Returns direct children of a parent in the Galaxy hierarchy.
/// The browse children request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// The browse children reply.
Task BrowseChildrenAsync(
BrowseChildrenRequest request,
CallOptions callOptions);
@@ -43,6 +47,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Watches for deployment events from the Galaxy Repository server.
/// The watch deploy events request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// An asynchronous stream of deploy events.
IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
index 777e13b..7b3aa33 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
@@ -12,7 +12,7 @@ public sealed class LazyBrowseNode
{
private readonly GalaxyRepositoryClient _client;
private readonly BrowseChildrenOptions _options;
- // Client.Dotnet-027 (Won't Fix): this gate is used only via WaitAsync/Release and
+ // Won't Fix: this gate is used only via WaitAsync/Release and
// never via AvailableWaitHandle, so SemaphoreSlim allocates no kernel wait handle —
// it holds no unmanaged/OS handle to leak. It is pure managed memory whose lifetime
// is the node's, so the type is intentionally not IDisposable: making it disposable
@@ -27,6 +27,11 @@ public sealed class LazyBrowseNode
private IReadOnlyList _children = [];
private volatile bool _isExpanded;
+ /// Initializes a new instance of the class.
+ /// The Galaxy Repository client used to fetch children on expansion.
+ /// The underlying Galaxy object for this node.
+ /// Whether the server reports this node has at least one matching descendant.
+ /// The browse options to apply when fetching children.
internal LazyBrowseNode(
GalaxyRepositoryClient client,
GalaxyObject @object,
@@ -66,6 +71,7 @@ public sealed class LazyBrowseNode
/// partially-built list.
///
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public async Task ExpandAsync(CancellationToken cancellationToken = default)
{
if (_isExpanded)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
index ef111df..5715904 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
@@ -7,6 +7,7 @@ public static class MxCommandReplyExtensions
{
/// Validates that the reply has a successful protocol status (Ok or MxAccessFailure), throwing a gateway exception if not.
/// The command reply to check.
+ /// The same reply, for chaining.
public static MxCommandReply EnsureProtocolSuccess(this MxCommandReply reply)
{
ArgumentNullException.ThrowIfNull(reply);
@@ -24,6 +25,7 @@ public static class MxCommandReplyExtensions
/// Validates that the reply indicates MXAccess success (no HResult or status failures), throwing MxAccessException if not.
/// The command reply to check.
+ /// The same reply, for chaining.
public static MxCommandReply EnsureMxAccessSuccess(this MxCommandReply reply)
{
ArgumentNullException.ThrowIfNull(reply);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
index 6d9ab58..ed321b3 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
@@ -249,6 +249,7 @@ public sealed class MxGatewayClient : IAsyncDisposable
///
/// Disposes the client and releases all resources.
///
+ /// A task that represents the asynchronous operation.
public ValueTask DisposeAsync()
{
if (_disposed)
@@ -318,6 +319,11 @@ public sealed class MxGatewayClient : IAsyncDisposable
private static HttpMessageHandler CreateHttpHandler(MxGatewayClientOptions options) =>
CreateHttpHandlerForTests(options);
+ ///
+ /// Creates the used for gRPC calls; exposed internally so tests can inspect it.
+ ///
+ /// The client options that configure connect timeout and TLS behavior.
+ /// A configured .
internal static SocketsHttpHandler CreateHttpHandlerForTests(MxGatewayClientOptions options)
{
SocketsHttpHandler handler = new()
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
index ff4ff7a..4d01bbb 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
@@ -12,6 +12,7 @@ internal static class MxGatewayClientRetryPolicy
/// Creates a Polly ResiliencePipeline that retries transient gRPC failures with exponential backoff.
/// Retry configuration (max attempts, delay bounds, jitter).
/// Optional logger for retry diagnostics.
+ /// A configured resilience pipeline that retries transient gRPC failures.
public static ResiliencePipeline Create(
MxGatewayClientRetryOptions options,
ILogger? logger)
@@ -42,6 +43,7 @@ internal static class MxGatewayClientRetryPolicy
/// Returns whether a command kind is eligible for automatic retry on transient failures.
/// The command kind to check.
+ /// if the command kind may be automatically retried; otherwise, .
public static bool IsRetryableCommand(MxCommandKind kind)
{
return kind is MxCommandKind.Ping
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
index e0c6f24..94671f8 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
@@ -211,6 +211,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task AdviseAsync(
int serverHandle,
int itemHandle,
@@ -252,6 +253,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task UnAdviseAsync(
int serverHandle,
int itemHandle,
@@ -293,6 +295,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task RemoveItemAsync(
int serverHandle,
int itemHandle,
@@ -675,6 +678,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The value to write.
/// User ID context for the write.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task WriteAsync(
int serverHandle,
int itemHandle,
@@ -704,6 +708,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// Map of zero-based array index to scalar .
/// User ID context for the write.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public Task WriteArrayElementsAsync(
int serverHandle,
int itemHandle,
@@ -786,6 +791,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The timestamp to write with the value.
/// User ID context for the write.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task Write2Async(
int serverHandle,
int itemHandle,
@@ -878,6 +884,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
///
/// Closes the session and releases resources.
///
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await CloseAsync().ConfigureAwait(false);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
index 5441431..318ad8a 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
@@ -7,6 +7,7 @@ public static class MxStatusProxyExtensions
{
/// Returns whether the status indicates success (success flag set and category is Ok).
/// The status to check.
+ /// if the status indicates success; otherwise .
public static bool IsSuccess(this MxStatusProxy status)
{
ArgumentNullException.ThrowIfNull(status);
@@ -17,6 +18,7 @@ public static class MxStatusProxyExtensions
/// Returns a formatted summary of the status for diagnostic output.
/// The status to summarize.
+ /// A formatted diagnostic summary string.
public static string ToDiagnosticSummary(this MxStatusProxy status)
{
ArgumentNullException.ThrowIfNull(status);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
index 4f047bf..25f3caa 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
@@ -14,6 +14,7 @@ public static class MxValueExtensions
/// Converts a boolean value to an MxValue with MxDataType.Boolean.
///
/// Scalar boolean value to wrap.
+ /// An carrying the wrapped boolean.
public static MxValue ToMxValue(this bool value)
{
return new MxValue
@@ -28,6 +29,7 @@ public static class MxValueExtensions
/// Converts a 32-bit integer value to an MxValue with MxDataType.Integer.
///
/// 32-bit integer value to wrap.
+ /// An carrying the wrapped integer.
public static MxValue ToMxValue(this int value)
{
return new MxValue
@@ -42,6 +44,7 @@ public static class MxValueExtensions
/// Converts a 64-bit integer value to an MxValue with MxDataType.Integer.
///
/// 64-bit integer value to wrap.
+ /// An carrying the wrapped integer.
public static MxValue ToMxValue(this long value)
{
return new MxValue
@@ -56,6 +59,7 @@ public static class MxValueExtensions
/// Converts a single-precision floating-point value to an MxValue with MxDataType.Float.
///
/// Single-precision floating-point value to wrap.
+ /// An carrying the wrapped value.
public static MxValue ToMxValue(this float value)
{
return new MxValue
@@ -70,6 +74,7 @@ public static class MxValueExtensions
/// Converts a double-precision floating-point value to an MxValue with MxDataType.Double.
///
/// Double-precision floating-point value to wrap.
+ /// An carrying the wrapped value.
public static MxValue ToMxValue(this double value)
{
return new MxValue
@@ -84,6 +89,7 @@ public static class MxValueExtensions
/// Converts a string value to an MxValue with MxDataType.String.
///
/// String value to wrap.
+ /// An carrying the wrapped string.
public static MxValue ToMxValue(this string value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -100,6 +106,7 @@ public static class MxValueExtensions
/// Converts a DateTimeOffset value to an MxValue with MxDataType.Time.
///
/// DateTimeOffset value to wrap.
+ /// An carrying the wrapped timestamp.
public static MxValue ToMxValue(this DateTimeOffset value)
{
return new MxValue
@@ -114,6 +121,7 @@ public static class MxValueExtensions
/// Converts a DateTime value to an MxValue with MxDataType.Time.
///
/// DateTime value to wrap.
+ /// An carrying the wrapped timestamp.
public static MxValue ToMxValue(this DateTime value)
{
return new DateTimeOffset(
@@ -127,6 +135,7 @@ public static class MxValueExtensions
/// Converts a boolean array to an MxValue with MxDataType.Boolean.
///
/// Array of boolean values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -145,6 +154,7 @@ public static class MxValueExtensions
/// Converts a 32-bit integer array to an MxValue with MxDataType.Integer.
///
/// Array of 32-bit integer values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -163,6 +173,7 @@ public static class MxValueExtensions
/// Converts a 64-bit integer array to an MxValue with MxDataType.Integer.
///
/// Array of 64-bit integer values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -181,6 +192,7 @@ public static class MxValueExtensions
/// Converts a single-precision floating-point array to an MxValue with MxDataType.Float.
///
/// Array of single-precision floating-point values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -199,6 +211,7 @@ public static class MxValueExtensions
/// Converts a double-precision floating-point array to an MxValue with MxDataType.Double.
///
/// Array of double-precision floating-point values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -217,6 +230,7 @@ public static class MxValueExtensions
/// Converts a string array to an MxValue with MxDataType.String.
///
/// Array of string values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -235,6 +249,7 @@ public static class MxValueExtensions
/// Converts a DateTimeOffset array to an MxValue with MxDataType.Time.
///
/// Array of DateTimeOffset values to wrap.
+ /// An carrying the wrapped array.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -253,6 +268,7 @@ public static class MxValueExtensions
/// Gets the projection kind (field name) of the given MxValue's current oneof value.
///
/// The MxValue whose oneof projection kind is returned.
+ /// The field name of the value's current oneof projection (e.g. "boolValue").
public static string GetProjectionKind(this MxValue value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -276,6 +292,7 @@ public static class MxValueExtensions
/// Converts an MxValue to a CLR object; returns the boxed value or null for null MxValues.
///
/// The MxValue to convert.
+ /// The boxed CLR value, or if the MxValue is null.
public static object? ToClrValue(this MxValue value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -299,6 +316,7 @@ public static class MxValueExtensions
/// Converts an MxArray to a CLR array; returns null if the array does not have a known element type.
///
/// The MxArray to convert.
+ /// The CLR array, or if the element type is not known.
public static object? ToClrArrayValue(this MxArray array)
{
ArgumentNullException.ThrowIfNull(array);
@@ -328,6 +346,7 @@ public static class MxValueExtensions
/// Variant type string (e.g., "VT_BSTR").
/// Diagnostic string describing the raw value.
/// Optional MXAccess data type override.
+ /// An with MxDataType.Unknown carrying the raw payload.
public static MxValue ToRawMxValue(
byte[] value,
string variantType,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
index 1cd41b1..05714ea 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
@@ -228,7 +228,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
// Consume mapped MxEvents through the session's single distributor pump (as an
// internal, non-counted subscriber) rather than opening a second raw drain of the
// worker event channel — a second drain would split events with the dashboard
- // mirror pump and silently lose Acknowledge/mode-change transitions (GWC-01).
+ // mirror pump and silently lose Acknowledge/mode-change transitions.
await foreach (MxEvent mxEvent in _sessionManager
.ReadAlarmEventsAsync(session.SessionId, linked.Token)
.ConfigureAwait(false))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigurationServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigurationServiceCollectionExtensions.cs
index 863db3b..d2762ae 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigurationServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigurationServiceCollectionExtensions.cs
@@ -15,8 +15,8 @@ public static class GatewayConfigurationServiceCollectionExtensions
public static IServiceCollection AddGatewayConfiguration(
this IServiceCollection services, IConfiguration configuration)
{
- // GatewayOptionsValidator depends on IHostEnvironment to gate the production-only rules
- // (SEC-04/06). The real host and the apikey CLI both build through WebApplicationBuilder,
+ // GatewayOptionsValidator depends on IHostEnvironment to gate the production-only rules.
+ // The real host and the apikey CLI both build through WebApplicationBuilder,
// which registers IHostEnvironment before this call — so TryAdd is a no-op there. Minimal
// containers (unit tests, tooling) have none; fall back to a non-production environment so
// the validator still activates and the production guards stay off outside a real
@@ -37,12 +37,16 @@ public static class GatewayConfigurationServiceCollectionExtensions
///
private sealed class FallbackHostEnvironment : IHostEnvironment
{
+ /// Gets or sets the name of the environment; defaults to .
public string EnvironmentName { get; set; } = Environments.Development;
+ /// Gets or sets the name of the application.
public string ApplicationName { get; set; } = typeof(FallbackHostEnvironment).Assembly.GetName().Name ?? "MxGateway";
+ /// Gets or sets the absolute path to the content root directory.
public string ContentRootPath { get; set; } = AppContext.BaseDirectory;
+ /// Gets or sets the file provider for the content root.
public IFileProvider ContentRootFileProvider { get; set; } = new NullFileProvider();
}
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
index d271063..dcd60ba 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
@@ -470,7 +470,7 @@ public sealed class GatewayOptionsValidator : OptionsValidatorBase
/// Security hot-path options bound from MxGateway:Security. Groups the API-key verification
-/// cache and last_used write-coalescing knobs (SEC-08) with the login and API-key
-/// rate-limiting knobs (SEC-11). Defaults preserve safe, low-overhead behaviour without requiring
+/// cache and last_used write-coalescing knobs with the login and API-key
+/// rate-limiting knobs. Defaults preserve safe, low-overhead behaviour without requiring
/// operators to configure anything.
///
public sealed class SecurityOptions
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
index baf68ea..4a2b862 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
@@ -37,8 +37,8 @@ public sealed class WorkerOptions
/// The maximum worker-frame (pipe) message size in bytes. Must stay at least
/// above
/// so a maximally-sized accepted gRPC payload
- /// still fits one worker frame (IPC-03); the gateway conveys this value to the worker in the
- /// handshake (GatewayHello.max_frame_bytes, IPC-02). Default is the 16 MB public gRPC cap
+ /// still fits one worker frame; the gateway conveys this value to the worker in the
+ /// handshake (GatewayHello.max_frame_bytes). Default is the 16 MB public gRPC cap
/// plus that reserve.
///
public int MaxMessageBytes { get; init; } =
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
index 6215e83..3dd3447 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
@@ -101,8 +101,6 @@ public sealed class DashboardApiKeyManagementService(
.RevokeKeyAsync(normalizedKeyId, RemoteAddress(), cancellationToken)
.ConfigureAwait(false);
- // SEC-08: drop any cached verification for this key in THIS gateway process so the revoke
- // takes effect immediately rather than after the verification-cache TTL elapses.
cacheInvalidator?.Invalidate(normalizedKeyId);
await WriteDashboardAuditAsync(
@@ -143,8 +141,6 @@ public sealed class DashboardApiKeyManagementService(
.RotateKeyAsync(normalizedKeyId, RemoteAddress(), cancellationToken)
.ConfigureAwait(false);
- // SEC-08: the old secret's cached verification must not outlive the rotate — evict it so
- // the superseded secret stops authenticating within this process immediately.
cacheInvalidator?.Invalidate(normalizedKeyId);
bool succeeded = rotated.Token is not null;
@@ -191,8 +187,6 @@ public sealed class DashboardApiKeyManagementService(
.DeleteAsync(normalizedKeyId, cancellationToken)
.ConfigureAwait(false);
- // SEC-08: a deleted key is only reachable after a prior revoke, but evict defensively so no
- // cached verification survives the delete.
cacheInvalidator?.Invalidate(normalizedKeyId);
await WriteDashboardAuditAsync(
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
index dea4e5f..ee9f91c 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
@@ -12,7 +12,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
public static class DashboardEndpointRouteBuilderExtensions
{
///
- /// The named rate-limiter policy applied to the POST /auth/login route (SEC-11). Registered
+ /// The named rate-limiter policy applied to the POST /auth/login route. Registered
/// in GatewayApplication via .
///
internal const string LoginRateLimiterPolicy = "dashboard-login";
@@ -40,8 +40,12 @@ public static class DashboardEndpointRouteBuilderExtensions
});
}
- // Test seam: a standalone partitioned limiter over the production partition logic, so a test can
- // acquire leases and assert the (permit+1)th is rejected without an HTTP server.
+ ///
+ /// Test seam: builds a standalone partitioned limiter over the production partition logic, so a
+ /// test can acquire leases and assert the (permit+1)th is rejected without an HTTP server.
+ ///
+ /// The bound security options carrying the login-limit knobs.
+ /// A partitioned rate limiter keyed the same way as the production login policy.
internal static PartitionedRateLimiter CreateLoginRateLimiter(SecurityOptions security)
=> PartitionedRateLimiter.Create(
ctx => GetLoginRateLimitPartition(ctx, security));
@@ -76,7 +80,6 @@ public static class DashboardEndpointRouteBuilderExtensions
(HttpContext httpContext, IAntiforgery antiforgery, IDashboardAuthenticator authenticator) =>
PostLoginAsync(httpContext, antiforgery, authenticator))
.AllowAnonymous()
- // SEC-11: throttle credential stuffing before the LDAP bind is relayed to the directory.
.RequireRateLimiting(LoginRateLimiterPolicy)
.WithName("DashboardLoginPost");
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
index 168f818..bcc5842 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
@@ -33,7 +33,7 @@ public sealed class HubTokenService
// bounds how long a stale role set survives a role change. Five minutes is transparent to
// clients because DashboardHubConnectionFactory mints a fresh token on every (re)connect;
// see docs/GatewayDashboardDesign.md. Heavier jti-denylist revocation is deliberately
- // deferred until per-session hub ACLs land (SEC-25), when tokens gain session binding.
+ // deferred until per-session hub ACLs land, when tokens gain session binding.
internal static readonly TimeSpan TokenLifetime = TimeSpan.FromMinutes(5);
private readonly ITimeLimitedDataProtector _protector;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs b/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
index 131ef19..ea38dec 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
@@ -41,7 +41,7 @@ public static class GatewayApplication
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
- // SEC-11: the rate limiter must run after routing has selected the endpoint (so its
+ // The rate limiter must run after routing has selected the endpoint (so its
// RequireRateLimiting policy metadata is visible) and before the endpoint executes.
app.UseRateLimiter();
app.UseAntiforgery();
@@ -105,7 +105,7 @@ public static class GatewayApplication
return builder;
}
- // SEC-11: register the named fixed-window rate-limiter policy applied to POST /auth/login. The
+ // Registers the named fixed-window rate-limiter policy applied to POST /auth/login. The
// limit knobs are read from MxGateway:Security at startup; the per-request partition is keyed on
// the remote IP (see DashboardEndpointRouteBuilderExtensions.GetLoginRateLimitPartition).
private static void AddLoginRateLimiter(WebApplicationBuilder builder)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
index 5afce48..9e0b284 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
@@ -14,43 +14,33 @@ public sealed class EventStreamService(
GatewayMetrics metrics) : IEventStreamService
{
///
- ///
- ///
- /// This reads the subscriber's lease channel fed by the session's single
- /// pump. The pump owns the single drain of
- /// the worker event stream and the worker→public mapping (mirroring the former
- /// ProduceEventsAsync); this loop is the per-subscriber boundary that
- /// applies the per-RPC filter (AfterWorkerSequence), queue-depth metrics,
- /// and the backpressure/overflow policy.
- ///
- ///
- /// The dashboard mirror runs OFF this per-RPC loop. The dashboard is a
- /// first-class internal subscriber on the session's
- /// (see GatewaySession.StartDashboardMirror),
- /// so it receives session events even when no gRPC client is streaming. This loop
- /// does not mirror to the dashboard. One deliberate consequence: the dashboard sees
- /// RAW session events, not the per-gRPC-subscriber AfterWorkerSequence-filtered
- /// view this loop applies — the dashboard is a separate LDAP-authenticated monitoring
- /// view that should see the session's full event activity.
- ///
- ///
- /// Overflow handling: the distributor's per-subscriber channel is bounded
- /// and the pump writes non-blocking. When this subscriber's channel is full the pump
- /// applies the per-subscriber backpressure policy and completes this subscriber's
- /// channel with a
- /// (). That terminal fault
- /// surfaces here when the reader's MoveNextAsync throws, and it propagates to
- /// the gRPC client unchanged. The overflow metric, and (in the legacy
- /// single-subscriber FailFast case) the session fault + fault metric, are recorded by
- /// the distributor's overflow handler so the session, the pump, and other subscribers
- /// are isolated from this subscriber's slowness.
- ///
- ///
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
string? callerKeyId,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
+ // This reads the subscriber's lease channel fed by the session's single
+ // SessionEventDistributor pump. The pump owns the single drain of the worker event
+ // stream and the worker->public mapping (mirroring the former ProduceEventsAsync); this
+ // loop is the per-subscriber boundary that applies the per-RPC filter (AfterWorkerSequence),
+ // queue-depth metrics, and the backpressure/overflow policy.
+ //
+ // The dashboard mirror runs OFF this per-RPC loop. The dashboard is a first-class internal
+ // subscriber on the session's SessionEventDistributor (see GatewaySession.StartDashboardMirror),
+ // so it receives session events even when no gRPC client is streaming. This loop does not
+ // mirror to the dashboard. One deliberate consequence: the dashboard sees RAW session events,
+ // not the per-gRPC-subscriber AfterWorkerSequence-filtered view this loop applies — the
+ // dashboard is a separate LDAP-authenticated monitoring view that should see the session's
+ // full event activity.
+ //
+ // Overflow handling: the distributor's per-subscriber channel is bounded and the pump writes
+ // non-blocking. When this subscriber's channel is full the pump applies the per-subscriber
+ // backpressure policy and completes this subscriber's channel with a SessionManagerException
+ // (SessionManagerErrorCode.EventQueueOverflow). That terminal fault surfaces here when the
+ // reader's MoveNextAsync throws, and it propagates to the gRPC client unchanged. The overflow
+ // metric, and (in the legacy single-subscriber FailFast case) the session fault + fault metric,
+ // are recorded by the distributor's overflow handler so the session, the pump, and other
+ // subscribers are isolated from this subscriber's slowness.
if (!sessionManager.TryGetSession(request.SessionId, out GatewaySession? session) || session is null)
{
throw new SessionManagerException(
@@ -58,7 +48,7 @@ public sealed class EventStreamService(
$"Session {request.SessionId} was not found.");
}
- // Owner-scoped attach (TST-02, security control): a session's event stream may be
+ // Owner-scoped attach (security control): a session's event stream may be
// attached or reattached ONLY by the API key that opened the session. The detach-grace
// and fan-out retention windows are on by default, so without this check any event-scoped
// key that learns a session id could attach to another key's retained session and receive
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcRequestValidator.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcRequestValidator.cs
index c6bc0e6..5a53786 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcRequestValidator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcRequestValidator.cs
@@ -7,7 +7,7 @@ public sealed class MxAccessGrpcRequestValidator
{
// Upper bound on a single DrainEvents request. DrainEvents is a diagnostics RPC that returns
// buffered events in one non-streaming reply, so an unbounded max_events could pack the whole
- // queue into a session-killing frame (IPC-04). The worker independently caps each reply at its
+ // queue into a session-killing frame. The worker independently caps each reply at its
// own MaxDrainEventsPerReply; this public bound rejects an obviously-abusive request loudly at
// the boundary. max_events = 0 is allowed and means "the worker's default batch cap".
private const uint MaxDrainEventsPerRequest = 10_000;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCommandLineParser.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCommandLineParser.cs
index 6ec44da..041094f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCommandLineParser.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCommandLineParser.cs
@@ -236,7 +236,7 @@ public static class ApiKeyAdminCommandLineParser
ReadHistorizedOnly: HasFlag(options, "read-historized-only"));
}
- // Parses the optional --expires value into an absolute UTC expiry (SEC-10). Accepts a relative
+ // Parses the optional --expires value into an absolute UTC expiry. Accepts a relative
// "d"/"h" duration from now (operator-friendly) or an absolute ISO-8601 instant/date
// (assumed UTC). Null/blank means no expiry — expiry stays opt-in, preserving prior behaviour.
private static DateTimeOffset? ParseExpiry(string? value)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/AuthStoreServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/AuthStoreServiceCollectionExtensions.cs
index 5b3bc65..5c3d40a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/AuthStoreServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/AuthStoreServiceCollectionExtensions.cs
@@ -69,7 +69,7 @@ public static class AuthStoreServiceCollectionExtensions
// migrator and the migration hosted service.
services.AddZbApiKeyAuth(effectiveConfig, AuthenticationSectionPath);
- // SEC-08 hot-path decorators. Every gRPC call previously did a SQLite read plus a
+ // Hot-path decorators. Every gRPC call previously did a SQLite read plus a
// last_used_utc WRITE via IApiKeyVerifier.VerifyAsync (the library verifier couples the
// mark into verification). Two gateway-side decorators cut that cost without editing the
// external library:
@@ -138,7 +138,7 @@ public static class AuthStoreServiceCollectionExtensions
///
/// Replaces the last registration of with a singleton that wraps
/// it. The wrapped (inner) service is created once, preserving singleton semantics. Used to layer
- /// the SEC-08 store decorator over the external library's registration without editing it.
+ /// the store decorator over the external library's registration without editing it.
///
private static void DecorateSingleton(
IServiceCollection services,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs
index fe3ae52..ea8e446 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs
@@ -30,7 +30,7 @@ public interface IApiKeyCacheInvalidator
///
/// Only successful verifications are cached. Failures and unparseable headers always fall through
/// to the inner verifier — caching a failure risks pinning a transiently-wrong negative, and the
-/// SEC-11 per-peer failure counter (not this cache) is what bounds brute-force cost.
+/// per-peer failure counter (not this cache) is what bounds brute-force cost.
///
///
/// The cache key is the hex SHA-256 of the presented token (which embeds both the key id and the
@@ -71,7 +71,11 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
{
}
- // Test/explicit-TTL seam.
+ /// Initializes a new instance of the class with an explicit TTL.
+ /// The wrapped verifier (the library verifier) reached on a cache miss.
+ /// The shared memory cache.
+ /// The verification-cache TTL; a zero or negative value disables caching.
+ /// Test/explicit-TTL seam.
internal CachingApiKeyVerifier(IApiKeyVerifier inner, IMemoryCache cache, TimeSpan ttl)
{
ArgumentNullException.ThrowIfNull(inner);
@@ -81,7 +85,14 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
_ttl = ttl;
}
- ///
+ ///
+ /// Verifies the given authorization header, returning a cached successful result when one is
+ /// still within TTL, or falling through to the inner verifier on a cache miss or non-cacheable
+ /// header.
+ ///
+ /// The raw Authorization header value to verify.
+ /// Token to cancel the asynchronous operation.
+ /// The verification result, cached or freshly computed.
public async Task VerifyAsync(string authorizationHeader, CancellationToken ct)
{
if (_ttl <= TimeSpan.Zero || !TryComputeCacheKey(authorizationHeader, out string cacheKey))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CoalescingMarkApiKeyStore.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CoalescingMarkApiKeyStore.cs
index 9270530..cd5e1a3 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CoalescingMarkApiKeyStore.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CoalescingMarkApiKeyStore.cs
@@ -41,7 +41,10 @@ public sealed class CoalescingMarkApiKeyStore : IApiKeyStore
{
}
- // Test/explicit-window seam.
+ /// Initializes a new instance of the class with an explicit coalescing window (test/explicit-window seam).
+ /// The wrapped store.
+ /// The coalescing window; marks within this window of the last forwarded mark for a key are dropped.
+ /// The time provider.
internal CoalescingMarkApiKeyStore(IApiKeyStore inner, TimeSpan window, TimeProvider clock)
{
ArgumentNullException.ThrowIfNull(inner);
@@ -51,15 +54,25 @@ public sealed class CoalescingMarkApiKeyStore : IApiKeyStore
_clock = clock;
}
- ///
+ /// Looks up an API key record by key id, delegating to the wrapped store unchanged.
+ /// The API key id to look up.
+ /// The cancellation token.
+ /// The matching , or if none exists.
public Task FindByKeyIdAsync(string keyId, CancellationToken ct)
=> _inner.FindByKeyIdAsync(keyId, ct);
- ///
+ /// Looks up an active API key record by key id, delegating to the wrapped store unchanged.
+ /// The API key id to look up.
+ /// The cancellation token.
+ /// The matching active , or if none exists or is inactive.
public Task FindActiveByKeyIdAsync(string keyId, CancellationToken ct)
=> _inner.FindActiveByKeyIdAsync(keyId, ct);
- ///
+ /// Marks the key as used, coalescing writes so at most one reaches the wrapped store per key per window.
+ /// The API key id being marked as used.
+ /// The UTC timestamp of the use.
+ /// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task MarkUsedAsync(string keyId, DateTimeOffset whenUtc, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(keyId);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/GatewayApiKeyIdentityMapper.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/GatewayApiKeyIdentityMapper.cs
index f507a79..75d9591 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/GatewayApiKeyIdentityMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/GatewayApiKeyIdentityMapper.cs
@@ -19,11 +19,6 @@ namespace ZB.MOM.WW.MxGateway.Server.Security.Authentication;
///
public static class GatewayApiKeyIdentityMapper
{
- // SEC-08: memoize the constraints deserialization keyed by the raw JSON blob so the per-call
- // JSON parse on the auth hot path collapses to a dictionary lookup. Distinct blobs are bounded
- // by the number of API keys (small); ApiKeyConstraints is an immutable record, so a parsed
- // instance is safe to share across callers. The cap is a defensive backstop against a pathological
- // spread of distinct blobs — past it, we simply parse without caching rather than grow unbounded.
private const int MaxCachedConstraintBlobs = 1024;
private static readonly ConcurrentDictionary ConstraintCache =
new(StringComparer.Ordinal);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs
index 730e4c4..c5baea1 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs
@@ -4,7 +4,7 @@ using ZB.MOM.WW.MxGateway.Server.Configuration;
namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;
///
-/// Cheap, in-process per-peer sliding-window failure counter for the gRPC auth path (SEC-11). It is
+/// Cheap, in-process per-peer sliding-window failure counter for the gRPC auth path. It is
/// checked BEFORE the API-key verification store read and short-circuits a peer that has exceeded
/// failed attempts within
/// ; a successful verification resets the
@@ -45,7 +45,11 @@ public sealed class ApiKeyFailureLimiter
{
}
- // Test/explicit seam.
+ /// Initializes a new instance of the class. Test/explicit seam.
+ /// The maximum number of failures allowed within .
+ /// The sliding window over which failures are counted.
+ /// The maximum number of tracked peers before least-recently-active eviction kicks in.
+ /// The time provider.
internal ApiKeyFailureLimiter(int limit, TimeSpan window, int maxPeers, TimeProvider clock)
{
ArgumentNullException.ThrowIfNull(clock);
@@ -145,6 +149,7 @@ public sealed class ApiKeyFailureLimiter
private sealed class PeerState
{
+ /// Timestamps (in ticks) of failures still within the sliding window.
public Queue FailureTicks { get; } = new();
public long LastActivityTicks;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs
index 0a187ef..b88fd3a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs
@@ -64,7 +64,7 @@ public sealed class GatewayGrpcAuthorizationInterceptor(
string? authorizationHeader = context.RequestHeaders.GetValue("authorization");
- // SEC-11: short-circuit a peer that has already failed too many times inside the sliding
+ // Short-circuit a peer that has already failed too many times inside the sliding
// window BEFORE the verification store read, so online guessing cannot spend a SQLite read
// per attempt. The peer key prefers the presented key id over the transport address (NAT
// caveat). ResourceExhausted signals throttling without revealing whether any particular
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
index ae697f3..62e4d9a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
@@ -19,7 +19,7 @@ public static class GrpcAuthorizationServiceCollectionExtensions
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
- // SEC-11 per-peer failure counter, checked before the verification store read. Bind the knobs
+ // Per-peer failure counter, checked before the verification store read. Bind the knobs
// from IConfiguration directly (not IOptions) to avoid coupling this
// registration to the whole-options validation pipeline.
services.AddSingleton(sp => new ApiKeyFailureLimiter(
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
index 43ee931..428d99f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
@@ -222,11 +222,6 @@ public sealed class SessionManager : ISessionManager
}
///
- ///
- /// Mirrors the registry/metrics cleanup that
- /// performs after a successful close, but skips the WorkerClient.ShutdownAsync
- /// step that would otherwise attempt.
- ///
public async Task KillWorkerAsync(
string sessionId,
string reason,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
index 342ae6d..bc65c8a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
@@ -27,7 +27,7 @@ public sealed class WorkerClient : IWorkerClient
// Staging hand-off between the read loop and the dedicated event writer. The read loop writes
// here with a non-blocking TryWrite so a full consumer channel (_events) can never stall the read
- // loop behind an event — replies and heartbeats keep flowing (GWC-04). Unbounded, but only fills
+ // loop behind an event — replies and heartbeats keep flowing. Unbounded, but only fills
// during the bounded EventChannelFullModeTimeout window before EventWriteLoopAsync faults on a
// sustained backlog, after which the read loop stops.
private readonly Channel _eventStaging;
@@ -208,7 +208,7 @@ public sealed class WorkerClient : IWorkerClient
// Reject an oversized command at the enqueue boundary so only this correlation fails
// (ResourceExhausted) rather than the frame reaching the write loop and faulting the whole
- // session (IPC-03). Command envelopes are the only gateway-authored outbound payload whose
+ // session. Command envelopes are the only gateway-authored outbound payload whose
// size the caller controls; checking here keeps a MessageTooLarge in the write loop a
// genuine desync signal.
int envelopeSize = commandEnvelope.CalculateSize();
@@ -269,7 +269,7 @@ public sealed class WorkerClient : IWorkerClient
// The event channel is SingleReader: only one enumerator may ever drain it, otherwise
// the two readers would each receive a random subset of events. Claim the reader at CALL
// time (not lazily on first MoveNext) and fail loudly on a second consumer rather than
- // silently splitting the stream (see GWC-01). The distributor pump is the only intended
+ // silently splitting the stream. The distributor pump is the only intended
// caller; the alarm monitor and dashboard mirror attach to the distributor instead.
if (Interlocked.CompareExchange(ref _eventsReaderClaimed, 1, 0) != 0)
{
@@ -519,7 +519,7 @@ public sealed class WorkerClient : IWorkerClient
/// Routes a received envelope to its handler. Every branch dispatches synchronously and
/// immediately — the event branch only stages the event for the dedicated writer — so a full
/// event channel can never delay a command reply, heartbeat, fault, or shutdown ack behind an
- /// event backlog (GWC-04).
+ /// event backlog.
///
/// The envelope to dispatch.
private void DispatchEnvelope(WorkerEnvelope envelope)
@@ -559,7 +559,7 @@ public sealed class WorkerClient : IWorkerClient
/// succeeds unless the channel has been completed during shutdown — in which case the event is
/// safely dropped because the client is closing. Backpressure and the sustained-overflow fault
/// are applied by against the bounded consumer channel,
- /// off the read loop (GWC-04).
+ /// off the read loop.
///
/// The event received from the worker.
private void StageWorkerEvent(WorkerEvent workerEvent)
@@ -575,7 +575,7 @@ public sealed class WorkerClient : IWorkerClient
///
/// Drains staged worker events and applies the bounded-channel backpressure (and
/// sustained-overflow fault) on a dedicated task, so the timed write
- /// never runs on the read loop (GWC-04). Mirrors for events.
+ /// never runs on the read loop. Mirrors for events.
///
private async Task EventWriteLoopAsync()
{
@@ -984,7 +984,7 @@ public sealed class WorkerClient : IWorkerClient
GatewayVersion = typeof(GatewayContractInfo).Assembly.GetName().Version?.ToString() ?? GatewayVersionFallback,
// Convey the negotiated worker-frame maximum so the worker adopts it instead of a
- // hard-coded default (IPC-02). Sits above the public gRPC cap by the envelope reserve.
+ // hard-coded default. Sits above the public gRPC cap by the envelope reserve.
MaxFrameBytes = (uint)_connection.FrameOptions.MaxMessageBytes,
});
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClientErrorCode.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClientErrorCode.cs
index 8f32111..b16c58d 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClientErrorCode.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClientErrorCode.cs
@@ -15,6 +15,6 @@ public enum WorkerClientErrorCode
// The serialized command envelope exceeds the negotiated worker-frame maximum. Rejected at the
// enqueue boundary so only the offending command fails (mapped to ResourceExhausted) instead of
- // the oversized frame reaching the write loop and faulting the whole session (IPC-03).
+ // the oversized frame reaching the write loop and faulting the whole session.
CommandTooLarge,
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameProtocolOptions.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameProtocolOptions.cs
index 1b664d2..7ef2712 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameProtocolOptions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameProtocolOptions.cs
@@ -15,7 +15,7 @@ public sealed class WorkerFrameProtocolOptions
/// gRPC payload accepted at the public boundary always fits inside one worker frame once wrapped
/// in a WorkerEnvelope (correlation id, timestamps, oneof framing). Without this headroom
/// the pipe max equals the gRPC max and a maximally-sized accepted request faults the whole
- /// session on the outbound write (IPC-03). 64 KiB is far larger than the fixed envelope overhead.
+ /// session on the outbound write. 64 KiB is far larger than the fixed envelope overhead.
///
public const int EnvelopeOverheadReserveBytes = 64 * 1024;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
index 5a114af..94bf920 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
@@ -14,7 +14,7 @@ public sealed class GatewayOptionsTests
GatewayOptions options = BindOptions(new Dictionary());
Assert.Equal(AuthenticationMode.ApiKey, options.Authentication.Mode);
- // SEC-01: the default is derived from CommonApplicationData (C:\ProgramData on Windows,
+ // The default is derived from CommonApplicationData (C:\ProgramData on Windows,
// /usr/share on Unix) rather than a Windows literal, so assert against the same derivation
// to stay platform-correct.
Assert.Equal(
@@ -35,7 +35,7 @@ public sealed class GatewayOptionsTests
Assert.Equal(10, options.Worker.ShutdownTimeoutSeconds);
Assert.Equal(5, options.Worker.HeartbeatIntervalSeconds);
Assert.Equal(15, options.Worker.HeartbeatGraceSeconds);
- // 16 MiB public gRPC cap plus the 64 KiB worker-frame envelope reserve (IPC-03 headroom).
+ // 16 MiB public gRPC cap plus the 64 KiB worker-frame envelope reserve for headroom.
Assert.Equal((16 * 1024 * 1024) + (64 * 1024), options.Worker.MaxMessageBytes);
Assert.Equal(30, options.Sessions.DefaultCommandTimeoutSeconds);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
index 65c60f1..57c60bb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
@@ -550,10 +550,6 @@ public sealed class GatewayOptionsValidatorTests
Assert.True(result.Succeeded);
}
- // -------------------------------------------------------------------------
- // SEC-01: security-sensitive paths must be rooted (absolute)
- // -------------------------------------------------------------------------
-
private static GatewayOptions CloneWithAuthentication(GatewayOptions source, AuthenticationOptions authentication)
=> new()
{
@@ -606,10 +602,6 @@ public sealed class GatewayOptionsValidatorTests
f => f.Contains("MxGateway:Tls:SelfSignedCertPath") && f.Contains("rooted"));
}
- // -------------------------------------------------------------------------
- // SEC-04: DisableLogin production guard
- // -------------------------------------------------------------------------
-
private static GatewayOptions CloneWithDashboard(GatewayOptions source, DashboardOptions dashboard)
=> new()
{
@@ -649,10 +641,6 @@ public sealed class GatewayOptionsValidatorTests
Assert.True(result.Succeeded);
}
- // -------------------------------------------------------------------------
- // SEC-06: LDAP plaintext transport production guard
- // -------------------------------------------------------------------------
-
/// Verifies plaintext LDAP transport (None) aborts startup in Production.
[Fact]
public void Validate_Fails_WhenLdapTransportNoneInProduction()
@@ -684,8 +672,6 @@ public sealed class GatewayOptionsValidatorTests
Assert.True(result.Succeeded);
}
- // ---- SEC-11: MxGateway:Security validation ----
-
private static GatewayOptions WithSecurity(SecurityOptions security) => new() { Security = security };
/// Verifies the default security options pass validation.
@@ -791,7 +777,7 @@ public sealed class GatewayOptionsValidatorTests
///
/// Verifies the default worker-frame maximum keeps the required envelope-overhead reserve above
- /// the default public gRPC cap, so a stock configuration passes the IPC-03 headroom check.
+ /// the default public gRPC cap, so a stock configuration passes the headroom check.
///
[Fact]
public void Validate_Succeeds_WhenWorkerFrameMaxHasEnvelopeHeadroom()
@@ -803,7 +789,7 @@ public sealed class GatewayOptionsValidatorTests
///
/// Verifies that a worker-frame maximum equal to the gRPC cap (zero headroom) fails validation:
/// a maximally-sized accepted gRPC payload would not fit one worker frame once wrapped in a
- /// WorkerEnvelope, faulting the whole session on the outbound write (IPC-03).
+ /// WorkerEnvelope, faulting the whole session on the outbound write.
///
[Fact]
public void Validate_Fails_WhenWorkerFrameMaxEqualsGrpcMaxWithoutHeadroom()
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Contracts/ClientProtoInputTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Contracts/ClientProtoInputTests.cs
index 981b54f..b047347 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Contracts/ClientProtoInputTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Contracts/ClientProtoInputTests.cs
@@ -9,7 +9,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Contracts;
public sealed class ClientProtoInputTests
{
///
- /// Guards the published client descriptor set against silent staleness (IPC-01). Every message
+ /// Guards the published client descriptor set against silent staleness. Every message
/// and field compiled into the in-process contract (which the build regenerates from the current
/// .proto sources) must appear in the committed protoset. A missing symbol means the
/// descriptor was not regenerated after a proto change; run
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLoginRateLimitTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLoginRateLimitTests.cs
index 523496a..48a4480 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLoginRateLimitTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLoginRateLimitTests.cs
@@ -7,7 +7,7 @@ using ZB.MOM.WW.MxGateway.Server.Dashboard;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
-/// SEC-11: the POST /auth/login fixed-window per-IP rate limiter. Exercised through the same
+/// Tests the POST /auth/login fixed-window per-IP rate limiter. Exercised through the same
/// partition factory the production policy registers, so the test pins the real permit limit and
/// per-IP partitioning without standing up an HTTP server.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
index f254ba1..611447b 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
@@ -203,7 +203,7 @@ public sealed class DashboardSessionAdminServiceTests
///
/// Verifies that a successful close writes a canonical dashboard-close-session
/// — actor, session-id target, and Success outcome — to the
- /// audit store, not only the operational log (SEC-12).
+ /// audit store, not only the operational log.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -229,7 +229,7 @@ public sealed class DashboardSessionAdminServiceTests
///
/// Verifies that a successful kill writes a canonical dashboard-kill-worker
- /// to the audit store (SEC-12).
+ /// to the audit store.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -253,7 +253,7 @@ public sealed class DashboardSessionAdminServiceTests
///
/// Verifies that an unauthorized (viewer) close attempt still writes a Denied
- /// audit row, so rejected destructive attempts are durably recorded (SEC-12).
+ /// audit row, so rejected destructive attempts are durably recorded.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -305,7 +305,10 @@ public sealed class DashboardSessionAdminServiceTests
/// Gets the audit events written through this writer, in order.
public IReadOnlyList Events => _events.ToArray();
- ///
+ /// Records the given audit event for later inspection by the test.
+ /// The audit event to record.
+ /// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public Task WriteAsync(AuditEvent evt, CancellationToken ct = default)
{
_events.Enqueue(evt);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs
index 4d726fc..502cd9d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs
@@ -145,7 +145,7 @@ public sealed class HubTokenServiceTests
}
///
- /// The default token lifetime is the short (5-minute) window mandated by SEC-05, not the
+ /// The default token lifetime is the short (5-minute) window, not the
/// former 30-minute window. Pins the value so a regression that widens the exposure window
/// of an irrevocable, query-string-carried token is caught in CI.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
index e4f7664..4943e8d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
@@ -39,7 +39,7 @@ public sealed class EventStreamServiceTests
}
///
- /// TST-02 (owner-scoped attach): the API key that opened a session may attach its event
+ /// Owner-scoped attach: the API key that opened a session may attach its event
/// stream — the caller key equals the session owner, so streaming proceeds normally.
///
/// A task that represents the asynchronous operation.
@@ -64,7 +64,7 @@ public sealed class EventStreamServiceTests
}
///
- /// TST-02 (owner-scoped attach, security control): a caller whose API key differs from
+ /// Owner-scoped attach, security control: a caller whose API key differs from
/// the key that opened the session is rejected with a
/// fault before any events are streamed — closing the reconnect/fan-out trust-boundary hole.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcRequestValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcRequestValidatorTests.cs
index 52f9908..0bc8df1 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcRequestValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcRequestValidatorTests.cs
@@ -18,8 +18,9 @@ public sealed class MxAccessGrpcRequestValidatorTests
///
/// Verifies a DrainEvents request within the per-request ceiling passes validation, including the
- /// max_events = 0 "worker default cap" sentinel (IPC-04).
+ /// max_events = 0 "worker default cap" sentinel.
///
+ /// The requested drain-events ceiling to validate.
[Theory]
[InlineData(0u)]
[InlineData(1u)]
@@ -32,7 +33,7 @@ public sealed class MxAccessGrpcRequestValidatorTests
///
/// Verifies a DrainEvents request above the per-request ceiling is rejected with InvalidArgument
- /// so one accepted request cannot pack an unbounded reply frame (IPC-04).
+ /// so one accepted request cannot pack an unbounded reply frame.
///
[Fact]
public void ValidateInvoke_RejectsDrainEvents_AboveCeiling()
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionDashboardMirrorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionDashboardMirrorTests.cs
index b2df718..3b12acf 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionDashboardMirrorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionDashboardMirrorTests.cs
@@ -108,7 +108,7 @@ public sealed class GatewaySessionDashboardMirrorTests
}
///
- /// GWC-01 regression: with the internal dashboard mirror active, a second internal
+ /// With the internal dashboard mirror active, a second internal
/// subscriber (the alarm monitor's feed, attached via
/// ) receives EVERY event —
/// including the alarm Acknowledge transition — rather than the two consumers
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
index 8300759..c4b112e 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
@@ -59,7 +59,7 @@ public sealed class WorkerClientTests
///
/// Verifies that a command whose serialized envelope exceeds the negotiated worker-frame maximum
/// fails only that command with at the enqueue
- /// boundary, leaving the client ready for subsequent commands (IPC-03). Without the pre-check the
+ /// boundary, leaving the client ready for subsequent commands. Without the pre-check the
/// oversized frame would reach the write loop and fault the whole session.
///
/// A task that represents the asynchronous operation.
@@ -170,7 +170,7 @@ public sealed class WorkerClientTests
///
/// The worker event channel is single-reader: a second
- /// enumerator must throw rather than silently split events between two consumers (GWC-01).
+ /// enumerator must throw rather than silently split events between two consumers.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -221,7 +221,7 @@ public sealed class WorkerClientTests
///
/// Verifies that a command reply arriving on the pipe after events is dispatched promptly even
/// when the event channel is full and has no consumer — event enqueue is decoupled from the read
- /// loop, so a blocked event writer cannot delay a reply (GWC-04). The event full-mode timeout is
+ /// loop, so a blocked event writer cannot delay a reply. The event full-mode timeout is
/// set far above the command timeout: without the decoupling the read loop would block behind the
/// full event channel and the in-flight InvokeAsync would hit CommandTimeout.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
index 2dec8bd..3b3b0fb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
@@ -161,7 +161,7 @@ public sealed class GatewayMetricsTests
/// Verifies that increments
/// mxgateway.heartbeats.failed without emitting a session_id tag: the tag is
/// unbounded cardinality (every session mints a new exporter time series), so per-session
- /// attribution is deliberately kept out of the exported counter (SEC-20).
+ /// attribution is deliberately kept out of the exported counter.
///
[Fact]
public void HeartbeatFailed_IncrementsCounterWithoutSessionIdTag()
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/GatewayTreeHygieneTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/GatewayTreeHygieneTests.cs
index 4505874..ed3083c 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/GatewayTreeHygieneTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/GatewayTreeHygieneTests.cs
@@ -1,7 +1,7 @@
namespace ZB.MOM.WW.MxGateway.Tests.ProjectStructure;
///
-/// Repo-hygiene guards over the source tree. See SEC-01: a Windows-absolute default path that
+/// Repo-hygiene guards over the source tree. A Windows-absolute default path that
/// resolves relative to the launch working directory silently materializes a SQLite credential
/// store inside the tree. This test fails if any such *.db file appears under src/.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
index 6890a75..7d517cc 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
@@ -54,7 +54,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
///
/// Verifies that a key created with an already-past --expires is rejected by the verifier
- /// — the CLI expiry wiring reaches the store and the library enforces it end-to-end (SEC-10).
+ /// — the CLI expiry wiring reaches the store and the library enforces it end-to-end.
///
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs
index 9fe0eba..f7b94bb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs
@@ -52,7 +52,7 @@ public sealed class ApiKeyAdminCommandLineParserTests
Assert.Contains("events:read", result.Command.Scopes);
}
- /// A create-key command without --expires leaves the key non-expiring (opt-in, SEC-10).
+ /// A create-key command without --expires leaves the key non-expiring (opt-in).
[Fact]
public void Parse_CreateKeyCommand_WithoutExpires_HasNoExpiry()
{
@@ -63,7 +63,7 @@ public sealed class ApiKeyAdminCommandLineParserTests
Assert.Null(result.Command.ExpiresUtc);
}
- /// An absolute ISO-8601 --expires value is parsed to that exact UTC instant (SEC-10).
+ /// An absolute ISO-8601 --expires value is parsed to that exact UTC instant.
[Fact]
public void Parse_CreateKeyCommand_WithAbsoluteExpires_ParsesInstant()
{
@@ -77,7 +77,7 @@ public sealed class ApiKeyAdminCommandLineParserTests
result.Command.ExpiresUtc);
}
- /// A relative "<N>d" --expires value resolves to a future UTC instant (SEC-10).
+ /// A relative "<N>d" --expires value resolves to a future UTC instant.
[Fact]
public void Parse_CreateKeyCommand_WithRelativeExpires_ResolvesToFuture()
{
@@ -94,7 +94,7 @@ public sealed class ApiKeyAdminCommandLineParserTests
DateTimeOffset.UtcNow + TimeSpan.FromDays(30) + TimeSpan.FromMinutes(1));
}
- /// An unparseable --expires value fails at parse time (SEC-10).
+ /// An unparseable --expires value fails at parse time.
[Fact]
public void Parse_CreateKeyCommand_WithInvalidExpires_Fails()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs
index 5429448..a658eec 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs
@@ -8,7 +8,7 @@ using LibApiKeyIdentity = ZB.MOM.WW.Auth.Abstractions.ApiKeys.ApiKeyIdentity;
namespace ZB.MOM.WW.MxGateway.Tests.Security.Authentication;
///
-/// SEC-08 hot-path decorators. Covers both mechanisms:
+/// Hot-path decorators. Covers both mechanisms:
/// (read/verification coalescing plus revoke/rotate invalidation) and
/// (the last_used write coalescing that keeps the
/// per-RPC database write off the throughput ceiling).
@@ -18,6 +18,7 @@ public sealed class CachingApiKeyVerifierTests
private const string Header = "Bearer mxgw_operator01_super-secret";
/// A cache hit within the TTL returns the cached result and never calls the inner verifier.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_RepeatedWithinTtl_CallsInnerOnce()
{
@@ -34,6 +35,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// Different presented secrets are cached under distinct keys (no cross-secret aliasing).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_DifferentTokens_NotAliased()
{
@@ -48,6 +50,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// Failed verifications are never cached; every attempt reaches the inner verifier.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_FailedVerification_NotCached()
{
@@ -62,6 +65,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// A TTL of zero disables caching: the inner verifier is called on every request.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_ZeroTtl_DisablesCache()
{
@@ -76,6 +80,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// Invalidating a key id (revoke/rotate) drops its cached verification, forcing a re-verify.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invalidate_DropsCachedEntry_ForcesReverify()
{
@@ -96,6 +101,7 @@ public sealed class CachingApiKeyVerifierTests
/// The store decorator coalesces repeated MarkUsed writes for the same key inside the
/// window down to a single forwarded write — the ≤1/min guarantee for last_used_utc.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoalescingStore_RepeatedMarksWithinWindow_ForwardsOnce()
{
@@ -114,6 +120,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// After the window elapses the next mark is forwarded again (staleness is bounded, not frozen).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoalescingStore_AfterWindow_ForwardsAgain()
{
@@ -129,6 +136,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// Distinct keys are coalesced independently.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoalescingStore_DistinctKeys_TrackedSeparately()
{
@@ -144,6 +152,7 @@ public sealed class CachingApiKeyVerifierTests
}
/// A zero window disables coalescing: every mark is forwarded.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoalescingStore_ZeroWindow_ForwardsEveryMark()
{
@@ -173,8 +182,13 @@ public sealed class CachingApiKeyVerifierTests
private sealed class FakeVerifier(ApiKeyVerification result) : IApiKeyVerifier
{
+ /// Gets the number of times has been called.
public int CallCount { get; private set; }
+ /// Records the call and returns the fixed supplied at construction.
+ /// The authorization header presented by the caller.
+ /// A token to observe for cancellation.
+ /// The fixed verification result.
public Task VerifyAsync(string authorizationHeader, CancellationToken ct)
{
CallCount++;
@@ -184,14 +198,28 @@ public sealed class CachingApiKeyVerifierTests
private sealed class FakeStore : IApiKeyStore
{
+ /// Gets the number of times has been called.
public int MarkUsedCount { get; private set; }
+ /// Always returns ; not exercised by these tests.
+ /// The key id to look up.
+ /// A token to observe for cancellation.
+ /// .
public Task FindByKeyIdAsync(string keyId, CancellationToken ct)
=> Task.FromResult(null);
+ /// Always returns ; not exercised by these tests.
+ /// The key id to look up.
+ /// A token to observe for cancellation.
+ /// .
public Task FindActiveByKeyIdAsync(string keyId, CancellationToken ct)
=> Task.FromResult(null);
+ /// Records the call by incrementing .
+ /// The key id that was used.
+ /// The UTC timestamp of use.
+ /// A token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public Task MarkUsedAsync(string keyId, DateTimeOffset whenUtc, CancellationToken ct)
{
MarkUsedCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
index 796739b..189b8fa 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
@@ -359,7 +359,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-11: once a peer has exceeded the failure limit, the interceptor short-circuits with
+ /// Once a peer has exceeded the failure limit, the interceptor short-circuits with
/// BEFORE calling the verifier, so an online guessing
/// loop stops spending a store read per attempt. A verifier that always fails is used; after the
/// limit is reached the verifier is no longer invoked.
@@ -404,7 +404,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-11: a successful verification resets the peer's failure counter, so accumulated failures
+ /// A successful verification resets the peer's failure counter, so accumulated failures
/// from a fat-fingered secret do not lock out a client that subsequently authenticates.
///
/// A task that represents the asynchronous operation.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
index 5c00e3c..300f933 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
@@ -9,7 +9,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;
///
/// Many tests build the full gateway host through GatewayApplication.Build against the dev
/// appsettings.json (which ships Ldap:Transport=None and other dev-only defaults).
-/// An unset environment resolves to Production, where the SEC-04/06 production guards fail startup
+/// An unset environment resolves to Production, where the production guards fail startup
/// by design — so those host-building tests would trip the guards. Setting the environment to
/// Development once, before any test runs, keeps that suite exercising app wiring rather than
/// production-config validation. Tests that specifically assert production behavior construct
@@ -28,6 +28,10 @@ namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;
///
internal static class TestHostEnvironmentInitializer
{
+ ///
+ /// Applies the Development environment and isolated self-signed-cert path defaults described
+ /// on this type, run once by the runtime before any test in the assembly executes.
+ ///
[ModuleInitializer]
internal static void SetDevelopmentEnvironmentDefault()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
index 8921762..b60ebf6 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
@@ -310,7 +310,7 @@ public sealed class WorkerFrameProtocolTests
///
/// Verifies that under concurrent writers every frame receives a distinct, gap-free sequence in
/// strictly increasing on-wire order — the sequence is stamped by the writer at write time, so the
- /// wire order and the stamped sequence always agree (WRK-04).
+ /// wire order and the stamped sequence always agree.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -339,7 +339,7 @@ public sealed class WorkerFrameProtocolTests
///
/// Verifies that when a control frame and an event frame are both queued behind an in-progress
/// write, the draining lock-holder writes the control frame first even though the event was queued
- /// earlier (WRK-07).
+ /// earlier.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -373,7 +373,7 @@ public sealed class WorkerFrameProtocolTests
Assert.Equal(WorkerEnvelope.BodyOneofCase.WorkerEvent, frame3.BodyCase);
}
- /// Verifies a zero negotiated frame maximum keeps the constructor default (IPC-02).
+ /// Verifies a zero negotiated frame maximum keeps the constructor default.
[Fact]
public void AdoptNegotiatedMaxMessageBytes_WithZero_KeepsDefault()
{
@@ -383,7 +383,7 @@ public sealed class WorkerFrameProtocolTests
Assert.Equal(original, options.MaxMessageBytes);
}
- /// Verifies an in-range negotiated frame maximum is adopted (IPC-02).
+ /// Verifies an in-range negotiated frame maximum is adopted.
[Fact]
public void AdoptNegotiatedMaxMessageBytes_WithInRangeValue_Adopts()
{
@@ -392,7 +392,7 @@ public sealed class WorkerFrameProtocolTests
Assert.Equal(4 * 1024 * 1024, options.MaxMessageBytes);
}
- /// Verifies a negotiated frame maximum above the worker ceiling is rejected (IPC-02).
+ /// Verifies a negotiated frame maximum above the worker ceiling is rejected.
[Fact]
public void AdoptNegotiatedMaxMessageBytes_AboveCeiling_Throws()
{
@@ -452,10 +452,13 @@ public sealed class WorkerFrameProtocolTests
new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
private int _writeCount;
+ /// Gets a task that completes once the first call has started blocking.
public Task FirstWriteStarted => _firstWriteStarted.Task;
+ /// Releases the first blocked write so it can complete.
public void ReleaseFirstWrite() => _release.Release();
+ ///
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (Interlocked.Increment(ref _writeCount) == 1)
@@ -467,6 +470,7 @@ public sealed class WorkerFrameProtocolTests
await base.WriteAsync(buffer, offset, count, cancellationToken);
}
+ ///
protected override void Dispose(bool disposing)
{
if (disposing)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
index 3533efe..4b71b16 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
@@ -452,7 +452,7 @@ public sealed class WorkerPipeSessionTests
///
/// Verifies that a DrainEvents control command with max_events = 0 is bounded by the
/// worker rather than draining the entire queue into one reply frame: the session passes a
- /// capped, non-zero maximum to the runtime session (IPC-04).
+ /// capped, non-zero maximum to the runtime session.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -743,7 +743,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-01 regression: a long in-flight STA command that keeps pumping
+ /// Regression test: a long in-flight STA command that keeps pumping
/// must NOT self-fault as StaHung, and its reply must still be
/// delivered. The real fix makes StaRuntime.PumpPendingMessages
/// refresh LastActivityUtc on every wait iteration, so a healthy
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
index f143324..7173434 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
@@ -92,7 +92,7 @@ public sealed class StaRuntimeTests
/// the first OnDataChange) invokes the pump step on every wait
/// iteration while it legitimately holds the STA thread; refreshing
/// activity here keeps the watchdog from mistaking a busy STA for a hung
- /// one (WRK-01). The runtime is deliberately left unstarted so the only
+ /// one. The runtime is deliberately left unstarted so the only
/// source of activity is the pump call under test, not the idle loop.
///
[Fact]
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
index 776c708..fb0d611 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
@@ -128,7 +128,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
///
/// Records the maxEvents argument of the most recent non-suppressed
/// call — i.e. the effective cap the session passed for an explicit
- /// DrainEvents control command. Lets a test assert the worker bounds the drain (IPC-04) rather
+ /// DrainEvents control command. Lets a test assert the worker bounds the drain rather
/// than forwarding the client's raw max_events = 0.
///
public uint? LastDrainMaxEvents { get; private set; }
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameProtocolOptions.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameProtocolOptions.cs
index b9e016e..96fdcde 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameProtocolOptions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameProtocolOptions.cs
@@ -12,7 +12,7 @@ public sealed class WorkerFrameProtocolOptions
///
/// Upper ceiling the worker will accept for a gateway-negotiated frame maximum
- /// (GatewayHello.max_frame_bytes, IPC-02). Matches the gateway's own configuration ceiling
+ /// (GatewayHello.max_frame_bytes). Matches the gateway's own configuration ceiling
/// so a nonsensical negotiated value is rejected at the handshake rather than driving an absurd
/// per-frame allocation. 256 MiB.
///
@@ -109,15 +109,15 @@ public sealed class WorkerFrameProtocolOptions
///
/// Gets the maximum worker-frame message size in bytes. Initialized from the constructor and
/// then adopted once from the gateway-negotiated value during the startup handshake
- /// (GatewayHello.max_frame_bytes, IPC-02) via ,
+ /// (GatewayHello.max_frame_bytes) via ,
/// before the message loop starts. Not mutated afterwards, so the single-threaded handshake write
/// is safe for the reader/writer that share this instance.
///
public int MaxMessageBytes { get; private set; }
///
- /// Adopts the gateway-negotiated frame maximum conveyed in GatewayHello.max_frame_bytes
- /// (IPC-02). A value of 0 (an older gateway that never set the field) is ignored and the
+ /// Adopts the gateway-negotiated frame maximum conveyed in GatewayHello.max_frame_bytes.
+ /// A value of 0 (an older gateway that never set the field) is ignored and the
/// constructor default is kept. A value above is rejected.
///
/// The gateway-negotiated maximum, or 0 for "keep default".
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWritePriority.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWritePriority.cs
index 46c60f8..1241586 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWritePriority.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWritePriority.cs
@@ -3,9 +3,9 @@ namespace ZB.MOM.WW.MxGateway.Worker.Ipc;
///
/// Relative scheduling priority for an outbound worker frame. The single writer task drains all
/// pending frames before any frame, so a command reply,
-/// fault, heartbeat, or shutdown acknowledgement is not delayed behind a backlog of queued events
-/// (WRK-07). Priority only reorders the write; the frame sequence is stamped at actual write time,
-/// so the on-wire order and the envelope Sequence always agree (WRK-04).
+/// fault, heartbeat, or shutdown acknowledgement is not delayed behind a backlog of queued events.
+/// Priority only reorders the write; the frame sequence is stamped at actual write time,
+/// so the on-wire order and the envelope Sequence always agree.
///
public enum WorkerFrameWritePriority
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
index 5ae2e58..dff6da9 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
@@ -12,22 +12,26 @@ namespace ZB.MOM.WW.MxGateway.Worker.Ipc;
/// Writes worker frames to a stream with length-prefixed protobuf serialization. Callers enqueue a
/// frame at a and then contend for a single write lock; whoever
/// holds the lock drains every queued frame, control frames first, so a reply, fault, or heartbeat is
-/// never delayed behind an event backlog (WRK-07). The envelope Sequence is stamped by the
+/// never delayed behind an event backlog. The envelope Sequence is stamped by the
/// draining lock-holder at the moment of writing, so the on-wire order and the stamped sequence always
-/// agree even under concurrent callers and priority reordering (WRK-04).
+/// agree even under concurrent callers and priority reordering.
///
public sealed class WorkerFrameWriter
{
private sealed class PendingFrame
{
+ /// Initializes a new instance of the PendingFrame class.
+ /// Worker envelope awaiting write.
public PendingFrame(WorkerEnvelope envelope)
{
Envelope = envelope;
Completion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
}
+ /// Gets the worker envelope awaiting write.
public WorkerEnvelope Envelope { get; }
+ /// Gets the completion source signaled once the frame has been written or has failed.
public TaskCompletionSource Completion { get; }
}
@@ -191,7 +195,7 @@ public sealed class WorkerFrameWriter
WorkerEnvelopeValidator.Validate(envelope, _options);
// Stamp the sequence at the actual point of writing, under the write lock, so the wire order
- // and the stamped sequence agree regardless of caller concurrency or priority (WRK-04).
+ // and the stamped sequence agree regardless of caller concurrency or priority.
envelope.Sequence = unchecked(++_nextSequence);
int payloadLength = envelope.CalculateSize();
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
index fea8594..b9629ab 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
@@ -20,7 +20,7 @@ public sealed class WorkerPipeSession
// Hard cap on how many events a single DrainEvents diagnostic reply may carry. DrainEvents is a
// non-streaming control command, so an unbounded drain (including the max_events = 0 "as many as
- // available" request) could pack the whole queue into one session-killing reply frame (IPC-04).
+ // available" request) could pack the whole queue into one session-killing reply frame.
// The gateway request validator rejects requests above its public ceiling; this worker-side cap is
// the backstop and defines the effective per-reply maximum. Kept in step with that public ceiling.
private const uint MaxDrainEventsPerReply = 10_000;
@@ -233,7 +233,7 @@ public sealed class WorkerPipeSession
}
// Adopt the gateway-negotiated frame maximum so both ends frame to the same limit instead of
- // matched compile-time defaults (IPC-02). Applied here, before the message loop, so every
+ // matched compile-time defaults. Applied here, before the message loop, so every
// post-handshake frame is validated against the negotiated value; the reader and writer share
// this options instance. The hello frame itself was small and already read under the default.
_options.AdoptNegotiatedMaxMessageBytes(gatewayHello.MaxFrameBytes);
@@ -375,7 +375,7 @@ public sealed class WorkerPipeSession
{
// Events are the low-priority frame class: the writer holds them behind any pending
// control frame (reply, fault, heartbeat, shutdown ack) so those are not delayed
- // behind an event backlog (WRK-07).
+ // behind an event backlog.
await _writer
.WriteAsync(CreateEnvelope(workerEvent), WorkerFrameWritePriority.Event, cancellationToken)
.ConfigureAwait(false);
@@ -543,7 +543,7 @@ public sealed class WorkerPipeSession
if (runtimeSession is not null)
{
// Bound the diagnostic drain so max_events = 0 ("as many as available") or an over-large
- // request cannot pack the whole queue into one session-killing reply frame (IPC-04).
+ // request cannot pack the whole queue into one session-killing reply frame.
uint requested = command.DrainEvents?.MaxEvents ?? 0;
uint maxEvents = requested == 0 || requested > MaxDrainEventsPerReply
? MaxDrainEventsPerReply
@@ -1026,7 +1026,7 @@ public sealed class WorkerPipeSession
{
// Sequence is deliberately left unset here: the frame writer stamps it at the actual point of
// writing, under its single drain task, so the on-wire order and the stamped sequence agree
- // even under concurrent producers and priority reordering (WRK-04).
+ // even under concurrent producers and priority reordering.
return new WorkerEnvelope
{
ProtocolVersion = _options.ProtocolVersion,
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/SubtagAlarmConsumer.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/SubtagAlarmConsumer.cs
index 9ef6ab8..c02b519 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/SubtagAlarmConsumer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/SubtagAlarmConsumer.cs
@@ -78,13 +78,6 @@ public sealed class SubtagAlarmConsumer : IMxAccessAlarmConsumer
}
///
- ///
- /// The expression is ignored — the subtag
- /// set is fixed by the watch list. Also advises the ack-comment subtag so
- /// it is an active MXAccess item by the time
- /// writes it; MXAccess rejects a write to an added-but-not-advised item
- /// with E_INVALIDARG.
- ///
public void Subscribe(string subscription)
{
if (disposed)
@@ -111,11 +104,6 @@ public sealed class SubtagAlarmConsumer : IMxAccessAlarmConsumer
}
///
- ///
- /// Resolves the synthetic GUID back to its alarm full reference and
- /// delegates to the by-name write path; operator-identity arguments are
- /// not surfaced through the subtag write.
- ///
public int AcknowledgeByGuid(
Guid alarmGuid,
string ackComment,
@@ -139,11 +127,6 @@ public sealed class SubtagAlarmConsumer : IMxAccessAlarmConsumer
}
///
- ///
- /// In subtag mode the comment is written to the target's writable
- /// ack-comment subtag; the operator-identity arguments are not
- /// surfaced through the subtag write.
- ///
public int AcknowledgeByName(
string alarmName,
string providerName,
@@ -169,10 +152,6 @@ public sealed class SubtagAlarmConsumer : IMxAccessAlarmConsumer
}
///
- ///
- /// Each returned record is stamped
- /// and assigned its synthetic GUID.
- ///
public IReadOnlyList SnapshotActiveAlarms()
{
IReadOnlyList records = stateMachine.SnapshotActive();
@@ -185,7 +164,6 @@ public sealed class SubtagAlarmConsumer : IMxAccessAlarmConsumer
}
///
- /// No-op: the subtag path is event-driven and owns no poll cadence.
public void PollOnce()
{
// Subtag mode is event-driven; value changes arrive via the source's
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
index e41f371..8dd78b9 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
@@ -301,14 +301,6 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
}
///
- ///
- /// STA-bound hosts drive polling by calling this from
- /// the thread that owns the COM object. The consumer deliberately
- /// owns no internal timer: a thread-pool timer would call the
- /// apartment-threaded COM object off its owning STA and can block
- /// indefinitely on cross-apartment marshaling when the STA is not
- /// pumping messages.
- ///
public void PollOnce()
{
wwAlarmConsumerClass? com;