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 a84a324..f84fb72 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
@@ -347,13 +347,13 @@ public static class MxGatewayClientCli
///
/// Canonical CLI credential environment variable, shared by every official
- /// client CLI (CLI-45) so one exported variable drives the same operator
+ /// client CLI so one exported variable drives the same operator
/// workflow in all five languages.
///
private const string DefaultVerifyPasswordEnvironmentName = "MXGATEWAY_VERIFY_PASSWORD";
///
- /// Pre-CLI-45 environment variable, still honoured as a deprecated fallback
+ /// Legacy environment variable, still honoured as a deprecated fallback
/// for one release so existing scripts keep working.
///
private const string LegacyVerifyPasswordEnvironmentName = "MXGATEWAY_VERIFY_USER_PASSWORD";
@@ -379,14 +379,14 @@ public static class MxGatewayClientCli
}
///
- /// Resolves the effective MXAccess verify-user credential in the CLI-45
+ /// Resolves the effective MXAccess verify-user credential in this
/// order: --password, the deprecated --verify-user-password
/// alias, the environment variable named by --password-env (default
/// MXGATEWAY_VERIFY_PASSWORD), then the deprecated
/// MXGATEWAY_VERIFY_USER_PASSWORD. An empty value from any source is
/// treated as absent. The credential is never echoed; this resolver exists so
- /// the error-redaction catch block can strip it from any surfaced error
- /// (CLI-04), mirroring .
+ /// the error-redaction catch block can strip it from any surfaced error,
+ /// mirroring .
///
private static string? TryResolveVerifyUserPassword(CliArguments arguments)
{
@@ -416,7 +416,7 @@ public static class MxGatewayClientCli
/// Resolves the verify-user credential for authenticate-user, throwing
/// a redaction-safe error when no source yields a non-empty value. Failing
/// fast keeps a misconfigured environment from becoming a real MXAccess
- /// authentication attempt with an empty credential (CLI-45); the thrown
+ /// authentication attempt with an empty credential; the thrown
/// message names only the option/env var, never the value.
///
private static string ResolveVerifyUserPassword(CliArguments arguments)
@@ -758,9 +758,9 @@ public static class MxGatewayClientCli
{
// The credential is resolved from --password or its env var (default
// MXGATEWAY_VERIFY_PASSWORD) and is never echoed; a missing or empty value
- // fails fast before the invoke rather than reaching the wire (CLI-45).
+ // fails fast before the invoke rather than reaching the wire.
// On any surfaced error the RunCoreAsync catch block routes
- // it through MxGatewayCliSecretRedactor so it cannot reach stderr (CLI-04).
+ // it through MxGatewayCliSecretRedactor so it cannot reach stderr.
return InvokeAndWriteAsync(
arguments,
client,
@@ -1425,7 +1425,7 @@ public static class MxGatewayClientCli
else if (gatewayEvent.ReplayGap is { } replayGap)
{
// Render the ReplayGap sentinel as the typed cross-CLI row instead of the raw
- // sentinel MxEvent (NEXT-02, mirroring the Go/Python/Rust CLIs).
+ // sentinel MxEvent, mirroring the Go/Python/Rust CLIs.
output.WriteLine(FormatReplayGapRow(replayGap));
}
else
@@ -1849,7 +1849,7 @@ public static class MxGatewayClientCli
}
///
- /// Formats the typed ReplayGap row shared by the CLIs (NEXT-02). Hand-built so the
+ /// Formats the typed ReplayGap row shared by the CLIs. Hand-built so the
/// cursors are JSON numbers like the Go/Python/Rust rows, not the protobuf JSON
/// formatter's quoted uint64 strings.
///
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 b0b4f3e..43da1f1 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
@@ -134,6 +134,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that write-secured builds a WriteSecured command with the value and user ids.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WriteSecured_BuildsWriteSecuredCommand()
{
@@ -178,6 +179,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies that authenticate-user builds an AuthenticateUser command sourcing the
/// credential from the flag, and that the credential never appears in stdout/stderr.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AuthenticateUser_BuildsCommandAndDoesNotEchoCredential()
{
@@ -218,9 +220,10 @@ public sealed class MxGatewayClientCliTests
}
///
- /// CLI-04: a surfaced error for authenticate-user must have the credential
+ /// Verifies that a surfaced error for authenticate-user must have the credential
/// redacted (never echoed to stderr), mirroring the API-key redaction seam.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AuthenticateUser_ErrorOutput_RedactsCredential()
{
@@ -248,7 +251,7 @@ public sealed class MxGatewayClientCliTests
}
///
- /// CLI-45: --password is the primary credential flag, matching the other
+ /// --password is the primary credential flag, matching the other
/// four CLIs. The credential reaches the wire but never stdout/stderr.
///
/// A task that represents the asynchronous operation.
@@ -290,10 +293,12 @@ public sealed class MxGatewayClientCliTests
}
///
- /// CLI-45: the credential is read from the environment variable named by
+ /// the credential is read from the environment variable named by
/// --password-env, whose default is the canonical
/// MXGATEWAY_VERIFY_PASSWORD shared by all five CLIs.
///
+ /// The value passed to --password-env, or null to use the default.
+ /// The environment variable that holds the credential.
/// A task that represents the asynchronous operation.
[Theory]
[InlineData(null, "MXGATEWAY_VERIFY_PASSWORD")]
@@ -340,7 +345,7 @@ public sealed class MxGatewayClientCliTests
}
///
- /// CLI-45: the pre-rename names stay usable for one release — the deprecated
+ /// the pre-rename names stay usable for one release — the deprecated
/// --verify-user-password flag and the deprecated
/// MXGATEWAY_VERIFY_USER_PASSWORD environment variable both still resolve.
///
@@ -413,7 +418,7 @@ public sealed class MxGatewayClientCliTests
}
///
- /// CLI-45: a missing or empty credential fails fast before the invoke — the CLI
+ /// a missing or empty credential fails fast before the invoke — the CLI
/// never sends a fabricated empty password to the wire. The error names the flag
/// and the environment variable, never a value.
///
@@ -463,6 +468,9 @@ public sealed class MxGatewayClientCliTests
private readonly string _name;
private readonly string? _original;
+ /// Sets the environment variable and remembers its original value.
+ /// The environment variable name.
+ /// The temporary value, or null to clear it.
public EnvironmentVariableScope(string name, string? value)
{
_name = name;
@@ -470,6 +478,7 @@ public sealed class MxGatewayClientCliTests
Environment.SetEnvironmentVariable(name, value);
}
+ /// Restores the original environment variable value.
public void Dispose()
{
Environment.SetEnvironmentVariable(_name, _original);
@@ -588,7 +597,7 @@ public sealed class MxGatewayClientCliTests
///
/// Verifies stream-events renders the ReplayGap sentinel as the typed cross-CLI row —
- /// numeric cursors under a replayGap key — instead of the raw sentinel MxEvent (NEXT-02).
+ /// numeric cursors under a replayGap key — instead of the raw sentinel MxEvent.
///
/// A task that represents the asynchronous operation.
[Fact]
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 8fb4f89..9cf14e7 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
@@ -228,6 +228,7 @@ public sealed class MxGatewayClientSessionTests
/// with the gap populated, while normal
/// events pass through unchanged with IsReplayGap false.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventItemsAsync_SurfacesReplayGapSentinel()
{
@@ -430,6 +431,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that unregister builds an unregister command with the server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnregisterAsync_BuildsUnregisterCommand()
{
@@ -451,6 +453,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that advise-supervisory builds the supervisory advise command.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AdviseSupervisoryAsync_BuildsAdviseSupervisoryCommand()
{
@@ -473,6 +476,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that add-buffered-item returns the item handle from the typed reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddBufferedItemAsync_BuildsCommandAndReturnsItemHandle()
{
@@ -498,6 +502,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that set-buffered-update-interval builds the command with the interval.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SetBufferedUpdateIntervalAsync_BuildsCommandWithInterval()
{
@@ -520,6 +525,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that suspend builds the command and returns the reply status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SuspendAsync_BuildsCommandAndReturnsStatus()
{
@@ -545,6 +551,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that activate builds the command and returns the reply status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ActivateAsync_BuildsCommandAndReturnsStatus()
{
@@ -568,6 +575,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write-secured builds a WriteSecured command with value and user ids.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecuredAsync_BuildsWriteSecuredCommand()
{
@@ -598,6 +606,7 @@ public sealed class MxGatewayClientSessionTests
/// natively. The client must surface that scripted failure (as an
/// ) rather than pre-validating it away.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecuredAsync_SurfacesNativeFailureWhenNotAuthenticated()
{
@@ -621,6 +630,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write-secured2 builds a WriteSecured2 command with value and timestamp.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecured2Async_BuildsWriteSecured2Command()
{
@@ -647,6 +657,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that authenticate-user builds the command and returns the resolved user id.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateUserAsync_BuildsCommandAndReturnsUserId()
{
@@ -675,6 +686,7 @@ public sealed class MxGatewayClientSessionTests
/// must never contain the credential — the error path is built only from
/// reply-derived diagnostics, not the request payload.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateUserAsync_FailureDoesNotLeakCredentialInErrorMessage()
{
@@ -698,6 +710,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that archestra-user-to-id builds the command and returns the resolved user id.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ArchestraUserToIdAsync_BuildsCommandAndReturnsUserId()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySecretRedactionTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySecretRedactionTests.cs
index ba04c89..1ea5527 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySecretRedactionTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySecretRedactionTests.cs
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
///
public sealed class MxGatewaySecretRedactionTests
{
+ /// Test: Redact replaces every occurrence of secret.
[Fact]
public void Redact_ReplacesEveryOccurrenceOfSecret()
{
@@ -19,6 +20,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal("pw= retry pw= again ", result);
}
+ /// Test: Redact scrubs both secrets when one is substring of the other.
[Fact]
public void Redact_ScrubsBothSecretsWhenOneIsSubstringOfTheOther()
{
@@ -33,6 +35,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.DoesNotContain("secret", result, StringComparison.Ordinal);
}
+ /// Test: Redact with null secrets array returns message unchanged.
[Fact]
public void Redact_WithNullSecretsArray_ReturnsMessageUnchanged()
{
@@ -43,6 +46,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
+ /// Test: Redact with empty secrets array returns message unchanged.
[Fact]
public void Redact_WithEmptySecretsArray_ReturnsMessageUnchanged()
{
@@ -53,6 +57,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
+ /// Test: Redact ignores whitespace only secret.
[Fact]
public void Redact_IgnoresWhitespaceOnlySecret()
{
@@ -64,6 +69,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
+ /// Test: Redacted preserves concrete subtype and does not chain secret bearing original.
[Fact]
public void Redacted_PreservesConcreteSubtypeAndDoesNotChainSecretBearingOriginal()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySessionReplyContractTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySessionReplyContractTests.cs
index f9c71d0..7e2faba 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySessionReplyContractTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewaySessionReplyContractTests.cs
@@ -4,15 +4,16 @@ using ZB.MOM.WW.MxGateway.Contracts.Proto;
namespace ZB.MOM.WW.MxGateway.Client.Tests;
///
-/// Tests for the credential-scrub (CLI-40) and malformed-reply (CLI-41) contracts on the
+/// Tests for the credential-scrub and malformed-reply contracts on the
/// credential and id-returning session helpers, driven from shared behavior fixtures.
///
public sealed class MxGatewaySessionReplyContractTests
{
///
- /// CLI-40: when MXAccess echoes the submitted credential back in its failure diagnostic,
+ /// Verifies that when MXAccess echoes the submitted credential back in its failure diagnostic,
/// the surfaced exception message must scrub it to the library redaction marker.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateUserAsync_RedactsEchoedCredentialInFailureMessage()
{
@@ -33,13 +34,14 @@ public sealed class MxGatewaySessionReplyContractTests
}
///
- /// CLI-40: the redacted exception must not leak the echoed credential through any structured
+ /// Verifies that the redacted exception must not leak the echoed credential through any structured
/// accessor either — (protocol message, diagnostic
/// message, and each MXSTATUS_PROXY diagnostic text) and
/// all carry the server-echoed credential verbatim before the fix. Both the OK+negative-HRESULT
/// and the MXACCESS_FAILURE reply route to , so both must scrub.
///
/// The echoed-credential reply fixture to drive.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("authenticate-user.echoed-credential.reply.json")]
[InlineData("authenticate-user.echoed-credential-mxaccess-failure.reply.json")]
@@ -71,9 +73,10 @@ public sealed class MxGatewaySessionReplyContractTests
}
///
- /// CLI-41: an OK reply that carries neither the typed AuthenticateUser payload nor an
+ /// Verifies that an OK reply that carries neither the typed AuthenticateUser payload nor an
/// int32 return_value is a malformed reply, surfaced as a typed exception rather than an NRE.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateUserAsync_MissingPayloadAndReturnValue_ThrowsMalformedReply()
{
@@ -87,9 +90,10 @@ public sealed class MxGatewaySessionReplyContractTests
}
///
- /// CLI-41: an OK reply that omits the typed payload but carries an int32 return_value
+ /// Verifies that an OK reply that omits the typed payload but carries an int32 return_value
/// resolves to that return value.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateUserAsync_ReturnValueOnly_ResolvesReturnValue()
{
@@ -104,9 +108,10 @@ public sealed class MxGatewaySessionReplyContractTests
}
///
- /// CLI-41: the AddBufferedItem fallback shares the malformed-reply contract — an OK reply
+ /// Verifies that the AddBufferedItem fallback shares the malformed-reply contract — an OK reply
/// with neither a typed item handle nor an int32 return_value throws the typed exception.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddBufferedItemAsync_MissingPayloadAndReturnValue_ThrowsMalformedReply()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxStatusProxyExtensionsTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxStatusProxyExtensionsTests.cs
index 5c54950..5d62434 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxStatusProxyExtensionsTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxStatusProxyExtensionsTests.cs
@@ -32,6 +32,9 @@ public sealed class MxStatusProxyExtensionsTests
}
/// Verifies that the raw success member never overrides the authoritative category.
+ /// The status category under test.
+ /// The raw success member, which must not influence the result.
+ /// The expected IsSuccess result.
[Theory]
[InlineData(MxStatusCategory.Ok, 0, true)]
[InlineData(MxStatusCategory.Ok, 1, true)]
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/WireFakeGatewayServer.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/WireFakeGatewayServer.cs
index ce10b50..3cfc9bd 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/WireFakeGatewayServer.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/WireFakeGatewayServer.cs
@@ -96,7 +96,8 @@ internal sealed class WireFakeGatewayServer : IAsyncDisposable
DefaultCallTimeout = TimeSpan.FromSeconds(30),
});
- ///
+ /// Stops and disposes the underlying web application.
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await _app.StopAsync().ConfigureAwait(false);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
index b24512c..8a9e570 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
@@ -854,6 +854,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
///
/// The ServerHandle from register.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task UnregisterAsync(
int serverHandle,
CancellationToken cancellationToken = default)
@@ -888,6 +889,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 AdviseSupervisoryAsync(
int serverHandle,
int itemHandle,
@@ -985,6 +987,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The buffered update interval, in milliseconds.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task SetBufferedUpdateIntervalAsync(
int serverHandle,
int updateIntervalMilliseconds,
@@ -1125,6 +1128,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The current operator user id.
/// The verifier (secondary approver) user id.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task WriteSecuredAsync(
int serverHandle,
int itemHandle,
@@ -1204,6 +1208,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The current operator user id.
/// The verifier (secondary approver) user id.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task WriteSecured2Async(
int serverHandle,
int itemHandle,
diff --git a/src/ZB.MOM.WW.MxGateway.Contracts/GatewayContractInfo.cs b/src/ZB.MOM.WW.MxGateway.Contracts/GatewayContractInfo.cs
index 0d070c1..b459059 100644
--- a/src/ZB.MOM.WW.MxGateway.Contracts/GatewayContractInfo.cs
+++ b/src/ZB.MOM.WW.MxGateway.Contracts/GatewayContractInfo.cs
@@ -25,7 +25,7 @@ public static class GatewayContractInfo
/// (WorkerPipeSession.CreateDrainEventsReply, the backstop that also interprets
/// max_events = 0) cannot drift apart. A count cap alone is necessary but not
/// sufficient: the worker additionally caps the reply by serialized bytes against the
- /// negotiated frame maximum (WRK-21), so a reply may carry fewer events than this ceiling
+ /// negotiated frame maximum, so a reply may carry fewer events than this ceiling
/// and fewer than are queued. Callers drain iteratively until an empty reply.
/// This is a documented behavioral bound, not wire schema — it is deliberately a C#
/// constant and not a .proto field.
diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
index fef196f..1220118 100644
--- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
@@ -27,7 +27,7 @@ public sealed class DashboardLdapLiveTests
private const string SharedDirectoryPassword = "password";
///
- /// Dashboard visibility tags (SEC-25) used by the ACL scenarios below. They are operator-chosen
+ /// Dashboard visibility tags used by the ACL scenarios below. They are operator-chosen
/// labels that exist only in this fixture's configuration and in the fake sessions' owner-tag
/// list — nothing in the shared directory carries them.
///
@@ -168,7 +168,7 @@ public sealed class DashboardLdapLiveTests
}
///
- /// Verifies the SEC-25 tag grant end-to-end from a real LDAP bind: gw-viewer's only
+ /// Verifies the tag grant end-to-end from a real LDAP bind: gw-viewer's only
/// group (GwReader) is mapped to the team-a visibility tag by Dashboard:GroupToTag,
/// and the principal that bind produces is admitted by for a
/// team-a-tagged session but refused for a team-b-tagged one.
@@ -275,7 +275,7 @@ public sealed class DashboardLdapLiveTests
};
///
- /// The SEC-25 fixture map: GwReader is admitted as a Viewer and granted team-a. Both keys
+ /// The tagged fixture map: GwReader is admitted as a Viewer and granted team-a. Both keys
/// name groups that already exist in the shared directory — the tag layer is config-only.
///
private static DashboardOptions TaggedDashboardOptions() => new()
diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
index a9c2b66..fcc2506 100644
--- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
@@ -526,7 +526,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
// Assert. But a silent fall-through to "operator only" (currentUserId 0)
// quietly demotes the rest of this test from an authenticated round-trip
// to a bare failure-reply-shape check, which a stale rig credential (e.g.
- // TST-31) would otherwise hide indefinitely in nightly runs. Log the
+ // one that has expired) would otherwise hide indefinitely in nightly runs. Log the
// outcome loudly — never the password (verifyUser only) — so that
// degradation is visible in the test output even though it never fails
// the test by itself.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmProviderReasons.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmProviderReasons.cs
index 46359b2..d35cacf 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmProviderReasons.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmProviderReasons.cs
@@ -19,7 +19,7 @@ public static class AlarmProviderReasons
///
/// Reason prefix set when the effective mode can need the subtag watch-list
/// (Auto or ForceSubtag) but the list resolved to zero targets, so the
- /// subtag provider covers no alarms (GWC-37). In Auto this is a warning about the
+ /// subtag provider covers no alarms. In Auto this is a warning about the
/// standby, not about the currently-serving alarm manager, which is why the dashboard
/// renders it against the ALARMMGR mode as a coverage badge rather than a failover.
///
@@ -29,7 +29,7 @@ public static class AlarmProviderReasons
///
/// Reason prefix set when Galaxy Repository alarm discovery was enabled but failed, so
/// the watch-list carries only what configuration contributed and may be incomplete
- /// (GWC-37). Distinct from : discovery failing with a
+ /// . Distinct from : discovery failing with a
/// usable config-only list is a completeness warning, not a total loss of coverage.
///
public const string SubtagDiscoveryFailed =
@@ -37,7 +37,7 @@ public static class AlarmProviderReasons
///
/// Reason prefix set when a re-resolution at the failover edge produced a different
- /// watch-list than the one sent at SubscribeAlarms (GWC-37). The worker keeps the
+ /// watch-list than the one sent at SubscribeAlarms. The worker keeps the
/// list it was given for the life of the subscription, so the difference is reported
/// rather than applied; a monitor restart re-resolves and re-sends.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolution.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolution.cs
index 8c19eef..47469e6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolution.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolution.cs
@@ -5,8 +5,8 @@ namespace ZB.MOM.WW.MxGateway.Server.Alarms;
///
/// The outcome of one subtag watch-list resolution: the composed targets plus enough
/// provenance for the caller to tell an empty list that means "nothing was configured"
-/// from one that means "discovery was configured and silently produced nothing"
-/// (GWC-37). deliberately never throws
+/// from one that means "discovery was configured and silently produced nothing".
+/// deliberately never throws
/// on a discovery failure, so without this the two are indistinguishable at the call site
/// and a Galaxy Repository outage at startup can only be found in a log line.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolver.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolver.cs
index b17c053..4c48017 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolver.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/AlarmWatchListResolver.cs
@@ -39,7 +39,7 @@ public sealed class AlarmWatchListResolver : IAlarmWatchListResolver
AlarmDiscoveryOptions discovery = options.Fallback.Discovery;
- // GWC-37: the caller cannot grade an empty watch-list without knowing whether discovery
+ // The caller cannot grade an empty watch-list without knowing whether discovery
// was asked to contribute and whether it failed while doing so, because the failure is
// deliberately swallowed below.
string? discoveryFailureMessage = null;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
index 55ee66b..b271c8f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
@@ -41,7 +41,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
// every path that writes _alarms must null this under _sync, or readers keep a stale set.
private ActiveAlarmSnapshot[]? _currentAlarmsProjection;
- // NEXT-03 dedup tombstones, guarded by _sync: alarm instances whose Clear was synthesized by
+ // Dedup tombstones, guarded by _sync: alarm instances whose Clear was synthesized by
// the most recent reconcile pass, keyed by reference with the instance's original raise
// timestamp as the identity marker. A buffered live Clear for the same instance is a duplicate
// of the repair and is suppressed. One generation deep: each reconcile pass replaces the map,
@@ -57,7 +57,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
private string _providerReason = string.Empty;
private DateTimeOffset _providerSince = DateTimeOffset.UtcNow;
- // GWC-37 subtag-coverage verdict, guarded by _sync: whether the watch-list the worker is
+ // Subtag-coverage verdict, guarded by _sync: whether the watch-list the worker is
// using can actually cover anything, and why not. Independent of _providerDegraded (which
// means "the subtag provider is the one serving"): in Auto mode the alarm manager can be
// serving perfectly while the standby behind it covers zero alarms, and that is invisible
@@ -258,7 +258,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
try
{
- // Attach the internal distributor subscriber BEFORE subscribing (GWC-26). The pump
+ // Attach the internal distributor subscriber BEFORE subscribing. The pump
// has been running since MarkReady started the dashboard mirror, and the distributor
// only fans to subscribers registered at the time of the fan-out, so a subscriber
// taken after SubscribeAlarms + the first reconcile would silently lose every
@@ -351,7 +351,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
AlarmProviderMode forcedMode = MapForcedMode(_options.Fallback.Mode);
- // GWC-37: grade the coverage before the command goes out, so a Galaxy Repository outage at
+ // Grade the coverage before the command goes out, so a Galaxy Repository outage at
// startup is a standing status on the feed instead of one log line an operator reads weeks
// later — when the failover that needed the watch-list finds it empty. Broadcast because
// feed subscribers outlive the monitor's worker session and may already be attached.
@@ -507,7 +507,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
}
}
- // NEXT-03: best-effort dedup of the reconcile/live race. A reconcile that already synthesized
+ // Best-effort dedup of the reconcile/live race. A reconcile that already synthesized
// this transition as a feed repair left the cache carrying the worker's transition timestamp
// and resulting state — both derived from the same worker-side value the live transition
// carries — so an exact (timestamp, state) match means this live transition's outcome has
@@ -521,7 +521,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
&& existing.CurrentState == incoming.CurrentState;
}
- // NEXT-03, the Clear leg. A reconcile Clear repair removes the cache entry before the buffered
+ // The Clear leg of the dedup. A reconcile Clear repair removes the cache entry before the buffered
// live Clear drains, so there is no cached state to compare against; the tombstone recorded by
// ApplyReconcile identifies the cleared instance by its original raise timestamp instead. The
// match consumes the tombstone, so a genuinely new raise/clear cycle (which carries a newer
@@ -803,7 +803,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
// Caller holds _sync. Builds an AlarmProviderStatus snapshot of the current state.
//
- // GWC-37: degraded is the OR of "the subtag provider is the one serving" and "the subtag
+ // Degraded is the OR of "the subtag provider is the one serving" and "the subtag
// watch-list cannot cover anything". The second is what makes an empty watch-list visible in
// Auto mode, where the alarm manager is serving happily and the standby behind it is empty.
// The reasons are concatenated when both apply, which is the worst case worth naming loudly:
@@ -857,7 +857,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
// Replaces the cache with the worker's authoritative snapshot, broadcasting
// a synthetic transition for any alarm the live stream missed.
//
- // Repair scope (GWC-26): presence deltas (Clear/Raise) plus acked-state deltas. These are
+ // Repair scope: presence deltas (Clear/Raise) plus acked-state deltas. These are
// ALARM FEED transitions (AlarmFeedMessage on the StreamAlarms/dashboard surface), rebuilt
// from the worker's own authoritative snapshot to repair what the live feed missed. They are
// not MxEvents and never reach the gRPC StreamEvents path, so this feed-level repair does not
@@ -867,7 +867,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
// reads the worker's current state while the corresponding live transition may still be
// buffered in the alarm lease's channel; both would then broadcast, and the two are
// indistinguishable on the feed, since nothing serializes a reconcile against the in-flight
- // live stream. ApplyTransition narrows that window with a best-effort dedup (NEXT-03): a live
+ // live stream. ApplyTransition narrows that window with a best-effort dedup: a live
// transition whose worker timestamp and resulting state the cache already carries — or whose
// Clear matches a tombstone recorded below — was already broadcast as a repair and is
// suppressed. The dedup fires only on a positive marker match, so the contract stays
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GalaxyRepositoryOptionsValidator.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GalaxyRepositoryOptionsValidator.cs
index feb632a..7d7b79d 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GalaxyRepositoryOptionsValidator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GalaxyRepositoryOptionsValidator.cs
@@ -8,7 +8,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Configuration;
/// ZB.MOM.WW.GalaxyRepository package binds the options but deliberately ships no validator
/// (see A2-galaxyrepository-adoption-handoff.md); the gateway owns the rule because it is the
/// process that writes the snapshot. When persistence is on, the snapshot path must be a valid,
-/// rooted path on the running host for the same reason the auth DB path must be (SEC-33): a
+/// rooted path on the running host for the same reason the auth DB path must be: a
/// non-rooted value silently resolves against the launch working directory.
///
public sealed class GalaxyRepositoryOptionsValidator : OptionsValidatorBase
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigPathRules.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigPathRules.cs
index 38e72b1..43d17fb 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigPathRules.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayConfigPathRules.cs
@@ -18,7 +18,7 @@ internal static class GatewayConfigPathRules
/// against the launch working directory, so the store moves with the CWD and can leak into the
/// source tree. Rooting is checked with — the current
/// OS — so a Windows drive/UNC literal on a Unix host fails fast at startup rather than being
- /// blessed and then written as a junk-named relative file (the SEC-01/SEC-33 mechanism). Reject
+ /// blessed and then written as a junk-named relative file. Reject
/// rather than auto-root; silent relocation of a credential store is worse than a boot error.
/// Blank is handled by the caller's required-field check and is not treated as non-rooted here.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
index a0d8496..f103bdc 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
@@ -113,7 +113,7 @@ public sealed class GatewayOptionsValidator : OptionsValidatorBase GatewayConfigPathRules.AddIfNotRooted(value, message, builder);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
index 140f2e9..f7c27a5 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/WorkerOptions.cs
@@ -61,7 +61,7 @@ public sealed class WorkerOptions
/// still fits one worker frame, and at most twice that reserve above it so a
/// DrainEvents reply budgeted against this maximum (frame max less two reserves) still
/// fits the gRPC send cap it is returned through — otherwise the worker can pack a reply the
- /// pipe carries and the gRPC layer refuses, losing the already-drained events (IPC-33). The
+ /// pipe carries and the gRPC layer refuses, losing the already-drained events. The
/// gateway conveys this value to the worker in the handshake
/// (GatewayHello.max_frame_bytes). Default is the 16 MB public gRPC cap plus one reserve.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleHandler.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleHandler.cs
index 8d77bdc..2b7d0c6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleHandler.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleHandler.cs
@@ -5,7 +5,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
///
/// Handler for : succeeds only when the caller
/// is authenticated AND holds one of the requirement's roles. It reads no options at all, which
-/// is the point — there is no configuration value that can turn this into a bypass (SEC-40).
+/// is the point — there is no configuration value that can turn this into a bypass.
///
public sealed class AuthenticatedDashboardRoleHandler
: AuthorizationHandler
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleRequirement.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleRequirement.cs
index 8364ec6..fe87d36 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleRequirement.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/AuthenticatedDashboardRoleRequirement.cs
@@ -13,9 +13,9 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
/// into this one by accident.
///
///
-/// Introduced for SEC-40 to gate the alarm feed (AlarmsHub and the /alarms page),
+/// Introduced to gate the alarm feed (AlarmsHub and the /alarms page),
/// which is gateway-central and session-less and therefore carries no per-session provenance the
-/// SEC-25 tag ACL could scope it by. Requiring a real dashboard role claim is the narrowing that
+/// tag ACL could scope it by. Requiring a real dashboard role claim is the narrowing that
/// is actually available: it keeps galaxy-wide alarm metadata — alarm reference (a full tag path),
/// state, severity, category, area, acknowledging operator — away from the read-only environment
/// bypasses, which exist for local development and unauthenticated deployments rather than as a
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAlarmProviderStatus.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAlarmProviderStatus.cs
index 19e01b9..176f330 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAlarmProviderStatus.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAlarmProviderStatus.cs
@@ -32,7 +32,7 @@ public sealed record DashboardAlarmProviderStatus(
///
/// Badge label shown when the alarm manager is serving normally but the subtag standby
- /// behind it covers nothing — an empty or undiscoverable watch-list (GWC-37). The feed is
+ /// behind it covers nothing — an empty or undiscoverable watch-list. The feed is
/// healthy today; what is degraded is the fallback that would take over tomorrow, so the
/// badge names the standby rather than claiming the feed has failed over.
///
@@ -77,7 +77,7 @@ public sealed record DashboardAlarmProviderStatus(
&& status.Mode == AlarmProviderMode.Subtag
&& string.Equals(reason, AlarmProviderReasons.ForcedSubtag, StringComparison.Ordinal);
- // GWC-37: degraded WITHOUT subtag mode means the alarm manager is still serving and the
+ // Degraded WITHOUT subtag mode means the alarm manager is still serving and the
// standby is the unsound half. "Subtag monitoring (degraded)" would misreport which
// provider is live, so this state gets its own label; the amber badge is shared because
// the operator action — fix discovery — is equally overdue in both.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationDefaults.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationDefaults.cs
index 1a74af2..407a187 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationDefaults.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationDefaults.cs
@@ -35,7 +35,7 @@ public static class DashboardAuthenticationDefaults
///
/// Policy guarding the alarm feed — the AlarmsHub SignalR surface and the
- /// /alarms page that reads the same central monitor in process (SEC-40). Accepts the
+ /// /alarms page that reads the same central monitor in process. Accepts the
/// same two schemes as but carries
/// , a requirement type
/// does not handle, so the environment bypasses
@@ -49,10 +49,10 @@ public static class DashboardAuthenticationDefaults
public const string KeyPrefixClaimType = "mxgateway:key_prefix";
///
- /// Claim carrying one dashboard event-visibility tag the caller is granted (SEC-25). Stamped
+ /// Claim carrying one dashboard event-visibility tag the caller is granted. Stamped
/// at cookie login by and at hub-token mint by
/// , both resolving the caller's LDAP groups through
- /// MxGateway:Dashboard:GroupToTag. Since SEC-41 reads
+ /// MxGateway:Dashboard:GroupToTag. reads
/// this claim only as a FALLBACK, for a principal that carries no
/// claims to re-resolve from (the hub-token principal, whose
/// payload carries tags but not groups); a cookie principal is re-resolved against current
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs
index 8250990..765f89a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticator.cs
@@ -21,7 +21,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
/// Maps LDAP groups to dashboard roles.
///
/// Gateway options supplying MxGateway:Dashboard:GroupToTag, the map that turns the user's
-/// LDAP groups into the dashboard visibility tags stamped on the cookie principal (SEC-25).
+/// LDAP groups into the dashboard visibility tags stamped on the cookie principal.
///
/// Logger for diagnostic, credential-free login outcomes.
public sealed class DashboardAuthenticator(
@@ -142,7 +142,7 @@ public sealed class DashboardAuthenticator(
claims.AddRange(groupNames.Select(group => new Claim(
DashboardAuthenticationDefaults.LdapGroupClaimType,
group)));
- // Dashboard event-visibility tags (SEC-25). Visibility only — never a data-access grant —
+ // Dashboard event-visibility tags. Visibility only — never a data-access grant —
// and never logged: only the decision, never the tag values, reaches diagnostics.
claims.AddRange(DashboardGroupTagMapping
.MapGroupsToTags(groupNames, groupToTag)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
index b0e4c24..28f8358 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardEndpointRouteBuilderExtensions.cs
@@ -107,7 +107,7 @@ public static class DashboardEndpointRouteBuilderExtensions
// SignalR hubs. Authorization is enforced on the hub class via [Authorize], so both
// policies below accept either the dashboard cookie or a HubToken bearer. Snapshot and
// events use HubClientsPolicy; AlarmsHub uses AlarmsPolicy, which additionally requires a
- // real authenticated dashboard role (SEC-40) — see AlarmsHub for why the alarm feed is
+ // real authenticated dashboard role — see AlarmsHub for why the alarm feed is
// gated harder than the session-scoped ones.
endpoints.MapHub("/hubs/snapshot");
endpoints.MapHub("/hubs/alarms");
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
index 5c753e7..e8632aa 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
@@ -177,7 +177,7 @@ public static class DashboardServiceCollectionExtensions
DashboardAuthenticationDefaults.AuthenticationScheme,
DashboardAuthenticationDefaults.HubAuthenticationScheme)
.AddRequirements(DashboardAuthorizationRequirement.AnyDashboardRole));
- // SEC-40. Same two schemes as HubClientsPolicy (the alarm feed has an in-page reader
+ // Same two schemes as HubClientsPolicy (the alarm feed has an in-page reader
// and an external hub reader), but a requirement type DashboardAuthorizationHandler
// does not handle, so neither Authentication:Mode=Disabled nor anonymous localhost
// can satisfy it. Galaxy-wide alarm metadata therefore needs a real dashboard role.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAcl.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAcl.cs
index 5d45c98..7941d64 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAcl.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAcl.cs
@@ -26,7 +26,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
/// (ordinal-ignore-case).
///
///
-/// Where the grant comes from (SEC-41). The grant is re-resolved on every call
+/// Where the grant comes from. The grant is re-resolved on every call
/// from the caller's claims
/// through MxGateway:Dashboard:GroupToTag as it stands in the currently bound options —
/// the same single call
@@ -120,7 +120,7 @@ public sealed class DashboardSessionAcl(
if (groups is not null)
{
- // SEC-41: current options, not the login-time snapshot. MapGroupsToTags returns an
+ // Current options, not the login-time snapshot. MapGroupsToTags returns an
// OrdinalIgnoreCase set, so probing it with the session's tags carries the
// case-insensitive comparison in the same direction the claim scan below does.
IReadOnlySet granted = DashboardGroupTagMapping.MapGroupsToTags(
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
index d05d09c..ac41b38 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
@@ -39,7 +39,7 @@ public sealed class HubTokenService
// revocable. A short lifetime bounds the exposure window of a token captured from a proxy
// or log after logout (the cookie is cleared on logout, but outstanding tokens are not), and
// bounds how long a stale role set survives a role change. It now bounds a stale *tag* grant
- // the same way (SEC-25): the token carries the tags resolved from the caller's LDAP groups at
+ // the same way: the token carries the tags resolved from the caller's LDAP groups at
// mint time, so revoking a GroupToTag entry takes effect for token-authenticated hub
// connections within one lifetime — the natural place the deferred "tokens gain session
// binding" note landed. Five minutes is transparent to clients that re-fetch from /hubs/token
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHub.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHub.cs
index e0e68b2..d48f997 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHub.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHub.cs
@@ -11,9 +11,9 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
///
///
/// The feed is galaxy-wide: the alarm monitor is gateway-central and its messages carry no
-/// session provenance, so the SEC-25 per-session tag ACL that scopes EventsHub has nothing
+/// session provenance, so the per-session tag ACL that scopes EventsHub has nothing
/// to intersect here and is deliberately not applied — every authenticated Viewer sees the whole
-/// subscription expression's alarm metadata. What SEC-40 tightened instead is the entry gate:
+/// subscription expression's alarm metadata. What is tightened instead is the entry gate:
/// rather than the
/// the other hubs use, so the
/// read-only environment bypasses (Authentication:Mode=Disabled, anonymous localhost) no
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHubPublisher.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHubPublisher.cs
index db8368b..c280d73 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHubPublisher.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/AlarmsHubPublisher.cs
@@ -23,7 +23,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
/// StreamAlarms subscribers and the alarms page as well, and none of
/// those audiences is subject to this dashboard-display flag.
///
-/// The broadcast stays deliberately unfiltered (SEC-40). Audience is decided once, at hub
+/// The broadcast stays deliberately unfiltered. Audience is decided once, at hub
/// admission — carries
/// , so only an authenticated caller
/// with a real dashboard role is ever in — and the alarm
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
index 700a279..60c3269 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
@@ -39,8 +39,8 @@ public sealed class EventsHub(
/// The hub-level (HubClientsPolicy)
/// only checks that the caller carries one of the dashboard roles, which by
/// itself would let any Viewer subscribe to any session id they name. The
- /// per-session decision is 's
- /// (SEC-25 / TST-15). The admin bypass is evaluated first, so an
+ /// per-session decision is 's.
+ /// The admin bypass is evaluated first, so an
/// Administrator joins any session id they name; every check below it
/// applies to non-Admin callers only. For those: a Viewer sees a session
/// only when its tags intersect their granted tags, an untagged session
@@ -95,16 +95,12 @@ public sealed class EventsHub(
viewerRegistry.RemoveViewer(Context.ConnectionId, sessionId);
}
- ///
- /// Releases every session subscription the dropped connection held. A browser
- /// tab that closes never calls , so without
- /// this the session would look watched forever and the mirror would keep
- /// cloning and sending events to an empty group.
- ///
- /// The exception that terminated the connection, if any.
- /// A task representing the disconnect handling.
+ ///
public override Task OnDisconnectedAsync(Exception? exception)
{
+ // Release every session subscription the dropped connection held. A browser tab that
+ // closes never calls UnsubscribeSession, so without this the session would look watched
+ // forever and the mirror would keep cloning and sending events to an empty group.
viewerRegistry.ReleaseConnection(Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSessionAcl.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSessionAcl.cs
index 4d62553..3136653 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSessionAcl.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSessionAcl.cs
@@ -4,7 +4,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
///
/// Decides whether a dashboard principal may observe one session's mirrored
-/// event stream (SEC-25 / TST-15). Consulted at every subscribe seam: the
+/// event stream. Consulted at every subscribe seam: the
/// SignalR EventsHub.SubscribeSession join and the in-process
/// IDashboardSessionEventSubscriber.Subscribe used by the
/// session-details page.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs b/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
index e075983..af44744 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/GatewayApplication.cs
@@ -154,8 +154,8 @@ public static class GatewayApplication
// having pushed the ambient identity before the library's galaxy service runs. That
// ordering is still required, but it is no longer trusted silently: with
// Authentication:Mode=ApiKey the provider denies with PermissionDenied and logs the broken
- // invariant when the identity is absent, instead of resolving to the full hierarchy
- // (GWC-38). Under Mode=Disabled identity-absent is expected and stays unscoped.
+ // invariant when the identity is absent, instead of resolving to the full hierarchy.
+ // Under Mode=Disabled identity-absent is expected and stays unscoped.
builder.Services.AddSingleton();
@@ -164,7 +164,7 @@ public static class GatewayApplication
// snapshot. GalaxyRepositoryOptions.SnapshotCachePath is init-only, so the default cannot be
// applied via PostConfigure — supply it as a configuration value (before the bind) when the
// shipped config leaves it blank. It resolves to the per-OS CommonApplicationData location,
- // byte-identical to the removed appsettings literal on Windows (SEC-33).
+ // byte-identical to the removed appsettings literal on Windows.
if (string.IsNullOrWhiteSpace(builder.Configuration["MxGateway:Galaxy:SnapshotCachePath"]))
{
builder.Configuration["MxGateway:Galaxy:SnapshotCachePath"] = Path.Combine(
@@ -175,7 +175,7 @@ public static class GatewayApplication
builder.Services.AddZbGalaxyRepository(builder.Configuration, "MxGateway:Galaxy");
- // Validate that persistence has a valid, host-rooted snapshot path (SEC-33).
+ // Validate that persistence has a valid, host-rooted snapshot path.
builder.Services.AddSingleton<
Microsoft.Extensions.Options.IValidateOptions,
Configuration.GalaxyRepositoryOptionsValidator>();
@@ -224,7 +224,7 @@ public static class GatewayApplication
///
///
/// The location mirrors AuthenticationOptions.SqlitePath so both gateway stores sit
- /// together, and the mechanism is the one SEC-33 already used for
+ /// together, and the mechanism is the same mechanism already used for
/// MxGateway:Galaxy:SnapshotCachePath below — same problem, same fix, same file. It also
/// matches what docs/GatewayConfiguration.md already tells operators to
/// pass to the secret CLI — an absolute default also removes the CLI/gateway divergence
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
index ea1cf48..671e933 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
@@ -116,7 +116,7 @@ public sealed class EventStreamService(
// its `yield return` is what feeds the gRPC writer.
ChannelReader reader = subscriber.Reader;
- // GWC-15: register this subscriber's channel as a live backlog source instead of
+ // Register this subscriber's channel as a live backlog source instead of
// reconciling the queue-depth gauge on every event. The gauge previously read the
// bounded channel's Count (which takes the channel's internal lock) and adjusted the
// metric under its own lock on every streamed event. Now the metric reads Count only
@@ -197,7 +197,7 @@ public sealed class EventStreamService(
}
// The queue-depth gauge is maintained lazily via the backlog registration
- // above (GWC-15): the metric reads this subscriber's channel Count only when
+ // above: the metric reads this subscriber's channel Count only when
// scraped, so there is no per-event gauge bookkeeping on this hot path.
yield return mxEvent;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
index a10699c..1a326d5 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
@@ -35,7 +35,7 @@ public sealed class MxAccessGatewayService(
// The session's owner id and its dashboard-visibility tags both come from the resolved
// API key identity, never from the request: the key is the tenant principal, so a
- // client cannot label its own session with another tenant's tag (SEC-25).
+ // client cannot label its own session with another tenant's tag.
ApiKeyIdentity? owner = identityAccessor.Current;
GatewaySession session = await sessionManager
.OpenSessionAsync(
@@ -130,7 +130,7 @@ public sealed class MxAccessGatewayService(
// Map from the command alone: cloning the whole request only to overwrite its command with
// commandToInvoke deep-cloned the (potentially large) original payload for nothing, since
- // MapCommand reads nothing but the command (GWC-29). The one clone that matters still
+ // MapCommand reads nothing but the command. The one clone that matters still
// happens inside MapCommand, which is what keeps the worker-bound graph unaliased from
// commandToInvoke — the caller still reads it below via TrackCommandReply.
WorkerCommand workerCommand = mapper.MapCommand(commandToInvoke);
@@ -167,7 +167,7 @@ public sealed class MxAccessGatewayService(
.WithCancellation(context.CancellationToken)
.ConfigureAwait(false))
{
- // GWC-06: measure send latency with the allocation-free timestamp API rather
+ // Measure send latency with the allocation-free timestamp API rather
// than allocating a Stopwatch object per event per subscriber on the highest-
// volume gateway path. Stopwatch.GetTimestamp/GetElapsedTime measure the exact
// same wall-clock span the former Stopwatch.StartNew()/.Elapsed did.
@@ -185,15 +185,6 @@ public sealed class MxAccessGatewayService(
}
///
- ///
- /// Surfaces the public AcknowledgeAlarm RPC. Acknowledgement is
- /// session-less: the gateway routes it through the always-on
- /// monitor session. An
- /// alarm_full_reference that parses as a canonical GUID forwards
- /// to AcknowledgeAlarmCommand; a Provider!Group.Tag
- /// reference forwards to AcknowledgeAlarmByNameCommand; anything
- /// else returns an InvalidRequest diagnostic in the reply.
- ///
public override async Task AcknowledgeAlarm(
AcknowledgeAlarmRequest request,
ServerCallContext context)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
index 8ff862b..a035552 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
@@ -35,7 +35,7 @@ public sealed class MxAccessGrpcMapper
///
/// Maps a gRPC MX command to a worker command. Callers that already hold the command — including
/// the constraint pipeline, whose rewritten command is not the one on the request — use this
- /// overload rather than cloning a whole request to carry a single field (GWC-29); nothing outside
+ /// overload rather than cloning a whole request to carry a single field; nothing outside
/// the command is read here.
///
/// Command payload.
@@ -71,7 +71,7 @@ public sealed class MxAccessGrpcMapper
};
}
- // GWC-07 / IPC-05: ownership transfer, not a deep clone — the same rule MapEvent follows,
+ // ownership transfer, not a deep clone — the same rule MapEvent follows,
// applied to the other (and larger, on bulk reads) hot-path message. The enclosing
// WorkerCommandReply is parsed fresh from a single pipe frame in WorkerClient's read loop
// and is single-consumer by construction: CompleteCommand's TryRemove hands it to exactly
@@ -93,10 +93,10 @@ public sealed class MxAccessGrpcMapper
{
ArgumentNullException.ThrowIfNull(workerEvent);
- // GWC-07 / IPC-05: ownership transfer, not a deep clone. The enclosing WorkerEvent is
+ // ownership transfer, not a deep clone. The enclosing WorkerEvent is
// parsed fresh from a single pipe frame in WorkerClient's read loop and is discarded
// immediately after this mapping — the SessionEventDistributor pump is its single
- // consumer (GWC-01 claims the worker event channel as single-reader), so nothing else
+ // consumer (it claims the worker event channel as single-reader), so nothing else
// aliases or mutates workerEvent.Event. We therefore move the inner MxEvent into the
// outbound graph instead of cloning it. Downstream the pump fans this one MxEvent to
// every subscriber and retains it in the replay ring, but that sharing is READ-ONLY
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs b/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
index 3f1a7dc..c806121 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
@@ -35,7 +35,7 @@ public sealed class GatewayMetrics : IDisposable
private readonly ConcurrentDictionary _eventsBySession = new(StringComparer.Ordinal);
private readonly Dictionary _retryAttemptsByArea = new(StringComparer.OrdinalIgnoreCase);
- // GWC-15: live backlog sources for the gRPC event-stream queue-depth gauge. Each active
+ // live backlog sources for the gRPC event-stream queue-depth gauge. Each active
// StreamEvents subscriber registers a delegate returning its channel's current backlog; the
// gauge sums them ONLY when scraped or projected (GetGrpcEventStreamQueueDepth), so nothing is
// read on the per-event streaming hot path. Concurrent because subscribers register/unregister
@@ -43,7 +43,7 @@ public sealed class GatewayMetrics : IDisposable
private readonly ConcurrentDictionary> _eventStreamBacklogSources = new();
private long _nextEventStreamBacklogSourceId;
- // PERF-02: the same pull model for the worker event queue depth. It replaces a pushed scalar that
+ // the same pull model for the worker event queue depth. It replaces a pushed scalar that
// every WorkerClient wrote twice per event (staged, consumed) under _syncRoot — a process-wide
// lock on the hottest path, and last-writer-wins across sessions, so the gauge reported one
// arbitrary session's backlog instead of the gateway's. Each client registers a source returning
@@ -210,7 +210,7 @@ public sealed class GatewayMetrics : IDisposable
/// Name of the command method.
public void CommandStarted(string method)
{
- // PERF-02: the three command counters run two-to-three times per gRPC call, so they use
+ // the three command counters run two-to-three times per gRPC call, so they use
// Interlocked rather than _syncRoot — the same idiom as EventReceived. Nothing here needs a
// consistent multi-field view; GetSnapshot reads each with Interlocked.Read.
Interlocked.Increment(ref _commandsStarted);
@@ -281,7 +281,7 @@ public sealed class GatewayMetrics : IDisposable
/// Registers a live depth source for the worker event queue-depth gauge and returns a handle
/// that removes it when disposed. Each WorkerClient registers once and reports its own
/// undelivered (staged + queued) event count, so the gauge is the gateway-wide sum instead of
- /// the last value any one session happened to push (PERF-02).
+ /// the last value any one session happened to push.
///
///
/// Returns this worker client's current undelivered event count. Invoked only at collection
@@ -303,7 +303,7 @@ public sealed class GatewayMetrics : IDisposable
/// returns a handle that removes it when disposed. The gauge sums every registered
/// source's current value on demand (when scraped or via ),
/// rather than tracking a pushed running total, so the streaming hot path does no
- /// per-event gauge bookkeeping (GWC-15).
+ /// per-event gauge bookkeeping.
///
///
/// Returns this subscriber's current channel backlog. Invoked only at collection time;
@@ -351,7 +351,7 @@ public sealed class GatewayMetrics : IDisposable
{
// Tagged by stage only. Neither the key id nor the peer address may become a tag: key ids
// are credential material and peer addresses are unbounded cardinality, and /metrics is not
- // authenticated (open SEC-14), so anything tagged here is world-readable.
+ // authenticated, so anything tagged here is world-readable.
_authThrottledCounter.Add(1, new KeyValuePair("stage", stage));
}
@@ -460,7 +460,7 @@ public sealed class GatewayMetrics : IDisposable
{
// Compute the live queue depths outside _syncRoot: the sources are the subscriber channels'
// Count (their own locks) and the worker clients' interlocked counters, neither of which may
- // run under this lock. GWC-15, PERF-02.
+ // run under this lock.
int workerEventQueueDepth = GetWorkerEventQueueDepth();
int grpcEventStreamQueueDepth = GetGrpcEventStreamQueueDepth();
lock (_syncRoot)
@@ -521,7 +521,7 @@ public sealed class GatewayMetrics : IDisposable
}
}
- // Sums the undelivered event backlog across every live worker client (PERF-02).
+ // Sums the undelivered event backlog across every live worker client.
private int GetWorkerEventQueueDepth() => SumSources(_workerEventQueueDepthSources);
// Sums the live backlog across every registered event-stream subscriber.
@@ -571,6 +571,7 @@ public sealed class GatewayMetrics : IDisposable
{
private int _disposed;
+ /// Removes the source from its gauge; subsequent calls are no-ops.
public void Dispose()
{
if (Interlocked.Exchange(ref _disposed, 1) == 0)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/AuditDrainService.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/AuditDrainService.cs
index 0d9570f..5bba303 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/AuditDrainService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/AuditDrainService.cs
@@ -39,12 +39,7 @@ public sealed class AuditDrainService(
/// Upper bound on how long shutdown waits for the remaining buffered events.
private static readonly TimeSpan ShutdownDrainCap = TimeSpan.FromSeconds(2);
- ///
- /// Bootstraps the audit table, runs one retention sweep, then attaches the drain so the
- /// writer switches from synchronous write-through to enqueueing.
- ///
- /// Token to observe for cancellation.
- /// A task that represents the asynchronous operation.
+ ///
public override async Task StartAsync(CancellationToken cancellationToken)
{
try
@@ -64,12 +59,7 @@ public sealed class AuditDrainService(
await base.StartAsync(cancellationToken).ConfigureAwait(false);
}
- ///
- /// Detaches the drain (so late writes go straight to the sink) and gives the buffered
- /// events a bounded window to reach the store.
- ///
- /// Token to observe for cancellation.
- /// A task that represents the asynchronous operation.
+ ///
public override async Task StopAsync(CancellationToken cancellationToken)
{
writer.DetachDrain();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
index 67f4bb8..11170ab 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
@@ -87,11 +87,9 @@ public sealed class SqliteCanonicalAuditStore(
}
///
- ///
- /// One connection, one transaction and one prepared command for the whole batch: the drain
- /// pays a single commit for up to events rather
- /// than one round-trip per event.
- ///
+ // One connection, one transaction and one prepared command for the whole batch: the drain
+ // pays a single commit for up to AuditDrainService.MaxBatchSize events rather
+ // than one round-trip per event.
public async Task InsertBatchAsync(IReadOnlyList auditEvents, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(auditEvents);
@@ -148,17 +146,15 @@ public sealed class SqliteCanonicalAuditStore(
}
///
- ///
- /// The comparison goes through SQLite's datetime() rather than comparing the stored
- /// ISO-8601 text directly. Text comparison is only correct while every row is UTC-normalized
- /// ISO-8601 — which guarantees for rows written through
- /// this store, but not for rows that entered the table any other way (a repair script, an
- /// older schema, a future producer). On a mixed-format column a text comparison silently
- /// deletes live audit: 2026-05-17T09:00:00-05:00 is two hours AFTER a
- /// 2026-05-17T12:00:00+00:00 cutoff yet sorts before it. Comparing instants is correct
- /// regardless of how the text got there, and anything datetime() cannot parse yields
- /// NULL and is therefore never deleted — audit that cannot be dated is kept, not swept.
- ///
+ // The comparison goes through SQLite's datetime() rather than comparing the stored
+ // ISO-8601 text directly. Text comparison is only correct while every row is UTC-normalized
+ // ISO-8601 — which AuditEvent.OccurredAtUtc guarantees for rows written through
+ // this store, but not for rows that entered the table any other way (a repair script, an
+ // older schema, a future producer). On a mixed-format column a text comparison silently
+ // deletes live audit: 2026-05-17T09:00:00-05:00 is two hours AFTER a
+ // 2026-05-17T12:00:00+00:00 cutoff yet sorts before it. Comparing instants is correct
+ // regardless of how the text got there, and anything datetime() cannot parse yields
+ // NULL and is therefore never deleted — audit that cannot be dated is kept, not swept.
public async Task DeleteOlderThanAsync(DateTimeOffset cutoffUtc, CancellationToken cancellationToken)
{
await using SqliteConnection connection =
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraints.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraints.cs
index 1cf8418..e01265a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraints.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraints.cs
@@ -13,7 +13,7 @@ public sealed record ApiKeyConstraints(
private readonly IReadOnlyList _dashboardTags = Array.Empty();
///
- /// Gets the dashboard event-visibility tags granted to this key (SEC-25).
+ /// Gets the dashboard event-visibility tags granted to this key.
///
///
///
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 4dcbb6f..2e66215 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/CachingApiKeyVerifier.cs
@@ -44,7 +44,7 @@ public interface IApiKeyCacheInvalidator
/// evicting so an in-flight verification that started under the old generation discards its own
/// repopulation (set-then-recheck in VerifyAsync) — making the "gateway-initiated mutations
/// take effect immediately" contract true even against a verify that was already in the inner library
-/// when the revoke landed (SEC-34 window 3).
+/// when the revoke landed.
///
///
/// The short TTL is the backstop for two remaining bounded-staleness windows. (1) Out-of-band
@@ -141,7 +141,7 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
}
// Caches a successful verification unless the key was invalidated while the inner verify was in
- // flight (SEC-34 window 3, detected via the generation snapshot). The entry lifetime stays the
+ // flight (detected via the generation snapshot). The entry lifetime stays the
// TTL: the library verification identity carries no expiry, so the cache cannot cap at the key's
// ExpiresUtc — that window remains TTL-bounded and documented in the class remarks.
private void TryCacheSuccess(
@@ -202,11 +202,14 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
? generation
: 0;
- // Parses the key id out of a "Bearer mxgw__" header without any store access —
- // the same split the authorization interceptor does. Returns null for a header this cache cannot
- // attribute to a key id (in which case the generation race-guard is simply not applied).
- //
- // Correctness of the SEC-34 generation guard rests on parts[1] being the FULL key id: the '_'
+ ///
+ /// Parses the key id out of a Bearer mxgw_<keyId>_<secret> header without any store access,
+ /// using the same split the authorization interceptor does.
+ ///
+ /// The raw authorization header value, or .
+ /// The full key id, or for a header this cache cannot attribute to a key id (the generation race-guard is then not applied).
+ // Implementation note:
+ // Correctness of the generation guard rests on parts[1] being the FULL key id: the '_'
// split would truncate a key id that itself contained '_', silently disarming the guard for that
// key. This is safe because '_' is the token's field delimiter and both — and the only — key
// creation paths in the gateway forbid it: ApiKeyAdminCommandLineParser.IsValidKeyId and
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 6269f66..7fbc887 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ApiKeyFailureLimiter.cs
@@ -19,7 +19,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;
/// source-rotating sprayer that never trips any single partition.
///
///
-/// An over-limit state is a valve, not a wall (SEC-31): at most one request per
+/// An over-limit state is a valve, not a wall: at most one request per
/// is admitted through to the real
/// verifier, and a successful verification resets both layers. The reset path therefore stays
/// reachable while throttled — the earlier design keyed solely on the attacker-supplied key id and
@@ -29,8 +29,8 @@ namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;
/// The tracked partition set is a bounded LRU ().
/// Because only a validly shaped token mints a key-id partition and each transport peer may mint at
/// most of them (the peer-layer overflow collapses onto that
-/// address's fallback partition), the map bounds memory and resists a junk-token flush
-/// (SEC-32). A validly shaped presented key id still feeds its cross-peer aggregate when its peer
+/// address's fallback partition), the map bounds memory and resists a junk-token flush.
+/// A validly shaped presented key id still feeds its cross-peer aggregate when its peer
/// layer uses the fallback, so exhausting the per-peer cap cannot bypass distributed-spray
/// protection; the aggregate map remains bounded by the same capped eviction policy:
/// eviction prefers fully expired windows, never removes an over-limit partition below a transient
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayBrowseScopeProvider.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayBrowseScopeProvider.cs
index 94186bd..038aed6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayBrowseScopeProvider.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayBrowseScopeProvider.cs
@@ -8,7 +8,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;
/// Scopes Galaxy browse results to the calling API key's BrowseSubtrees constraint.
///
-/// Distinguishes two states the pre-GWC-38 code collapsed into one: "authenticated, no
+/// Distinguishes two states the earlier code collapsed into one: "authenticated, no
/// BrowseSubtrees constraint" (legitimately unscoped — the common case) and "no ambient identity
/// at all" (the interceptor-ordering invariant below is broken). The second used to resolve to the
/// full hierarchy silently, which made a scoping bypass invisible; it now denies loudly.
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 feaeaaa..345ed4d 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayGrpcAuthorizationInterceptor.cs
@@ -140,12 +140,17 @@ public sealed class GatewayGrpcAuthorizationInterceptor(
// Token shape mxgw__: the key id is the second underscore-delimited segment (the
// secret may itself contain underscores, which does not affect the key id). The shape is checked
// before a key-id partition is minted so a spray of invented tokens cannot mint one tracked
- // partition each and flush the limiter's bounded map (SEC-32). Anything that fails the check
+ // partition each and flush the limiter's bounded map. Anything that fails the check
// falls back to the sender's transport-peer partition.
//
// Internal rather than private so the parse rules can be pinned directly by test; the shape
- // check is a security boundary (SEC-32) and is worth asserting without routing every case
+ // check is a security boundary and is worth asserting without routing every case
// through a full RPC.
+ ///
+ /// Extracts the API key id from a bearer authorization header.
+ ///
+ /// The raw authorization header value, or .
+ /// The key id when the header has the mxgw_<keyId>_<secret> shape; otherwise .
internal static string? TryResolveKeyId(string? authorizationHeader)
{
if (string.IsNullOrWhiteSpace(authorizationHeader))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
index 5331a81..1de4054 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
@@ -39,7 +39,7 @@ public sealed class GatewaySession
private bool _everHadEventSubscriber;
private SessionEventDistributor? _eventDistributor;
private bool _eventDistributorStarted;
- // GWC-34: set under _syncRoot when DisposeAsync nulls _eventDistributor, making the
+ // Set under _syncRoot when DisposeAsync nulls _eventDistributor, making the
// "one distributor per session, never reset" lifecycle symmetric at both ends. Without it
// EnsureDistributorCreated reads the null as "not created yet" and builds a REPLACEMENT
// distributor after teardown — one whose pump can never start (_eventDistributorStarted is a
@@ -163,7 +163,7 @@ public sealed class GatewaySession
/// is unit-testable.
///
///
- /// Dashboard event-visibility tags inherited from the owning API key (SEC-25). Copied into
+ /// Dashboard event-visibility tags inherited from the owning API key. Copied into
/// the immutable set; or empty means untagged.
/// The tags come from the owner key, never from the client's wire request, so a client
/// cannot label its own session with another tenant's tag.
@@ -265,8 +265,8 @@ public sealed class GatewaySession
public string? OwnerKeyId { get; }
///
- /// Gets the dashboard event-visibility tags this session inherited from its owning API key
- /// (SEC-25). An empty set means untagged.
+ /// Gets the dashboard event-visibility tags this session inherited from its owning API key.
+ /// An empty set means untagged.
///
///
/// Immutable for the session's life — assigned once at construction from the owner key's
@@ -541,7 +541,7 @@ public sealed class GatewaySession
// concurrent callers (e.g. MarkReady's dashboard mirror and a racing first
// AttachEventSubscriber) agree on a single distributor and a single start.
//
- // GWC-34: after DisposeAsync the null distributor means "gone", not "not built yet", so this
+ // After DisposeAsync the null distributor means "gone", not "not built yet", so this
// throws instead of constructing a replacement nothing will ever pump. The attach paths already
// roll back and surface the exception, which is the same SessionNotReady the readiness gates
// raise — a caller that loses the race to teardown now fails immediately instead of hanging.
@@ -610,7 +610,7 @@ public sealed class GatewaySession
///
public IEventSubscriberLease AttachInternalEventSubscriber()
{
- // Readiness gate, mirroring AttachEventSubscriber (GWC-27). It must run BEFORE
+ // Readiness gate, mirroring AttachEventSubscriber. It must run BEFORE
// EnsureDistributorCreated: a premature attach would construct the distributor and start
// its pump against a not-yet-Ready worker, the pump source would throw SessionNotReady,
// PumpAsync would complete every subscriber with that error and latch _completed, and
@@ -694,7 +694,7 @@ public sealed class GatewaySession
// These three calls are OUTSIDE _syncRoot to avoid holding it across
// EnsureDistributorCreated's own lock and StartAsync's Task.Run.
//
- // GWC-34: the state check above can be overtaken by a close+dispose before we get here, and
+ // The state check above can be overtaken by a close+dispose before we get here, and
// EnsureDistributorCreated now says so instead of building an orphan distributor. The
// dashboard mirror is a best-effort observability attachment on a session that is already
// gone, so it is abandoned here rather than propagated out of MarkReady — the mirror-started
@@ -1918,7 +1918,7 @@ public sealed class GatewaySession
{
distributor = _eventDistributor;
_eventDistributor = null;
- // GWC-34: latch the null-out so EnsureDistributorCreated cannot read it as
+ // Latch the null-out so EnsureDistributorCreated cannot read it as
// "not created yet" and hand a racing attach a distributor that will never pump.
_eventDistributorDisposed = true;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
index 0470f5e..29dd222 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
@@ -19,7 +19,7 @@ public interface ISessionManager
///
/// Opens a new gateway session, stamping the owning API key's dashboard event-visibility
- /// tags onto it (SEC-25).
+ /// tags onto it.
///
/// Request payload.
/// Client identity string.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionEventDistributor.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionEventDistributor.cs
index 04212ab..72050a6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionEventDistributor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionEventDistributor.cs
@@ -520,7 +520,7 @@ public sealed class SessionEventDistributor : IAsyncDisposable
{
gap = _anyEventSeen && afterSequence < _highestSequenceSeen;
- // GWC-25: nothing is retained, but a gapped client still needs a usable resume
+ // Nothing is retained, but a gapped client still needs a usable resume
// anchor. The documented client formula is
// after_worker_sequence = oldest_available_sequence - 1, so reporting 0 here made
// an unsigned client compute ulong.MaxValue: the follow-up resume then replayed
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
index f4cc712..0ded52e 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
@@ -532,7 +532,7 @@ public sealed class SessionManager : ISessionManager
// The short prefix and bare guid keep the pipe's Unix-domain-socket path
// (TMPDIR + "CoreFxPipe_" + name) inside the 104-byte sun_path limit on
// macOS, whose default per-user TMPDIR is ~49 chars; the gateway PID keeps
- // the name collision-free across gateway restarts (NEXT-01).
+ // the name collision-free across gateway restarts.
string pipeName = $"mxgw-{Environment.ProcessId}-{sessionUid}";
string nonce = CreateNonce();
DateTimeOffset openedAt = _timeProvider.GetUtcNow();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
index a300af8..873dcdd 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
@@ -28,7 +28,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. Bounded at 2 × EventChannelCapacity
- // (GWC-24): an unbounded staging channel let a consumer that drains slower than the worker
+ // because an unbounded staging channel let a consumer that drains slower than the worker
// produces grow gateway memory without limit and without a fault, because each individual timed
// write into _events still completed inside EventChannelFullModeTimeout. A rejected TryWrite here
// is the sustained-slow-drain signal and faults the client immediately (ProtocolViolation), which
@@ -41,7 +41,7 @@ public sealed class WorkerClient : IWorkerClient
private readonly SemaphoreSlim _pendingCommandSlots;
private readonly CancellationTokenSource _stopCts = new();
- // PERF-02: this client's contribution to the gateway-wide worker queue-depth gauge. Registered
+ // this client's contribution to the gateway-wide worker queue-depth gauge. Registered
// once here and read only when the gauge is scraped, so staging and consuming an event cost an
// Interlocked on _eventQueueDepth and nothing else — previously each of those two hot-path steps
// called into GatewayMetrics and took its process-wide lock. Null when metrics are disabled.
@@ -233,13 +233,13 @@ public sealed class WorkerClient : IWorkerClient
// size the caller controls; checking here keeps a MessageTooLarge in the write loop a
// genuine desync signal.
//
- // PERF-07: this size cannot be handed to WorkerFrameWriter to spare its own
+ // this size cannot be handed to WorkerFrameWriter to spare its own
// CalculateSize. WriteLoopAsync stamps envelope.Sequence immediately before the write
- // (GWC-28), and a non-zero varint field grows the encoding — so the number computed here
+ // and a non-zero varint field grows the encoding — so the number computed here
// is a lower bound on the frame the writer actually emits, never the frame length. Passing
// it as a knownSize would under-length the prefix and desync the worker's framing.
//
- // IPC-39: being a lower bound is conservative for the knownSize question but the wrong
+ // being a lower bound is conservative for the knownSize question but the wrong
// direction for this pre-check, which must not admit an envelope the writer will then
// reject with a session-fatal MessageTooLarge. Compare against the frame maximum less the
// MaxSequenceEncodingBytes the stamp can add, so every envelope this check accepts still
@@ -257,7 +257,7 @@ public sealed class WorkerClient : IWorkerClient
await EnqueueAsync(commandEnvelope, cancellationToken).ConfigureAwait(false);
- // PERF-07: one pooled timer instead of a linked CTS + Task.Delay + WhenAny per command.
+ // one pooled timer instead of a linked CTS + Task.Delay + WhenAny per command.
// Task.WaitAsync arms a TimerQueueTimer on the shared timer queue and cancels it when the
// reply lands, so the steady-state cost of a command that replies in time is a single
// continuation — the old shape allocated a linked CancellationTokenSource, its
@@ -354,7 +354,7 @@ public sealed class WorkerClient : IWorkerClient
{
await foreach (WorkerEvent workerEvent in _events.Reader.ReadAllAsync(cancellationToken).ConfigureAwait(false))
{
- // No metrics call on the hot path: the gauge pulls _eventQueueDepth when scraped (PERF-02).
+ // No metrics call on the hot path: the gauge pulls _eventQueueDepth when scraped.
Interlocked.Decrement(ref _eventQueueDepth);
yield return workerEvent;
}
@@ -420,7 +420,7 @@ public sealed class WorkerClient : IWorkerClient
/// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
- // GWC-32: disposal is the third channel-completing path, and it must enter a terminal state
+ // disposal is the third channel-completing path, and it must enter a terminal state
// like the other two (MarkClosed, SetFaulted) BEFORE the channels are completed. Otherwise a
// client disposed while still Ready keeps reporting IsTerminalState() == false, and a read
// loop already inside DispatchEnvelope (the _stopCts.Cancel below only interrupts the NEXT
@@ -490,7 +490,7 @@ public sealed class WorkerClient : IWorkerClient
/// Worst-case number of bytes 's sequence stamp adds to an
/// envelope that was sized before it: one tag byte plus a ten-byte varint, the maximum
/// encoding of a 64-bit protobuf field. The CommandTooLarge pre-check subtracts this
- /// from the negotiated frame maximum (IPC-39) because it measures the envelope while
+ /// from the negotiated frame maximum because it measures the envelope while
/// Sequence is still 0 — an unset field costs nothing to encode, so the measured size
/// is a lower bound on the frame the writer emits, and without the allowance an envelope in
/// the last eleven bytes of the range would pass the pre-check and then fault the session on
@@ -505,12 +505,12 @@ public sealed class WorkerClient : IWorkerClient
{
await foreach (WorkerEnvelope envelope in _outboundEnvelopes.Reader.ReadAllAsync(_stopCts.Token).ConfigureAwait(false))
{
- // GWC-28: stamp the sequence at the point of writing, not when the envelope is built.
+ // stamp the sequence at the point of writing, not when the envelope is built.
// Stamping at construction let two concurrent InvokeAsync callers take 1 and 2 and then
// enqueue in the order 2, 1 — non-monotonic on the wire, breaking gateway.md's
// "monotonic per sender" contract. This loop is the channel's single consumer
// (SingleReader = true), so wire order and stamp order are the same thing here and
- // _nextSequence needs no interlocking. Mirrors the worker's WRK-04 fix.
+ // _nextSequence needs no interlocking. Mirrors the worker's equivalent fix.
envelope.Sequence = unchecked(++_nextSequence);
await _writer.WriteAsync(envelope, _stopCts.Token).ConfigureAwait(false);
}
@@ -678,11 +678,11 @@ public sealed class WorkerClient : IWorkerClient
/// faults regardless of how backed up the event path is. It returns false in two cases:
/// the staging channel has been completed by one of the three completing paths —
/// , or , each of
- /// which enters a terminal state before completing the channels (GWC-32), so the event is
+ /// which enters a terminal state before completing the channels, so the event is
/// safely dropped because the client is already terminal — or the channel is full at its
/// 2 × bound. The latter means the
/// consumer has been draining slower than the worker produces for the whole time it took the
- /// worker to emit that many further events, so the client is faulted immediately (GWC-24) —
+ /// worker to emit that many further events, so the client is faulted immediately —
/// is non-blocking, so the read loop still never awaits here. The
/// complementary full-stall case (a consumer that stops entirely) is caught earlier by the
/// timed write in .
@@ -753,7 +753,7 @@ public sealed class WorkerClient : IWorkerClient
/// the actionable fix (attach StreamEvents or raise
/// MxGateway:Events:QueueCapacity). This is the full-stall half of
/// the backpressure policy; a consumer that merely drains too slowly is
- /// caught by the staging bound in (GWC-24).
+ /// caught by the staging bound in .
/// Queue depth is not counted here — the event was already counted when it
/// was staged, so moving it between the two channels changes nothing.
///
@@ -851,7 +851,7 @@ public sealed class WorkerClient : IWorkerClient
///
/// Fails the pending command for a caller whose own token fired — a client deadline shorter
/// than the gateway's command timeout, or a disconnect that cancelled the RPC's token — and
- /// forwards a WorkerCancel for the correlation the caller has abandoned (IPC-34).
+ /// forwards a WorkerCancel for the correlation the caller has abandoned.
///
/// Caller cancellation is the common abandonment path, not the rare one, and it leaves the
/// worker in exactly the state the timeout arm's cancel exists for: the correlation is still
@@ -982,7 +982,7 @@ public sealed class WorkerClient : IWorkerClient
{
WorkerEnvelope envelope = await _reader.ReadAsync(cancellationToken).ConfigureAwait(false);
- // IPC-35: a fault frame during the handshake is the worker reporting a structured startup
+ // a fault frame during the handshake is the worker reporting a structured startup
// failure — most often MXAccess COM creation (not installed, not registered, access denied)
// — not a protocol problem. Flattening it to ProtocolViolation discarded the category and
// diagnostic exactly where they matter most: first session open on a freshly deployed host,
@@ -1303,7 +1303,7 @@ public sealed class WorkerClient : IWorkerClient
string correlationId,
WorkerCommand command)
{
- // IPC-05: no second clone. MxAccessGrpcMapper.MapCommand already deep-cloned the command
+ // no second clone. MxAccessGrpcMapper.MapCommand already deep-cloned the command
// out of the caller-owned gRPC MxCommandRequest, so this WorkerCommand is a fresh graph
// owned by the invoke pipeline and referenced by no other consumer. The envelope is built
// and owned entirely inside WorkerClient and the command is not touched again after this
@@ -1340,7 +1340,7 @@ public sealed class WorkerClient : IWorkerClient
{
// Sequence is deliberately left unset here: WriteLoopAsync stamps it immediately before the
// frame goes out, so the numbers are monotonic in wire order however the callers interleave
- // between construction and enqueue (GWC-28, mirroring the worker's WRK-04 fix).
+ // between construction and enqueue (mirroring the worker's fix).
WorkerEnvelope envelope = new()
{
ProtocolVersion = _connection.FrameOptions.ProtocolVersion,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameReader.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameReader.cs
index 1c79432..70964bc 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameReader.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameReader.cs
@@ -19,7 +19,7 @@ public sealed class WorkerFrameReader
private readonly WorkerFrameProtocolOptions _options;
private readonly Stream _stream;
- // Reused across frames rather than allocated per read (GWC-30). Safe because ReadAsync is
+ // Reused across frames rather than allocated per read. Safe because ReadAsync is
// single-consumer by construction; the prefix is fully overwritten by every read.
private readonly byte[] _lengthPrefix = new byte[sizeof(uint)];
@@ -61,8 +61,8 @@ public sealed class WorkerFrameReader
}
// Rent the payload buffer from the shared pool rather than allocating a fresh byte[] per
- // frame; large event frames near the cap would otherwise allocate an LOH buffer each time
- // (IPC-14). ParseFrom copies whatever it needs into the parsed message, so the rented buffer
+ // frame; large event frames near the cap would otherwise allocate an LOH buffer each time.
+ // ParseFrom copies whatever it needs into the parsed message, so the rented buffer
// can be returned as soon as parsing completes without the envelope aliasing it. The rented
// buffer may be larger than requested, so the read and parse are bounded to length.
int length = checked((int)payloadLength);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
index 124e58f..a7f1cf4 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
@@ -57,7 +57,7 @@ public sealed class WorkerFrameWriter
// Serialize once into a single pooled buffer that carries the 4-byte little-endian length
// prefix followed by the payload, then issue one stream write. This avoids a second
// serialization pass (ToByteArray re-runs CalculateSize), a separate prefix array and its
- // own write, and any per-frame heap allocation (GWC-08, IPC-13). The rented buffer may be
+ // own write, and any per-frame heap allocation. The rented buffer may be
// larger than requested, so only the first frameLength bytes are ever written.
int frameLength = sizeof(uint) + payloadLength;
byte[] frame = ArrayPool.Shared.Rent(frameLength);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/AlarmWatchListResolverTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/AlarmWatchListResolverTests.cs
index 62f8809..6e89c67 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/AlarmWatchListResolverTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/AlarmWatchListResolverTests.cs
@@ -19,7 +19,7 @@ public sealed class AlarmWatchListResolverTests
///
/// Resolves and projects to the target list. These cases assert composition rules, which
/// live in ; the discovery-provenance fields
- /// the resolution also carries (GWC-37) are asserted by their own cases below.
+ /// the resolution also carries are asserted by their own cases below.
///
/// The resolver under test.
/// Alarm options to resolve against.
@@ -259,7 +259,7 @@ public sealed class AlarmWatchListResolverTests
}
///
- /// GWC-37: swallowing the discovery failure is right for the resolver but leaves the
+ /// Swallowing the discovery failure is right for the resolver but leaves the
/// caller unable to tell "discovery produced nothing" from "nothing was configured", which
/// is why the empty watch-list could sit unnoticed for a monitor's whole life. The
/// resolution therefore reports whether discovery was attempted, whether it failed, and
@@ -284,7 +284,7 @@ public sealed class AlarmWatchListResolverTests
///
/// The complement of the case above: discovery disabled is not discovery failed. An empty
/// watch-list here means the deployment did not ask for subtag coverage, which the monitor
- /// must not report as a degraded standby (GWC-37).
+ /// must not report as a degraded standby.
///
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorAttachOrderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorAttachOrderTests.cs
index f319ae2..fee7c4a 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorAttachOrderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorAttachOrderTests.cs
@@ -13,7 +13,7 @@ using ZB.MOM.WW.MxGateway.Tests.TestSupport;
namespace ZB.MOM.WW.MxGateway.Tests.Alarms;
///
-/// GWC-26 regression tests for the alarm monitor's startup ordering. Unlike the
+/// Regression tests for the alarm monitor's startup ordering. Unlike the
/// sibling alarm-monitor tests, the session manager here hands the monitor a REAL
/// that is driven to Ready with a dashboard mirror, so the
/// distributor pump is already running when the monitor attaches — the production
@@ -156,7 +156,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
}
///
- /// GWC-35: an acknowledged cached alarm followed by an active snapshot with a newer
+ /// An acknowledged cached alarm followed by an active snapshot with a newer
/// original-raise timestamp is a new alarm instance, not an acknowledgement reversal. The
/// reconcile repair must broadcast a Raise carrying the incoming instance identity.
///
@@ -216,7 +216,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
}
///
- /// NEXT-03. A reconcile Raise repair applied while the matching live Raise is still
+ /// A reconcile Raise repair applied while the matching live Raise is still
/// buffered must not double-broadcast: the live transition carrying the same worker
/// timestamp and resulting state the cache already holds is a duplicate and is suppressed.
///
@@ -275,7 +275,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
}
///
- /// NEXT-03, the Clear leg. A reconcile Clear repair removes the cache entry, so the
+ /// The Clear leg of the dedup. A reconcile Clear repair removes the cache entry, so the
/// buffered live Clear is deduped through the tombstone keyed on the instance's original
/// raise timestamp — and a genuinely new raise/clear cycle is never swallowed.
///
@@ -490,7 +490,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
SourceProvider = AlarmProviderMode.Alarmmgr,
};
- // Snapshot carrying the worker-side identity markers the NEXT-03 dedup compares on.
+ // Snapshot carrying the worker-side identity markers the dedup compares on.
private static ActiveAlarmSnapshot SnapshotAt(
AlarmConditionState state,
Timestamp lastTransition,
@@ -502,7 +502,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
return snapshot;
}
- // Live transition with explicit worker timestamps, for driving the NEXT-03 dedup.
+ // Live transition with explicit worker timestamps, for driving the dedup.
private static MxEvent TransitionAt(
ulong sequence,
AlarmTransitionKind kind,
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorProviderModeTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorProviderModeTests.cs
index 6e054e0..643d2b6 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorProviderModeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Alarms/GatewayAlarmMonitorProviderModeTests.cs
@@ -624,7 +624,7 @@ public sealed class GatewayAlarmMonitorProviderModeTests
}
///
- /// GWC-37: a Galaxy Repository outage at startup used to leave one LogWarning and an
+ /// A Galaxy Repository outage at startup used to leave one LogWarning and an
/// empty subtag watch-list that stayed empty for the monitor's whole life — invisible until
/// a failover found the standby covering nothing. The condition is now a standing verdict
/// on the provider status, so it reaches the alarm feed, the dashboard badge and every
@@ -661,7 +661,7 @@ public sealed class GatewayAlarmMonitorProviderModeTests
}
///
- /// GWC-37: the failover edge is the moment the watch-list stops being theoretical, so the
+ /// The failover edge is the moment the watch-list stops being theoretical, so the
/// monitor re-resolves it there, hot-swaps the recovered list through
/// UpdateAlarmWatchList, and publishes the acknowledged verdict on the same status
/// frame the failover produces. The update must precede the status frame so the frame never
@@ -748,6 +748,7 @@ public sealed class GatewayAlarmMonitorProviderModeTests
}
/// Periodic reconciliation applies a recovered watch list once and suppresses an unchanged resolution on the next cadence.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchListRefresh_PeriodicRecovery_SendsExactlyOneMaterialUpdate()
{
@@ -774,6 +775,7 @@ public sealed class GatewayAlarmMonitorProviderModeTests
}
/// A rejected refresh keeps the old fingerprint and degraded verdict so the same material change is retried.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchListRefresh_WorkerRejects_RetainsFingerprintAndRetriesSameTargets()
{
@@ -937,7 +939,7 @@ public sealed class GatewayAlarmMonitorProviderModeTests
/// that hands out a scripted sequence of
/// resolutions — one per call, the last repeating — and counts the calls, so a test can
/// drive "discovery was down at subscribe and back up by the failover" and assert that the
- /// second resolution happened at all (GWC-37).
+ /// second resolution happened at all.
///
/// Resolutions to return, in call order.
private sealed class ScriptedWatchListResolver(params AlarmWatchListResolution[] script) : IAlarmWatchListResolver
@@ -997,6 +999,8 @@ public sealed class GatewayAlarmMonitorProviderModeTests
_events.Writer.TryWrite(new WorkerEvent { Event = mxEvent });
/// Pushes a provider-mode change onto the worker event stream.
+ /// The provider mode being reported.
+ /// The reason for the mode change.
public void EmitModeChange(AlarmProviderMode mode, string reason) => EmitEvent(new MxEvent
{
OnAlarmProviderModeChanged = new OnAlarmProviderModeChangedEvent
@@ -1008,6 +1012,9 @@ public sealed class GatewayAlarmMonitorProviderModeTests
});
/// Waits until at least the requested number of update commands have arrived.
+ /// The minimum number of update commands to wait for.
+ /// The maximum time to wait.
+ /// A task that represents the asynchronous operation.
public async Task WaitForUpdateCountAsync(int count, TimeSpan timeout)
{
await WaitUntilAsync(() => UpdateCommands.Count >= count, timeout);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GalaxyRepositoryOptionsValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GalaxyRepositoryOptionsValidatorTests.cs
index d1d4619..7fc3a1e 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GalaxyRepositoryOptionsValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GalaxyRepositoryOptionsValidatorTests.cs
@@ -8,7 +8,7 @@ using ZB.MOM.WW.MxGateway.Server.Configuration;
namespace ZB.MOM.WW.MxGateway.Tests.Configuration;
///
-/// Gateway-owned validation of the shared (SEC-33): the Galaxy
+/// Gateway-owned validation of the shared : the Galaxy
/// package binds the options but ships no validator, so the gateway rejects a persisted snapshot
/// whose path is blank, invalid, or non-rooted on the running host, and supplies a rooted per-OS
/// default when the shipped config leaves the path blank.
@@ -109,7 +109,7 @@ public sealed class GalaxyRepositoryOptionsValidatorTests
///
/// Verifies the gateway supplies a rooted per-OS default when the shipped config leaves
/// SnapshotCachePath blank, so the removed appsettings literal is not needed and validation
- /// passes on any host (SEC-33). Resolving the options triggers the registered validator.
+ /// passes on any host. Resolving the options triggers the registered validator.
///
[Fact]
public void Build_DefaultsBlankSnapshotCachePathToRootedDefault()
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayConfigurationProviderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayConfigurationProviderTests.cs
index 3b5a148..32dad0f 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayConfigurationProviderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayConfigurationProviderTests.cs
@@ -9,7 +9,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Configuration;
///
///
/// The projection is hand-written member by member, so an option that exists and validates can
-/// still be invisible on the settings page — which is exactly what happened to the two SEC-25
+/// still be invisible on the settings page — which is exactly what happened to the two
/// dashboard-ACL options. These tests pin the dashboard-tag members to the options they come
/// from; the redaction assertions pin the opposite invariant, that the two secret-bearing members
/// are the only ones masked.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
index 966cec3..8c471e9 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsTests.cs
@@ -86,7 +86,7 @@ public sealed class GatewayOptionsTests
["MxGateway:Events:QueueCapacity"] = "256",
["MxGateway:Dashboard:Enabled"] = "false",
["MxGateway:Protocol:MaxGrpcMessageBytes"] = "8388608",
- // The frame-headroom rule is two-sided (IPC-33): the worker-frame maximum must sit
+ // The frame-headroom rule is two-sided: the worker-frame maximum must sit
// between one and two 64 KiB envelope reserves above the gRPC cap, so moving the
// gRPC cap without moving this one no longer validates. Kept at one reserve above,
// the same shape as the shipped default.
@@ -175,7 +175,7 @@ public sealed class GatewayOptionsTests
/// but only the binder decides whether that instance is populated in place or replaced by a
/// default-comparer one. Asserting the comparer on a hand-constructed
/// would prove nothing about the configured path; a mis-cased LDAP group name from the directory
- /// would then silently grant no tags, and the SEC-25 ACL would deny with no diagnostic.
+ /// would then silently grant no tags, and the dashboard session ACL would deny with no diagnostic.
///
[Fact]
public void DashboardOptions_GroupToTag_BindsCaseInsensitively()
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
index 54be27a..cbafda0 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
@@ -778,7 +778,7 @@ public sealed class GatewayOptionsValidatorTests
}
///
- /// Verifies rooting is host-meaningful (SEC-33): a Windows drive-qualified literal fails on a
+ /// Verifies rooting is host-meaningful: a Windows drive-qualified literal fails on a
/// Unix host (where it is not rooted) rather than being blessed and written as a junk-named
/// relative file. On Windows the same literal is genuinely rooted and passes.
///
@@ -805,7 +805,7 @@ public sealed class GatewayOptionsValidatorTests
}
///
- /// Verifies MxGateway:Events:QueueCapacity above int.MaxValue/2 fails (GWC-24 rider): the value
+ /// Verifies MxGateway:Events:QueueCapacity above int.MaxValue/2 fails: the value
/// flows into WorkerClient as checked(2 * EventChannelCapacity), which would otherwise overflow.
///
[Fact]
@@ -1078,7 +1078,7 @@ public sealed class GatewayOptionsValidatorTests
result.Failures!,
f => f.Contains("MxGateway:Ldap:ServiceAccountPassword is required when LDAP login is enabled."));
- // SEC-36: the message must steer the operator to the two supported out-of-band channels
+ // The message must steer the operator to the two supported out-of-band channels
// (dev user-secrets, deployed env var) so a blanked/unresolved credential never gets
// "fixed" by re-committing a value.
Assert.Contains("dotnet user-secrets set", failure);
@@ -1258,7 +1258,7 @@ public sealed class GatewayOptionsValidatorTests
}
///
- /// Verifies the headroom rule's upper half (IPC-33): a worker-frame maximum more than two
+ /// Verifies the headroom rule's upper half: a worker-frame maximum more than two
/// envelope reserves above the gRPC cap is rejected. The worker budgets a DrainEvents reply at
/// the frame maximum less two reserves and the gateway returns that same reply through
/// Invoke, so a wider gap lets the worker pack a reply the pipe carries and the gRPC send
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/PreHostSecretExpansionTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/PreHostSecretExpansionTests.cs
index 95725ae..a905a61 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/PreHostSecretExpansionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/PreHostSecretExpansionTests.cs
@@ -18,6 +18,10 @@ namespace ZB.MOM.WW.MxGateway.Tests.Configuration;
///
public sealed class PreHostSecretExpansionTests
{
+ ///
+ /// A seeded secret reference in configuration resolves to its plaintext.
+ ///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExpandConfiguration_SeededReference_ResolvesToPlaintext()
{
@@ -37,6 +41,7 @@ public sealed class PreHostSecretExpansionTests
/// ${secret:ldap/mxgateway/bind}. Proves that exact reference at that exact key resolves to
/// the seeded plaintext through the same pre-host expander the host runs.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExpandConfiguration_LdapBindReference_ResolvesToSeededPassword()
{
@@ -52,6 +57,10 @@ public sealed class PreHostSecretExpansionTests
Assert.Equal(bindPassword, config["MxGateway:Ldap:ServiceAccountPassword"]);
}
+ ///
+ /// A reference to an absent secret throws instead of leaving the token in place.
+ ///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExpandConfiguration_MissingReference_ThrowsFailClosed()
{
@@ -81,8 +90,11 @@ public sealed class PreHostSecretExpansionTests
_envVarName = envVarName;
}
+ /// Gets the secret resolver from the fixture's DI graph.
public ISecretResolver Resolver => _provider.GetRequiredService();
+ /// Creates a fixture with a unique SQLite store and master-key environment variable.
+ /// The migrated fixture.
public static SecretsFixture Create()
{
string unique = Guid.NewGuid().ToString("N");
@@ -111,8 +123,13 @@ public sealed class PreHostSecretExpansionTests
return new SecretsFixture(provider, sqlitePath, envVarName);
}
- // Seals a plaintext value under a fresh DEK and upserts it — the same store/cipher pair the
- // CLI 'secret set' verb uses.
+ ///
+ /// Seals a plaintext value under a fresh DEK and upserts it, using the same store/cipher pair
+ /// the CLI 'secret set' verb uses.
+ ///
+ /// The secret name.
+ /// The plaintext value to store.
+ /// A task that represents the asynchronous operation.
public async Task SeedAsync(string name, string plaintext)
{
var secretName = new SecretName(name);
@@ -122,11 +139,15 @@ public sealed class PreHostSecretExpansionTests
await store.UpsertAsync(sealed_, default);
}
+ /// Builds an in-memory configuration from the given key/value pairs.
+ /// The configuration entries.
+ /// The built configuration root.
public IConfigurationRoot BuildConfig(params (string Key, string Value)[] entries) =>
new ConfigurationBuilder()
.AddInMemoryCollection(entries.ToDictionary(e => e.Key, e => (string?)e.Value))
.Build();
+ /// Disposes the service provider and clears the test environment variable.
public void Dispose()
{
_provider.Dispose();
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SecretsNavRenderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SecretsNavRenderTests.cs
index 1b4bbb8..fee22f1 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SecretsNavRenderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SecretsNavRenderTests.cs
@@ -15,7 +15,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Dashboard;
///
/// Renders and asserts which policy-gated links the side rail emits —
-/// Secrets (secrets:manage) and, since SEC-40, Alarms
+/// Secrets (secrets:manage) and Alarms
/// ().
///
///
@@ -100,7 +100,7 @@ public sealed class SecretsNavRenderTests
}
///
- /// SEC-40's nav half: an anonymous caller — the read-only localhost path — is not offered the
+ /// The nav half: an anonymous caller — the read-only localhost path — is not offered the
/// Alarms link, because the page and hub now refuse them. Same reasoning as the Secrets
/// negative above: this is the assertion that distinguishes a gate from an inert one.
///
@@ -114,7 +114,7 @@ public sealed class SecretsNavRenderTests
}
///
- /// The control for that negative: an authenticated Viewer still gets the Alarms link. SEC-40
+ /// The control for that negative: an authenticated Viewer still gets the Alarms link. The Alarms gate
/// excludes the environment bypasses, not Viewers — alarm metadata stays galaxy-wide for a
/// real dashboard role because the central monitor carries no per-session provenance.
///
@@ -135,7 +135,7 @@ public sealed class SecretsNavRenderTests
{
options.AddSecretsAuthorization();
// The rail's Alarms AuthorizeView resolves this by name; an unregistered policy throws
- // rather than denying, so it must be present for any rail render (SEC-40).
+ // rather than denying, so it must be present for any rail render.
options.AddPolicy(
DashboardAuthenticationDefaults.AlarmsPolicy,
policy => policy.AddRequirements(AuthenticatedDashboardRoleRequirement.AnyDashboardRole));
@@ -163,6 +163,7 @@ public sealed class SecretsNavRenderTests
// vacuously.
private sealed class StubAuthenticationStateProvider(string[] roles) : AuthenticationStateProvider
{
+ ///
public override Task GetAuthenticationStateAsync()
{
ClaimsIdentity identity = roles.Length == 0
@@ -181,6 +182,7 @@ public sealed class SecretsNavRenderTests
// under static rendering.
private sealed class StubNavigationManager : NavigationManager
{
+ /// Initializes the stub with a fixed localhost base URI.
public StubNavigationManager() => Initialize("https://localhost/", "https://localhost/");
}
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SettingsPageTagVisibilityRenderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SettingsPageTagVisibilityRenderTests.cs
index 0a99f8e..c75d43d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SettingsPageTagVisibilityRenderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/SettingsPageTagVisibilityRenderTests.cs
@@ -11,7 +11,7 @@ using HtmlRenderer = Microsoft.AspNetCore.Components.Web.HtmlRenderer;
namespace ZB.MOM.WW.MxGateway.Tests.Dashboard;
///
-/// Renders and asserts the two SEC-25 dashboard-ACL options —
+/// Renders and asserts the two dashboard-ACL options —
/// Dashboard:GroupToTag and Dashboard:UntaggedSessionVisibility — reach the page.
///
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmFeedAuthorizationTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmFeedAuthorizationTests.cs
index fb85b24..ba571cc 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmFeedAuthorizationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmFeedAuthorizationTests.cs
@@ -16,7 +16,7 @@ using AuthenticationOptions = ZB.MOM.WW.MxGateway.Server.Configuration.Authentic
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
-/// Covers SEC-40: the alarm feed requires a real authenticated dashboard role, so the read-only
+/// Covers the rule that the alarm feed requires a real authenticated dashboard role, so the read-only
/// environment bypasses (Authentication:Mode=Disabled, anonymous localhost) no longer
/// receive galaxy-wide alarm metadata.
///
@@ -65,7 +65,7 @@ public sealed class AlarmFeedAuthorizationTests
///
/// An authenticated Viewer — the ordinary LDAP-logged-in dashboard user — does satisfy the
- /// alarm requirement: SEC-40 excludes the environment bypasses, not Viewers. Alarm metadata
+ /// alarm requirement: the rule excludes the environment bypasses, not Viewers. Alarm metadata
/// stays galaxy-wide for them because the monitor is gateway-central and carries no
/// per-session provenance to tag-scope by.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmsHubPublisherTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmsHubPublisherTests.cs
index 7eb18b3..ea9e9fb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmsHubPublisherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/AlarmsHubPublisherTests.cs
@@ -11,7 +11,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
/// Verifies that honours
-/// MxGateway:Dashboard:ShowTagValues (TST-16): the alarm value fields of
+/// MxGateway:Dashboard:ShowTagValues: the alarm value fields of
/// both value-bearing payload arms are stripped from the copy broadcast to
/// browser clients when the flag is off, present when it is on, and the source
/// — shared with the gRPC StreamAlarms
@@ -286,22 +286,48 @@ public sealed class AlarmsHubPublisherTests
/// Gets the capturing client proxy shared by this fake.
public CapturingClientProxy GroupProxy { get; } = new();
+ /// Gets the shared capturing proxy for all clients.
public IClientProxy All => GroupProxy;
+ /// Returns the shared capturing proxy, ignoring the exclusions.
+ /// Connection ids to exclude.
+ /// The shared capturing proxy.
public IClientProxy AllExcept(IReadOnlyList excludedConnectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for one connection.
+ /// The target connection id.
+ /// The shared capturing proxy.
public IClientProxy Client(string connectionId) => GroupProxy;
+ /// Returns the shared capturing proxy for several connections.
+ /// The target connection ids.
+ /// The shared capturing proxy.
public IClientProxy Clients(IReadOnlyList connectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for one group.
+ /// The target group name.
+ /// The shared capturing proxy.
public IClientProxy Group(string groupName) => GroupProxy;
+ /// Returns the shared capturing proxy for a group, ignoring the exclusions.
+ /// The target group name.
+ /// Connection ids to exclude.
+ /// The shared capturing proxy.
public IClientProxy GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for several groups.
+ /// The target group names.
+ /// The shared capturing proxy.
public IClientProxy Groups(IReadOnlyList groupNames) => GroupProxy;
+ /// Returns the shared capturing proxy for one user.
+ /// The target user id.
+ /// The shared capturing proxy.
public IClientProxy User(string userId) => GroupProxy;
+ /// Returns the shared capturing proxy for several users.
+ /// The target user ids.
+ /// The shared capturing proxy.
public IClientProxy Users(IReadOnlyList userIds) => GroupProxy;
}
@@ -342,9 +368,19 @@ public sealed class AlarmsHubPublisherTests
private sealed class NoopGroupManager : IGroupManager
{
+ /// Ignores the membership change and completes synchronously.
+ /// The connection being added.
+ /// The group the connection joins.
+ /// Token to observe for cancellation.
+ /// A completed task.
public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
+ /// Ignores the removal and completes synchronously.
+ /// The connection being removed.
+ /// The group the connection leaves.
+ /// Token to observe for cancellation.
+ /// A completed task.
public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardBrowseAndAlarmModelTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardBrowseAndAlarmModelTests.cs
index 55ca53b..d124bc7 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardBrowseAndAlarmModelTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardBrowseAndAlarmModelTests.cs
@@ -180,7 +180,7 @@ public sealed class DashboardBrowseAndAlarmModelTests
///
/// An explicitly-degraded status whose mode is still Alarmmgr (the
/// Degraded || Mode==Subtag guard's second, independent branch) must map to the
- /// amber badge, but not to the failover label: GWC-37 gives that combination a meaning —
+ /// amber badge, but not to the failover label: that combination has its own meaning —
/// the alarm manager is serving and the subtag standby behind it covers nothing — so
/// reporting "Subtag monitoring (degraded)" would name the wrong live provider.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardEventBroadcasterTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardEventBroadcasterTests.cs
index 55aa942..9e5a0b5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardEventBroadcasterTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardEventBroadcasterTests.cs
@@ -9,7 +9,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
/// Verifies that honours
-/// MxGateway:Dashboard:ShowTagValues (SEC-25): tag values are stripped
+/// MxGateway:Dashboard:ShowTagValues: tag values are stripped
/// from the mirrored copy when the flag is off, present when it is on, and the
/// shared source event is never mutated. Also verifies the viewer gate — the
/// mirror does no work at all for a session nobody is watching.
@@ -325,22 +325,48 @@ public sealed class DashboardEventBroadcasterTests
/// Gets the capturing client proxy shared by this fake.
public CapturingClientProxy GroupProxy { get; } = new();
+ /// Gets the shared capturing proxy for all connections.
public IClientProxy All => GroupProxy;
+ /// Returns the shared capturing proxy, ignoring exclusions.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy AllExcept(IReadOnlyList excludedConnectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for any connection.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy Client(string connectionId) => GroupProxy;
+ /// Returns the shared capturing proxy for any connection set.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy Clients(IReadOnlyList connectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for any group.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy Group(string groupName) => GroupProxy;
+ /// Returns the shared capturing proxy for any group, ignoring exclusions.
+ /// Ignored.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => GroupProxy;
+ /// Returns the shared capturing proxy for any group set.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy Groups(IReadOnlyList groupNames) => GroupProxy;
+ /// Returns the shared capturing proxy for any user.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy User(string userId) => GroupProxy;
+ /// Returns the shared capturing proxy for any user set.
+ /// Ignored.
+ /// The shared capturing proxy.
public IClientProxy Users(IReadOnlyList userIds) => GroupProxy;
}
@@ -367,9 +393,19 @@ public sealed class DashboardEventBroadcasterTests
private sealed class NoopGroupManager : IGroupManager
{
+ /// Ignores the group membership change.
+ /// Ignored.
+ /// Ignored.
+ /// Ignored.
+ /// A completed task.
public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
+ /// Ignores the group membership change.
+ /// Ignored.
+ /// Ignored.
+ /// Ignored.
+ /// A completed task.
public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLiveDataServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLiveDataServiceTests.cs
index 9079e5f..820e29b 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLiveDataServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardLiveDataServiceTests.cs
@@ -20,6 +20,7 @@ public sealed class DashboardLiveDataServiceTests
///
/// Verifies a tag already in the advise set is not subscribed again on a later read.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenTagAlreadySubscribed_DoesNotResubscribe()
{
@@ -41,6 +42,7 @@ public sealed class DashboardLiveDataServiceTests
/// Verifies the advise set is capped: subscribing past the cap unadvises the
/// least-recently-read tag on the worker and leaves the re-read tag advised.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_PastCap_EvictsLeastRecentlyReadTag()
{
@@ -78,6 +80,7 @@ public sealed class DashboardLiveDataServiceTests
/// than the cap keeps them all (a read never evicts a tag it is about to return),
/// and the next read that subscribes anything squeezes the overshoot back out.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithMoreDistinctTagsThanCap_KeepsThemAllThenSelfCorrects()
{
@@ -108,6 +111,7 @@ public sealed class DashboardLiveDataServiceTests
/// touches nearly the whole advise set evicts only the untouched remainder, ends over
/// the cap, and the following read trims it back.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenTouchedTagsFillTheCap_EvictsOnlyUntouchedTags()
{
@@ -135,6 +139,7 @@ public sealed class DashboardLiveDataServiceTests
/// Verifies a tag the worker failed to advise still occupies a slot but is evicted
/// without any unsubscribe command — there is no item handle to unadvise.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenAdviseFailed_EvictsTagWithoutUnsubscribing()
{
@@ -165,6 +170,7 @@ public sealed class DashboardLiveDataServiceTests
/// Verifies a failed unadvise of an evicted tag does not fail the read, and the
/// evicted tag is dropped from tracking anyway.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenEvictionUnsubscribeFails_StillCompletesRead()
{
@@ -190,10 +196,11 @@ public sealed class DashboardLiveDataServiceTests
///
/// Verifies the /browse live-value seam honours
- /// MxGateway:Dashboard:ShowTagValues (TST-16): with the flag off — the
+ /// MxGateway:Dashboard:ShowTagValues: with the flag off — the
/// default — the value text the page renders is the redaction placeholder,
/// never the formatted tag value.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenShowTagValuesFalse_RedactsValueTextButKeepsMetadata()
{
@@ -220,6 +227,7 @@ public sealed class DashboardLiveDataServiceTests
}
/// Verifies the formatted value is served when the flag is on.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenShowTagValuesTrue_ServesFormattedValue()
{
@@ -243,6 +251,7 @@ public sealed class DashboardLiveDataServiceTests
/// withheld, and its diagnostic still reaches the panel. Redacting it would
/// contradict the error the same row displays.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenReadFailedAndShowTagValuesFalse_LeavesPlaceholderUnredacted()
{
@@ -489,7 +498,8 @@ public sealed class DashboardLiveDataServiceTests
{
}
- ///
+ /// Completes immediately because the fake holds no resources.
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
private BulkSubscribeReply Subscribe(IEnumerable tagAddresses)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAclTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAclTests.cs
index 5d872ca..f9af367 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAclTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAclTests.cs
@@ -10,7 +10,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
/// Covers , the single decision both dashboard subscribe seams
-/// consult (SEC-25 / TST-15).
+/// consult.
///
///
/// Every branch is asserted in its denying direction as well as its allowing one, because the
@@ -77,6 +77,7 @@ public sealed class DashboardSessionAclTests
}
/// A blank session id is denied without consulting anything.
+ /// A blank or whitespace-only session id.
[Theory]
[InlineData("")]
[InlineData(" ")]
@@ -146,8 +147,8 @@ public sealed class DashboardSessionAclTests
}
///
- /// A principal carrying no tag claims — the anonymous-localhost / empty-grant Viewer of
- /// SEC-02 — sees a tagged session never, and an untagged one only when the operator opted
+ /// A principal carrying no tag claims — the anonymous-localhost / empty-grant Viewer —
+ /// sees a tagged session never, and an untagged one only when the operator opted
/// into .
///
[Fact]
@@ -179,7 +180,7 @@ public sealed class DashboardSessionAclTests
}
///
- /// SEC-41, the load-bearing regression: a cookie-style principal whose tag claim was stamped
+ /// The load-bearing regression: a cookie-style principal whose tag claim was stamped
/// at login under an older GroupToTag map is DENIED once that map no longer grants the
/// tag to any group the principal belongs to. The auth cookie survives the restart that
/// rebinds options, so trusting the stamped claim let a config-revoked grant live on for the
@@ -224,7 +225,7 @@ public sealed class DashboardSessionAclTests
///
/// Re-resolution is ordinal-ignore-case on both sides — the group key against the map (which
/// owns) and the resolved tag against the session's tag
- /// set. Pinned because the pre-SEC-41 claim scan got the second comparison from
+ /// set. Pinned because the earlier claim scan got the second comparison from
/// Session.Tags's own comparer, and the re-resolution arm probes the grant set in the
/// opposite direction.
///
@@ -294,7 +295,7 @@ public sealed class DashboardSessionAclTests
}
///
- /// Builds a dashboard principal. is the SEC-41 discriminator: a
+ /// Builds a dashboard principal. is the discriminator: a
/// principal WITH group claims is re-resolved against the current map (the cookie seam), one
/// WITHOUT falls back to its stamped tag claims (the hub-token seam). Existing cases pass
/// tags only, so they continue to exercise the fallback arm exactly as before.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubTests.cs
index b0f2b83..1874723 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubTests.cs
@@ -7,7 +7,7 @@ using ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
-/// Covers the ACL gate on (SEC-25 / TST-15).
+/// Covers the ACL gate on .
///
///
/// The denial assertions are the load-bearing ones — before the gate existed every caller was
@@ -131,7 +131,11 @@ public sealed class EventsHubTests
/// Gets the (connection id, group name) pairs added, in order.
public List<(string ConnectionId, string GroupName)> Added { get; } = [];
- ///
+ /// Records the group membership and completes synchronously.
+ /// The connection being added.
+ /// The group the connection joins.
+ /// Token to observe for cancellation.
+ /// A completed task.
public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
{
Added.Add((connectionId, groupName));
@@ -139,7 +143,11 @@ public sealed class EventsHubTests
return Task.CompletedTask;
}
- ///
+ /// Ignores the removal and completes synchronously.
+ /// The connection being removed.
+ /// The group the connection leaves.
+ /// Token to observe for cancellation.
+ /// A completed task.
public Task RemoveFromGroupAsync(
string connectionId,
string groupName,
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubViewerRegistryTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubViewerRegistryTests.cs
index e220b9c..acd5712 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubViewerRegistryTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/EventsHubViewerRegistryTests.cs
@@ -129,6 +129,8 @@ public sealed class EventsHubViewerRegistryTests
}
/// Blank connection or session ids are ignored rather than tracked.
+ /// The hub connection id, possibly blank.
+ /// The session id, possibly blank.
[Theory]
[InlineData("", "session-1")]
[InlineData(" ", "session-1")]
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 7846fd3..b48cf51 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/HubTokenServiceTests.cs
@@ -178,7 +178,7 @@ public sealed class HubTokenServiceTests
}
///
- /// The dashboard visibility grant (SEC-25) survives the mint/validate round-trip: tags are
+ /// The dashboard visibility grant survives the mint/validate round-trip: tags are
/// resolved from the caller's LDAP-group claims through Dashboard:GroupToTag at
/// and rehydrated as
/// claims on the principal
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/SessionDetailsPageEventAclTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/SessionDetailsPageEventAclTests.cs
index 1480d26..1bb16b5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/SessionDetailsPageEventAclTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/SessionDetailsPageEventAclTests.cs
@@ -16,7 +16,7 @@ using ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
///
-/// Covers the ACL gate on the session-details page's in-process subscribe seam (SEC-25 / TST-15).
+/// Covers the ACL gate on the session-details page's in-process subscribe seam.
///
///
///
@@ -214,7 +214,7 @@ public sealed class SessionDetailsPageEventAclTests
///
public ChannelReader Reader => _channel.Reader;
- ///
+ /// Marks the subscription as released and completes its channel.
public void Dispose()
{
IsDisposed = true;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
index a20ffbc..1ebfbad 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
@@ -81,7 +81,7 @@ public sealed class GatewayApplicationTests
{
// Bind an ephemeral port (:0) — xUnit runs test collections in parallel, so any
// started-host test must avoid a fixed port to prevent a bind collision. The auth SQLite
- // store path is isolated to a per-process temp file by TestHostEnvironmentInitializer (SEC-33).
+ // store path is isolated to a per-process temp file by TestHostEnvironmentInitializer.
await using WebApplication app = GatewayApplication.Build(["--urls=http://127.0.0.1:0"]);
await app.StartAsync();
try
@@ -266,7 +266,7 @@ public sealed class GatewayApplicationTests
{
// Bind an ephemeral port (:0) — xUnit runs test collections in parallel, so any
// WebApplication-building test must avoid a fixed port to prevent a bind collision. The auth
- // store path is isolated by TestHostEnvironmentInitializer (SEC-33), so startup opens a
+ // store path is isolated by TestHostEnvironmentInitializer, so startup opens a
// writable store and the injected misconfiguration is what fails validation.
await using WebApplication app = GatewayApplication.Build(
[$"--{key}={value}", "--urls=http://127.0.0.1:0"]);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndReconnectReplayTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndReconnectReplayTests.cs
index 7bfa802..df3c53a 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndReconnectReplayTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndReconnectReplayTests.cs
@@ -19,7 +19,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway;
///
/// End-to-end reconnect/replay tests through the real gRPC StreamEvents path via the
-/// fake worker harness (TST-01, server half). A single subscriber detaches (cancel + await
+/// fake worker harness (server half). A single subscriber detaches (cancel + await
/// the stream task so its lease is fully disposed), the session is retained by detach-grace
/// while the distributor pump keeps appending worker events to the replay ring, and a second
/// stream reconnects with . Covers both
@@ -233,7 +233,7 @@ public sealed class GatewayEndToEndReconnectReplayTests
}
///
- /// GWC-25 regression, end to end: when age eviction has emptied the replay ring, the
+ /// Regression, end to end: when age eviction has emptied the replay ring, the
/// ReplayGap sentinel carries the next deliverable sequence (highest observed + 1),
/// so a client applying the documented
/// after_worker_sequence = oldest_available_sequence - 1 formula on its follow-up
@@ -305,7 +305,7 @@ public sealed class GatewayEndToEndReconnectReplayTests
Assert.NotNull(sentinel.ReplayGap);
Assert.Equal(staleCursor, sentinel.ReplayGap.RequestedAfterSequence);
- // The whole point of GWC-25: the sentinel anchors the resume at the next sequence that
+ // The whole point of the fix: the sentinel anchors the resume at the next sequence that
// can still be delivered, not at 0.
Assert.Equal(highestSeen + 1, sentinel.ReplayGap.OldestAvailableSequence);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryHostWiringTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryHostWiringTests.cs
index 0178369..2d2ffe1 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryHostWiringTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryHostWiringTests.cs
@@ -28,7 +28,7 @@ public sealed class GalaxyRepositoryHostWiringTests
/// Verifies the full production authz-filtering chain end-to-end.
/// Phase 1: an identity carrying no BrowseSubtrees pushed → BrowseChildren
/// returns both children (unconstrained). That, not an absent identity, is production's
- /// unscoped case since GWC-38 — with Authentication:Mode=ApiKey an absent identity
+ /// unscoped case — with Authentication:Mode=ApiKey an absent identity
/// now denies, which the isolated provider test pins.
/// Phase 2: identity with BrowseSubtrees = ["NonExistent"]
/// pushed via → the real
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
index 6a82b5d..15c5493 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
@@ -52,7 +52,7 @@ public sealed class MxAccessGatewayServiceTests
///
/// Verifies OpenSession forwards the calling key's dashboard-visibility tags, so the
- /// session's tags are derived from the owning API key rather than the wire request (SEC-25).
+ /// session's tags are derived from the owning API key rather than the wire request.
///
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcMapperTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcMapperTests.cs
index ebf4957..c82424d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcMapperTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGrpcMapperTests.cs
@@ -41,7 +41,7 @@ public sealed class MxAccessGrpcMapperTests
///
/// The command-only overload exists so Invoke does not deep-clone the whole request just to
- /// overwrite and discard its command (GWC-29). It must still perform the one clone that keeps the
+ /// overwrite and discard its command. It must still perform the one clone that keeps the
/// worker-bound graph unaliased from the caller-owned gRPC command, and must produce the same
/// as the request overload.
///
@@ -145,7 +145,7 @@ public sealed class MxAccessGrpcMapperTests
}
///
- /// Verifies MapEvent transfers ownership of the inner MxEvent (GWC-07 / IPC-05): the
+ /// Verifies MapEvent transfers ownership of the inner MxEvent: the
/// returned reference is the same instance carried by the WorkerEvent, not a clone. The
/// WorkerEvent is discarded after mapping and the distributor pump is its single consumer,
/// so moving the inner event out is safe and avoids a per-event deep copy.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
index 5581103..8d07108 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
@@ -669,7 +669,7 @@ public sealed class GatewaySessionTests
}
///
- /// GWC-27: must refuse to
+ /// must refuse to
/// attach before the session is Ready. Without the gate the attach would construct and
/// start the distributor against a not-yet-Ready worker; the pump source throws
/// SessionNotReady, every subscriber is completed with that error, and the
@@ -720,7 +720,7 @@ public sealed class GatewaySessionTests
}
///
- /// GWC-34, the disposal-side twin of the GWC-27 premature-attach poison: an attach that
+ /// The disposal-side twin of the premature-attach poison: an attach that
/// passed its readiness gate and then lost the CPU until the session was torn down used to
/// find _eventDistributor null, read that as "not created yet" and build a
/// REPLACEMENT distributor. Its pump could never start (the started flag is a one-way latch)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionEventDistributorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionEventDistributorTests.cs
index 5220ac3..fdbe7c5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionEventDistributorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionEventDistributorTests.cs
@@ -843,7 +843,7 @@ public sealed class SessionEventDistributorTests
}
///
- /// GWC-25: when age eviction has emptied the replay ring, a resume behind the highest
+ /// When age eviction has emptied the replay ring, a resume behind the highest
/// observed sequence still reports a gap, and the reported oldest-available sequence is
/// the next sequence that can possibly be delivered (highest seen + 1) — never 0,
/// which would make the client's documented oldest - 1 resume formula wrap to
@@ -889,7 +889,7 @@ public sealed class SessionEventDistributorTests
}
///
- /// GWC-25: the same next-deliverable-sequence rule applies when retention is disabled
+ /// The same next-deliverable-sequence rule applies when retention is disabled
/// outright (replay capacity 0) — the ring is always empty, so a behind cursor must still
/// get a usable resume anchor rather than 0.
///
@@ -924,7 +924,7 @@ public sealed class SessionEventDistributorTests
}
///
- /// GWC-25 regression: a client that applies the documented
+ /// Regression: a client that applies the documented
/// after_worker_sequence = oldest_available_sequence - 1 formula to an empty-ring
/// ReplayGap resumes with a live watermark equal to the highest observed sequence, so the
/// caller's live filter passes every subsequent event. Under the pre-fix 0 the
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
index c0405df..0a04f13 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
@@ -41,7 +41,7 @@ public sealed class SessionManagerTests
/// Verifies the pipe name stays short enough that its Unix-domain-socket path
/// (TMPDIR + "CoreFxPipe_" + name) fits the 104-byte macOS sun_path limit under the
/// default per-user TMPDIR (~49 chars), and keeps the pid + session-guid uniqueness
- /// contract (NEXT-01).
+ /// contract.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -110,7 +110,7 @@ public sealed class SessionManagerTests
}
///
- /// Verifies a session inherits the owning API key's dashboard-visibility tags (SEC-25),
+ /// Verifies a session inherits the owning API key's dashboard-visibility tags,
/// compared ordinal-ignore-case so a differently cased grant still matches.
///
/// A task that represents the asynchronous operation.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
index c8f7047..3dd5ea2 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
@@ -24,7 +24,10 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncLifetime
private readonly List _launchers = [];
- ///
+ ///
+ /// Completes immediately; no asynchronous setup is required before each test.
+ ///
+ /// A task that represents the asynchronous operation.
public Task InitializeAsync() => Task.CompletedTask;
///
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 89084bd..ec1824e 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
@@ -36,10 +36,10 @@ public sealed class WorkerClientTests
///
/// The GatewayHello carries the negotiated worker-frame maximum so the worker adopts the
- /// configured limit instead of its own default (IPC-02); a regression to sending 0 means
+ /// configured limit instead of its own default; a regression to sending 0 means
/// "older gateway, use default" to the worker and would silently downgrade the negotiated limit.
/// The adoption half is asserted only in the Windows-only worker suite, so the gateway half is
- /// pinned here, in the portable suite (TST-28). Both the default and an override are covered so
+ /// pinned here, in the portable suite. Both the default and an override are covered so
/// the assertion tracks configuration rather than a constant.
///
/// Configured worker-frame maximum to negotiate.
@@ -164,7 +164,7 @@ public sealed class WorkerClientTests
TestTimeout,
CancellationToken.None);
- // The timeout also emits a WorkerCancel for the abandoned correlation (PERF-07), which sits
+ // The timeout also emits a WorkerCancel for the abandoned correlation, which sits
// ahead of the second command on the FIFO pipe; skip it rather than mistaking it for the
// command this assertion is about.
WorkerEnvelope secondCommand = await ReadNextCommandAsync(pipePair, timedOutCommand.CorrelationId);
@@ -180,7 +180,7 @@ public sealed class WorkerClientTests
///
/// A command timeout abandons the gateway-side wait, but the worker keeps the correlation on
/// its single STA queue and would still run it — so the gateway forwards a WorkerCancel
- /// for the abandoned correlation id (PERF-07). Without it, a client that retries after a
+ /// for the abandoned correlation id. Without it, a client that retries after a
/// timeout stacks work the worker still intends to execute. Asserted on the wire because the
/// cancel is protocol behavior the worker depends on, not an internal detail.
///
@@ -223,7 +223,7 @@ public sealed class WorkerClientTests
///
/// Caller cancellation abandons the correlation exactly as a gateway timeout does — a client
/// deadline shorter than the gateway's command timeout, or a disconnect, is the common
- /// abandonment path — so it forwards the same WorkerCancel (IPC-34). Without it a
+ /// abandonment path — so it forwards the same WorkerCancel. Without it a
/// retry storm of deadline-cancelled calls leaves the worker's single STA working through
/// commands nobody is waiting for while live callers queue behind them. Twin of
/// , driven
@@ -271,7 +271,7 @@ public sealed class WorkerClientTests
///
/// The cancel is forwarded for a caller that abandoned its command, never for the client's own
- /// teardown (IPC-34): once the stop token has fired the outbound channel is being completed and
+ /// teardown: once the stop token has fired the outbound channel is being completed and
/// every pending command is failed anyway, so a cancel would at best be pointless and at worst
/// a write racing teardown. Asserted on the wire — the guard in the cancellation arm is the
/// code-level expression of it, and the completed outbound channel is the second line of
@@ -330,8 +330,7 @@ public sealed class WorkerClientTests
/// A WorkerFault arriving in place of a handshake frame is the worker reporting a
/// structured startup failure — most often MXAccess COM creation — not a protocol problem, so
/// the gateway surfaces with the fault's
- /// category and diagnostic rather than a generic protocol violation naming only the body type
- /// (IPC-35). This is the window where the information matters most: first session open on a
+ /// category and diagnostic rather than a generic protocol violation naming only the body type. This is the window where the information matters most: first session open on a
/// freshly deployed host, where the message reaches the operator log and the client's
/// OpenFailed detail.
///
@@ -368,8 +367,7 @@ public sealed class WorkerClientTests
///
/// The envelope sequence is a monotonic per-sender counter (gateway.md), so the values
/// observed on the pipe must be strictly increasing in wire order. Stamping the sequence when
- /// the envelope is constructed lets two concurrent invokes stamp 1 and 2 but enqueue 2 then 1
- /// (GWC-28); stamping on the single-consumer write loop makes wire order and sequence order the
+ /// the envelope is constructed lets two concurrent invokes stamp 1 and 2 but enqueue 2 then 1; stamping on the single-consumer write loop makes wire order and sequence order the
/// same thing by construction.
///
/// A task that represents the asynchronous operation.
@@ -710,12 +708,12 @@ public sealed class WorkerClientTests
}
///
- /// GWC-32: disposing a still-Ready client while the worker is emitting events must be
+ /// Disposing a still-Ready client while the worker is emitting events must be
/// an ordinary teardown, not a fault. DisposeAsync completes the same three channels
/// MarkClosed and SetFaulted do, so it must enter a terminal state first;
/// otherwise the read loop — already inside DispatchEnvelope when the staging channel
/// is completed, or reading a stream that is torn down underneath it — misdiagnoses the
- /// completed channel as the GWC-24 sustained-backpressure overflow and raises a spurious
+ /// completed channel as the sustained-backpressure overflow and raises a spurious
/// ProtocolViolation fault, a worker-event-staging overflow metric and a
/// redundant kill during an intentional dispose. The event channel is sized far above the
/// burst so a genuine overflow is impossible, and DisposeAsync awaits its background
@@ -726,7 +724,7 @@ public sealed class WorkerClientTests
public async Task DisposeAsync_WhileWorkerIsEmittingEvents_ClosesWithoutFaultingOrOverflowing()
{
// The burst is capped at EmittedEventCeiling and the staging channel holds 2 x capacity, so
- // even if every emitted event were staged and none consumed the GWC-24 bound is unreachable:
+ // even if every emitted event were staged and none consumed the staging bound is unreachable:
// an overflow metric in this test can only be the dispose-race misdiagnosis.
const int capacity = 2048;
using GatewayMetrics metrics = new();
@@ -1007,13 +1005,13 @@ public sealed class WorkerClientTests
}
///
- /// GWC-24: the staging channel between the read loop and the event writer is bounded at
+ /// The staging channel between the read loop and the event writer is bounded at
/// 2 × , so a consumer that drains
/// slower than the worker produces faults the client at the bound instead of growing
/// gateway memory silently. The full-mode timeout here is far longer than the test could
/// ever wait, which proves the fault came from the staging bound and not from the timed
/// write in EnqueueWorkerEventAsync. A command reply interleaved before the fault
- /// must still complete: the read loop never blocks behind events (the GWC-04 guarantee).
+ /// must still complete: the read loop never blocks behind events (the read-loop guarantee).
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -1094,7 +1092,7 @@ public sealed class WorkerClientTests
}
///
- /// GWC-24: the worker event queue-depth gauge counts staged *and* queued events, so a
+ /// The worker event queue-depth gauge counts staged *and* queued events, so a
/// backlog held in the staging channel is visible rather than invisible. Depth is
/// incremented at staging and decremented when the consumer reads, so the single counter
/// reports total undelivered events and returns to zero once drained.
@@ -1148,7 +1146,7 @@ public sealed class WorkerClientTests
}
///
- /// GWC-33: a faulted client can remain retained for diagnostics, but its abandoned event
+ /// A faulted client can remain retained for diagnostics, but its abandoned event
/// backlog must stop contributing to the gateway-wide queue-depth gauge as soon as the
/// client enters a terminal state rather than waiting for disposal.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
index 6663b0f..ecc452b 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
@@ -57,7 +57,7 @@ public sealed class WorkerFrameProtocolTests
///
/// One reader instance reads many frames in sequence. The reader reuses a single length-prefix
- /// scratch buffer across calls (GWC-30), so varying the payload length frame to frame proves the
+ /// scratch buffer across calls, so varying the payload length frame to frame proves the
/// reused buffer is fully overwritten each time rather than carrying a stale prefix forward.
///
/// A task that represents the asynchronous operation.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
index 4101600..3ee8db7 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Metrics/GatewayMetricsTests.cs
@@ -19,11 +19,11 @@ public sealed class GatewayMetricsTests
metrics.CommandFailed("WriteSecured", "AuthorizationFailed", TimeSpan.FromMilliseconds(12));
metrics.EventReceived("session-1", "OnDataChange");
metrics.EventReceived("session-1", "OnDataChange");
- // PERF-02: the worker queue-depth gauge sums one live source per worker client, so the two
+ // The worker queue-depth gauge sums one live source per worker client, so the two
// registrations below stand in for two concurrent sessions holding 3 and 4 events.
using IDisposable workerDepthSourceA = metrics.RegisterWorkerEventQueueDepthSource(static () => 3);
using IDisposable workerDepthSourceB = metrics.RegisterWorkerEventQueueDepthSource(static () => 4);
- // GWC-15: the gRPC stream queue-depth gauge sums live backlog sources at collection time
+ // The gRPC stream queue-depth gauge sums live backlog sources at collection time
// rather than tracking a pushed running total. Register a source reporting 3.
using IDisposable backlogSource = metrics.RegisterEventStreamBacklogSource(static () => 3);
metrics.QueueOverflow("session-events");
@@ -58,7 +58,7 @@ public sealed class GatewayMetricsTests
}
///
- /// PERF-02: the worker queue-depth gauge sums every registered source rather than holding a
+ /// The worker queue-depth gauge sums every registered source rather than holding a
/// single pushed scalar, so concurrent sessions add up instead of overwriting one another,
/// and a disposed registration (a worker client going away) drops out of the sum. Disposal
/// is idempotent because a client's dispose path can run twice.
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/WindevCiContractTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/WindevCiContractTests.cs
index 0d59a1e..5b5e389 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/WindevCiContractTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/ProjectStructure/WindevCiContractTests.cs
@@ -1,7 +1,9 @@
namespace ZB.MOM.WW.MxGateway.Tests.ProjectStructure;
+/// Pins the structure of the windev worker CI script.
public sealed class WindevCiContractTests
{
+ /// Verifies live mode runs the Windows test tiers in the documented order.
[Fact]
public void LiveMode_RunsWindowsTiersInDocumentedOrder()
{
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 467e7d0..a07eaff 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCommandLineParserTests.cs
@@ -238,6 +238,7 @@ public sealed class ApiKeyAdminCommandLineParserTests
/// Verifies an empty tag segment is rejected rather than dropped: a stray comma must not
/// silently persist a grant the operator did not write.
///
+ /// The raw dashboard tag list containing an empty segment.
[Theory]
[InlineData("team-a,,team-b")]
[InlineData("team-a, ")]
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 49dce31..a13dd72 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/CachingApiKeyVerifierTests.cs
@@ -100,7 +100,7 @@ public sealed class CachingApiKeyVerifierTests
}
///
- /// SEC-34 window 3: an that lands while a
+ /// Window 3: an that lands while a
/// verification is in flight in the inner library must discard that verification's repopulation,
/// so the very next request re-verifies (revoke takes effect immediately, not after the TTL).
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ApiKeyFailureLimiterTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ApiKeyFailureLimiterTests.cs
index 2e7e3e6..17b05d5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ApiKeyFailureLimiterTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ApiKeyFailureLimiterTests.cs
@@ -4,7 +4,7 @@ using ZB.MOM.WW.MxGateway.Tests.TestSupport;
namespace ZB.MOM.WW.MxGateway.Tests.Security.Authorization;
///
-/// Unit tests for the two-layer API-key failure limiter (SEC-31 / SEC-32): composite
+/// Unit tests for the two-layer API-key failure limiter: composite
/// (transport peer, key id) partitions, the cross-peer per-key-id aggregate, probe
/// admission, the per-peer key-id partition cap, and the eviction preference order.
///
@@ -58,7 +58,7 @@ public sealed class ApiKeyFailureLimiterTests
///
/// The composite partition binds a throttle to the failing address: the same key id presented
- /// from a different transport peer is unaffected. This is the structural half of the SEC-31 fix.
+ /// from a different transport peer is unaffected. This is the structural half of the per-address throttle.
///
[Fact]
public void CompositePartition_ThrottleDoesNotFollowKeyIdToAnotherPeer()
@@ -102,7 +102,7 @@ public sealed class ApiKeyFailureLimiterTests
}
///
- /// SEC-38: a valid key id still feeds and consults its cross-peer aggregate when each
+ /// A valid key id still feeds and consults its cross-peer aggregate when each
/// attacking peer has exhausted its 32 dedicated key-id partitions and therefore records
/// the peer layer through the fallback bucket.
///
@@ -372,7 +372,7 @@ public sealed class ApiKeyFailureLimiterTests
}
///
- /// SEC-39: a request with no effective key id does not own the peer's shared fallback
+ /// A request with no effective key id does not own the peer's shared fallback
/// partition. Resetting after such a request must leave other fallback failures tracked.
///
[Fact]
@@ -395,7 +395,7 @@ public sealed class ApiKeyFailureLimiterTests
}
///
- /// SEC-32: a spray of unique junk partitions (junk tokens resolve to the sender's fallback
+ /// A spray of unique junk partitions (junk tokens resolve to the sender's fallback
/// partition, one per address) must not evict a partition that is currently throttled — the
/// LRU cap bounds memory, it must not be a reset button for the block.
///
@@ -420,7 +420,7 @@ public sealed class ApiKeyFailureLimiterTests
}
///
- /// SEC-32: one address may mint at most
+ /// One address may mint at most
/// key-id partitions; the overflow collapses into that address's fallback partition, which then
/// throttles the address wholesale instead of letting the spray mint unbounded state.
///
@@ -445,7 +445,7 @@ public sealed class ApiKeyFailureLimiterTests
}
///
- /// SEC-32 eviction preference: with the map at capacity a new failure evicts an entry whose
+ /// Eviction preference: with the map at capacity a new failure evicts an entry whose
/// window has fully expired rather than an entry that is still counting.
///
[Fact]
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayBrowseScopeProviderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayBrowseScopeProviderTests.cs
index 1e0eba2..e6fa3a9 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayBrowseScopeProviderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayBrowseScopeProviderTests.cs
@@ -32,8 +32,8 @@ public sealed class GatewayBrowseScopeProviderTests
///
/// An authenticated key with no BrowseSubtrees constraint is legitimately unscoped: the
- /// empty list is what the library reads as "no scoping". This is the state GWC-38 required
- /// to stay distinguishable from an absent identity, so it is asserted alongside its
+ /// empty list is what the library reads as "no scoping". This is the state that must
+ /// stay distinguishable from an absent identity, so it is asserted alongside its
/// denying twin below rather than left implicit.
///
[Fact]
@@ -49,7 +49,7 @@ public sealed class GatewayBrowseScopeProviderTests
}
///
- /// GWC-38: with API-key authentication enabled, an absent ambient identity means the
+ /// With API-key authentication enabled, an absent ambient identity means the
/// interceptor-ordering invariant is broken — the request's browse scope cannot be
/// established. The provider must DENY rather than resolve to the full hierarchy, because
/// a silently-unscoped browse is an invisible authorization bypass. The status code is
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 b9327a6..c38b7db 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
@@ -365,7 +365,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-31: once an attacking peer has exceeded the failure limit for a key id, the interceptor
+ /// Once an attacking peer has exceeded the failure limit for a key id, the interceptor
/// short-circuits with BEFORE calling the verifier, so
/// an online guessing loop stops spending a store read per attempt. The composite
/// (peer, key id) partition keeps that bound per attacking address.
@@ -407,7 +407,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-31 (the lockout inversion): an attacker who floods failures for a victim's key id from its
+ /// Lockout inversion: an attacker who floods failures for a victim's key id from its
/// own address must not deny that key to the legitimate holder. The holder presents the correct
/// secret from a different transport peer and authenticates on the first attempt — the verifier
/// is reached and the RPC succeeds.
@@ -454,7 +454,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-31 layer 2: failures for one key id sprayed across more distinct peers than
+ /// Layer 2: failures for one key id sprayed across more distinct peers than
/// ApiKeyFailureAggregateLimit put that key id into probe mode globally, so a
/// rotating-source attacker gets at most one verifier call per probe interval.
///
@@ -515,7 +515,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-31: the success-reset path stays reachable while throttled. A throttled partition admits
+ /// The success-reset path stays reachable while throttled. A throttled partition admits
/// one probe per interval; the correct secret rides that slot, authenticates, and fully clears
/// both limiter layers, so the next wrong attempt is
/// rather than .
@@ -572,7 +572,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
///
- /// SEC-32: only a validly shaped mxgw_<keyId>_<secret> token mints a key-id
+ /// Only a validly shaped mxgw_<keyId>_<secret> token mints a key-id
/// partition. Junk tokens of varied shapes all collapse onto the sender's transport-peer fallback
/// partition, so a spray cannot mint one tracked entry per invented token.
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/ChannelWorkerClient.cs b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/ChannelWorkerClient.cs
index 378d125..67bdf24 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/ChannelWorkerClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/ChannelWorkerClient.cs
@@ -61,6 +61,7 @@ public sealed class ChannelWorkerClient(string sessionId, ChannelReader
+ /// Completes immediately because the fake holds no resources.
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
index 7c6881a..650c944 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/TestHostEnvironmentInitializer.cs
@@ -85,7 +85,7 @@ internal static class TestHostEnvironmentInitializer
Environment.SetEnvironmentVariable("Secrets__SqlitePath", secretsPath);
}
- // Starting the full host eagerly opens the auth SQLite store. Since SEC-33 the shipped
+ // Starting the full host eagerly opens the auth SQLite store. The shipped
// appsettings.json no longer carries an Authentication:SqlitePath, and the CommonApplicationData
// code default resolves under an unwritable /usr/share on macOS. Point every host-building test at
// a per-process temp store (same pattern as Secrets__SqlitePath above) so host-start tests are
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Conversion/MxStatusProxyConverterTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Conversion/MxStatusProxyConverterTests.cs
index 8539640..fbd9a0b 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Conversion/MxStatusProxyConverterTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Conversion/MxStatusProxyConverterTests.cs
@@ -108,7 +108,7 @@ public sealed class MxStatusProxyConverterTests
///
/// Verifies that repeated conversions of the same status type produce
- /// identical results. WRK-06 caches the resolved FieldInfo objects per
+ /// identical results. The converter caches the resolved FieldInfo objects per
/// type after the first conversion; the cached path must yield the same
/// message the uncached first call produced.
///
@@ -137,7 +137,7 @@ public sealed class MxStatusProxyConverterTests
///
/// Verifies every accessor strategy converts the same status values
- /// identically. PERF-20 reads a public field of a publicly visible type
+ /// identically. The converter reads a public field of a publicly visible type
/// through a delegate compiled from an expression tree instead of
/// FieldInfo.GetValue; a field type whose conversion to int is not
/// a lossless widening () and a type the
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 8ab6d0b..75bbe1e 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
@@ -521,7 +521,7 @@ public sealed class WorkerFrameProtocolTests
/// Control-frame completion decoupling. The boundary flush is charged per class run, not per
/// control frame: a pass carrying nothing but control frames still pays exactly one flush. Flushing
/// after every control frame
- /// would reinstate the syscall-per-heartbeat cost WRK-12 removed.
+ /// would reinstate the syscall-per-heartbeat cost the earlier per-frame flush design incurred.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -592,7 +592,7 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// Verifies a per-frame rejection does not burn a sequence number (WRK-23). The sequence is a
+ /// Verifies a per-frame rejection does not burn a sequence number. The sequence is a
/// diagnostic counter, so a gap breaks nothing functionally — but an operator correlating a pipe
/// capture reads a gap as a lost frame and chases a bug that does not exist, and the gap-free
/// guarantee the concurrent-write test asserts would otherwise only hold until the first
@@ -664,7 +664,7 @@ public sealed class WorkerFrameProtocolTests
///
/// Verifies a negotiated frame maximum below the worker floor is rejected as
- /// InvalidConfiguration (WRK-24), and that exactly the floor is adopted. The floor matches
+ /// InvalidConfiguration and that exactly the floor is adopted. The floor matches
/// the gateway's own GatewayOptionsValidator.MinimumMaxMessageBytes, so the worker never
/// rejects a value the gateway's validator accepts, yet a nonsensical tiny value faults at the
/// handshake instead of leaving a session that fails every later frame.
@@ -684,7 +684,7 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// WRK-22 / IPC-26. A WriteAsync cancelled while it waits for the write lock must never
+ /// A WriteAsync cancelled while it waits for the write lock must never
/// have its frame written by the next lock-holder. Writer A holds the lock mid-write (blocked in
/// the stream); an event write is queued and then cancelled; when A is released and a later
/// control frame drains, the wire carries A's frame and the control frame only — the cancelled
@@ -727,7 +727,7 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// NEXT-04. A frame claimed by the draining lock-holder before its caller's cancellation lands
+ /// A frame claimed by the draining lock-holder before its caller's cancellation lands
/// is abandoned — the cancelled caller never awaits its completion. If the wire write then
/// faults, the tombstone path's fault-observing continuation must still observe the exception
/// so it never surfaces as .
@@ -791,7 +791,7 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// WRK-22 / IPC-26, the review's shutdown scenario. A cancelled event frame queued before a
+ /// Shutdown scenario: a cancelled event frame queued before a
/// shutdown-ack control frame must not trail the ack on the wire: the tombstone rule plus the
/// control-before-event scheduler keeps the ack the last frame written.
///
@@ -830,9 +830,9 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// WRK-25. The batch entry point enqueues a whole event burst under one lock acquisition and
+ /// The batch entry point enqueues a whole event burst under one lock acquisition and
/// drains it together, so N events cost exactly one flush and reach the wire in batch order with
- /// monotonic sequences — the coalescing WRK-12 shipped, now on the event hot path.
+ /// monotonic sequences — the flush coalescing now on the event hot path.
///
/// A task that represents the asynchronous operation.
[Fact]
@@ -868,7 +868,7 @@ public sealed class WorkerFrameProtocolTests
}
///
- /// WRK-25. Control-before-event still holds mid-batch: a control frame queued while a batch is
+ /// Control-before-event still holds mid-batch: a control frame queued while a batch is
/// draining jumps ahead of the batch's remaining events.
///
/// A task that represents the asynchronous operation.
@@ -1223,7 +1223,7 @@ public sealed class WorkerFrameProtocolTests
// A MemoryStream whose first write blocks until released and whose second write blocks until
// released and then throws, so a test can abandon a claimed frame by cancellation and fault its
- // wire write afterwards (NEXT-04).
+ // wire write afterwards.
private sealed class SecondWriteFaultingGatedStream : MemoryStream
{
private readonly SemaphoreSlim _firstRelease = new SemaphoreSlim(0);
@@ -1235,6 +1235,8 @@ public sealed class WorkerFrameProtocolTests
private readonly string _faultMessage;
private int _writeCount;
+ /// Initializes a new instance of the class.
+ /// The message of the exception thrown by the second write.
public SecondWriteFaultingGatedStream(string faultMessage)
{
_faultMessage = faultMessage;
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 09df002..033b5c8 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
@@ -20,7 +20,7 @@ public sealed class WorkerPipeSessionTests
private const string SessionId = "session-1";
private const string Nonce = "nonce-secret";
- // Byte-heavy drain fixture (WRK-21). 10,000 events at ~1.7 KiB each is ~17 MB of queue — far
+ // Byte-heavy drain fixture. 10,000 events at ~1.7 KiB each is ~17 MB of queue — far
// more than one frame — so DrainEvents must truncate.
//
// Two limits below are harness accommodations, not properties of the fix. PipePair runs both
@@ -559,7 +559,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// The WRK-21 repro. A queue full of byte-heavy events (large string values — the payload
+ /// The repro for the oversized drain reply. A queue full of byte-heavy events (large string values — the payload
/// profile this gateway exists for) used to make DrainEvents max_events = 0 build a
/// reply above the negotiated frame maximum: the writer rejected the frame, the exception
/// unwound the session, and the already-dequeued events were gone. The drain is now
@@ -703,7 +703,7 @@ public sealed class WorkerPipeSessionTests
{
// The lowest Worker.MaxMessageBytes GatewayOptionsValidator permits: the public gRPC floor
// (1024) plus the 64 KiB envelope-overhead reserve. The naive budget — frame max less the
- // two reserves the DrainEvents budget subtracts (IPC-33) — would be negative here; the
+ // two reserves the DrainEvents budget subtracts — would be negative here; the
// floored budget is half of the frame max (~33 KiB).
const uint validatorFloorFrameMax = 1024 + (64 * 1024);
using CancellationTokenSource cancellation = new(TimeSpan.FromSeconds(60));
@@ -761,7 +761,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// Verifies the control-reply write seam is not session-fatal on size (WRK-21 backstop). The
+ /// Verifies the control-reply write seam is not session-fatal on size (the drain backstop). The
/// reply builders size their payloads, so this path needs a deliberately budget-blind drain
/// to reach — but that is the point: a future command or a sizing bug must degrade to an
/// error reply for that correlation, never to a dead session.
@@ -859,7 +859,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// IPC-30. An event above the negotiated frame maximum is undeliverable end to end (the pipe
+ /// An event above the negotiated frame maximum is undeliverable end to end (the pipe
/// maximum sits only an envelope reserve above the public gRPC cap), so the session stays
/// fatal by design — but the death must be structured: a WorkerFault naming the event, with
/// no value payload in it, before the process exits. Silently dropping the event or
@@ -915,7 +915,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-31, the other side of the invariant. The graceful path leaves the message loop
+ /// The other side of the transport-ownership invariant. The graceful path leaves the message loop
/// through its return after the shutdown ack, with that iteration's read already
/// awaited — so there is no abandoned read for teardown to account for. Pinning this keeps
/// the new disposal-and-observe step a pure no-op on the path production takes every time a
@@ -955,7 +955,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-31. The session now owns and closes the transport rather than leaving it to
+ /// The session now owns and closes the transport rather than leaving it to
/// WorkerPipeClient's using, because the read it unblocks has to be observed
/// while the session still holds it. This asserts the closure actually happens on the
/// session's own timeline: the gateway end of the pipe must see disconnection while
@@ -1250,7 +1250,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-27. An STA call outside the command dispatcher (the alarm poll) advertises itself on
+ /// An STA call outside the command dispatcher (the alarm poll) advertises itself on
/// the heartbeat snapshot's StaCallInProgress flag, and the watchdog grants it the same
/// grace-to-ceiling suppression as a dispatched command: stale STA activity within the ceiling
/// does not fault while the flag is set, but stale activity beyond the ceiling faults anyway.
@@ -1340,8 +1340,8 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-25. The event drain loop submits a whole drained batch through the writer's batch entry
- /// point, so a burst of 128 events costs one flush, not 128 — the assertion the WRK-12
+ /// The event drain loop submits a whole drained batch through the writer's batch entry
+ /// point, so a burst of 128 events costs one flush, not 128 — the assertion the
/// tracking claim needed to actually hold on the event hot path.
///
/// A task that represents the asynchronous operation.
@@ -1413,7 +1413,7 @@ public sealed class WorkerPipeSessionTests
}
///
- /// WRK-24. A GatewayHello negotiating a frame maximum below the worker floor faults at the
+ /// A GatewayHello negotiating a frame maximum below the worker floor faults at the
/// handshake with a fault frame rather than being adopted — mirroring the above-ceiling
/// handshake behavior — so a nonsensical tiny value never leaves a session that fails every
/// later frame. No message loop is entered.
@@ -2338,7 +2338,7 @@ public sealed class WorkerPipeSessionTests
public sealed class AbandonedPipeReadTeardownTests
{
///
- /// WRK-31. A fault exit unwinds the message loop while its frame read is still pending,
+ /// A fault exit unwinds the message loop while its frame read is still pending,
/// and on net48 nothing can cancel that read — NamedPipeClientStream.ReadAsync
/// ignores the token, so only closing the handle ends it. The session must therefore
/// dispose the transport itself and account for the read that disposal unblocks: the
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
index 7533db1..e8725a6 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
@@ -2166,14 +2166,17 @@ public sealed class MxAccessCommandExecutorTests
///
private sealed class CompletionCacheEventSink : IMxAccessEventSink, IWriteCompletionCacheProvider
{
+ ///
public MxAccessWriteCompletionCache WriteCompletionCache { get; } = new MxAccessWriteCompletionCache();
+ ///
public void Attach(
object mxAccessComObject,
string sessionId)
{
}
+ ///
public void Detach()
{
}
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventMapperTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventMapperTests.cs
index 1194d0f..e7c6149 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventMapperTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventMapperTests.cs
@@ -239,14 +239,14 @@ public sealed class MxAccessEventMapperTests
}
///
- /// Verifies the exact-format fast path PERF-20 added in front of the
+ /// Verifies the exact-format fast path added in front of the
/// general parse chain returns exactly what that chain returned. The
/// cases cover the captured MXAccess shape (which the fast path is meant
/// to catch on a US-shaped host), its zero-padded and second-precision
/// siblings, and strings the derived formats cannot match — an ISO
/// round-trip form, a long-date form, and a day-first European form —
/// which must fall through to the unchanged two-stage chain. The
- /// expectation is computed with the pre-PERF-20 chain in this test, so it
+ /// expectation is computed with the original chain in this test, so it
/// holds on any host culture: the fast path is a shortcut, never a
/// different answer.
///
@@ -353,8 +353,8 @@ public sealed class MxAccessEventMapperTests
}
///
- /// The parse chain exactly as it stood before PERF-20 added the
- /// exact-format stage, used as the parity oracle above.
+ /// The parse chain exactly as it stood before the
+ /// exact-format stage was added, used as the parity oracle above.
///
/// Timestamp string to parse.
/// The parsed UTC timestamp on success.
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventQueueTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventQueueTests.cs
index 8d4681d..c5de83a 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventQueueTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessEventQueueTests.cs
@@ -37,8 +37,7 @@ public sealed class MxAccessEventQueueTests
///
/// Verifies that Enqueue takes ownership of the passed event instead of
/// cloning it: the dequeued instance is the very reference passed in, and
- /// the worker sequence/timestamp are stamped on that same instance
- /// (WRK-11).
+ /// the worker sequence/timestamp are stamped on that same instance.
///
[Fact]
public void Enqueue_TakesOwnershipOfPassedEventInstance()
@@ -105,7 +104,7 @@ public sealed class MxAccessEventQueueTests
///
/// Verifies the byte-budgeted drain stops before the budget is exceeded, leaves the
- /// remainder queued in order, and reports the exact remaining count (WRK-21). Events that
+ /// remainder queued in order, and reports the exact remaining count. Events that
/// do not fit must never be dequeued — dequeuing them is how the pre-fix drain lost events
/// when the reply frame was rejected.
///
@@ -184,7 +183,7 @@ public sealed class MxAccessEventQueueTests
}
///
- /// The no-loss half of the WRK-21 acceptance criterion, at full scale. Draining the review's
+ /// The no-loss half of the drain guarantee, at full scale. Draining the review's
/// 10,000 byte-heavy events under a budget that fits only a fraction of them per call must
/// return every event exactly once and in order: the pre-fix drain removed events from the
/// queue before the reply was sized, so a rejected frame destroyed them. This runs at the
@@ -258,7 +257,7 @@ public sealed class MxAccessEventQueueTests
/// Brackets the byte budget's per-event charge to the exact serialized size of the event.
/// The queue measures that size once at enqueue rather than during the drain, so this pins
/// the two ends of the charge against the very instance the queue holds: a budget one byte
- /// short must refuse the head (and leave it queued, WRK-21), and a budget of exactly the
+ /// short must refuse the head (and leave it queued), and a budget of exactly the
/// charge must ship it. An undercharge — sizing the event before Enqueue stamps its worker
/// sequence and timestamp, say — passes the first probe and breaks the frame guarantee; an
/// overcharge of even one byte fails the second. The preStamped case covers an event
@@ -371,7 +370,7 @@ public sealed class MxAccessEventQueueTests
}
///
- /// The other half of the WRK-21 head guarantee: a head refused for its size is drained
+ /// The other half of the head guarantee: a head refused for its size is drained
/// unchanged by a later call whose budget fits it. The size the queue charges lives with the
/// event across calls, so a refused attempt must neither consume nor alter it — and the
/// refusal itself is justified by the event's real serialized size.
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
index 3ff55fe..4659d70 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
@@ -527,7 +527,7 @@ public sealed class MxAccessStaSessionTests
}
///
- /// WRK-27. While the alarm poll's PollOnce is executing on the STA, a heartbeat captured mid-poll
+ /// While the alarm poll's PollOnce is executing on the STA, a heartbeat captured mid-poll
/// must report so the watchdog
/// grants the poll the same grace-to-ceiling suppression as a dispatched command; once the poll
/// returns the flag clears. PollOnce is blocked on a gate so the heartbeat can be captured while
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/WnWrapAlarmConsumerXmlTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/WnWrapAlarmConsumerXmlTests.cs
index 4ecac2a..afef255 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/WnWrapAlarmConsumerXmlTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/WnWrapAlarmConsumerXmlTests.cs
@@ -319,7 +319,7 @@ public sealed class WnWrapAlarmConsumerXmlTests
}
// -------------------------------------------------------------------------
- // Truncation cliff (Task 23). GetXmlCurrentAlarms2 caps its reply at
+ // Truncation cliff. GetXmlCurrentAlarms2 caps its reply at
// maxAlmCnt with no "more available" flag. Before the guard, a capped fetch
// shrank the retained snapshot, and every alarm past the cap vanished from
// SnapshotActiveAlarms — which the gateway's reconcile pass reads as a
@@ -587,7 +587,7 @@ public sealed class WnWrapAlarmConsumerXmlTests
}
// -------------------------------------------------------------------------
- // Single-pass parse parity (Task 23). The per-field SelectSingleNode calls
+ // Single-pass parse parity. The per-field SelectSingleNode calls
// were replaced by one walk over ChildNodes; these pin the semantics that
// walk has to reproduce.
// -------------------------------------------------------------------------
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 456205d..016b042 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
@@ -494,7 +494,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
///
/// Enqueues a batch of worker events atomically under one lock so the drain loop cannot
/// observe a partial batch. Lets a test assert the drain loop coalesces a whole batch into one
- /// flush (WRK-25) without racing a mid-enqueue drain that would split the batch.
+ /// flush without racing a mid-enqueue drain that would split the batch.
///
/// The events to enqueue in order.
public void EnqueueEvents(IEnumerable workerEvents)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs b/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
index 9aad71f..c03cfcc 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
@@ -263,6 +263,11 @@ public sealed class MxStatusProxyConverter
///
private readonly struct StatusFields
{
+ /// Initializes a new instance of the struct.
+ /// Accessor for the raw success member.
+ /// Accessor for the raw category member.
+ /// Accessor for the raw detected-by member.
+ /// Accessor for the raw detail member.
public StatusFields(
Func