docs: strip task-tracking IDs from code comments and fill missing XML docs
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m16s
ci / java (push) Successful in 2m5s
ci / portable (push) Failing after 5m9s

Tracking IDs are review bookkeeping that rots in shipped source; the rationale they tagged is kept. Comment-only change (CommentChecker 458 -> 16 false positives).
This commit is contained in:
Joseph Doherty
2026-10-07 15:34:32 -04:00
parent f2e0861709
commit f40409a688
115 changed files with 549 additions and 411 deletions
@@ -347,13 +347,13 @@ public static class MxGatewayClientCli
/// <summary>
/// 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.
/// </summary>
private const string DefaultVerifyPasswordEnvironmentName = "MXGATEWAY_VERIFY_PASSWORD";
/// <summary>
/// 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.
/// </summary>
private const string LegacyVerifyPasswordEnvironmentName = "MXGATEWAY_VERIFY_USER_PASSWORD";
@@ -379,14 +379,14 @@ public static class MxGatewayClientCli
}
/// <summary>
/// Resolves the effective MXAccess verify-user credential in the CLI-45
/// Resolves the effective MXAccess verify-user credential in this
/// order: <c>--password</c>, the deprecated <c>--verify-user-password</c>
/// alias, the environment variable named by <c>--password-env</c> (default
/// <c>MXGATEWAY_VERIFY_PASSWORD</c>), then the deprecated
/// <c>MXGATEWAY_VERIFY_USER_PASSWORD</c>. 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 <see cref="TryResolveApiKey" />.
/// the error-redaction catch block can strip it from any surfaced error,
/// mirroring <see cref="TryResolveApiKey" />.
/// </summary>
private static string? TryResolveVerifyUserPassword(CliArguments arguments)
{
@@ -416,7 +416,7 @@ public static class MxGatewayClientCli
/// Resolves the verify-user credential for <c>authenticate-user</c>, 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.
/// </summary>
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
}
/// <summary>
/// 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.
/// </summary>
@@ -134,6 +134,7 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>Verifies that write-secured builds a WriteSecured command with the value and user ids.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task RunAsync_AuthenticateUser_BuildsCommandAndDoesNotEchoCredential()
{
@@ -218,9 +220,10 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task RunAsync_AuthenticateUser_ErrorOutput_RedactsCredential()
{
@@ -248,7 +251,7 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>
/// CLI-45: <c>--password</c> is the primary credential flag, matching the other
/// <c>--password</c> is the primary credential flag, matching the other
/// four CLIs. The credential reaches the wire but never stdout/stderr.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
@@ -290,10 +293,12 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>
/// CLI-45: the credential is read from the environment variable named by
/// the credential is read from the environment variable named by
/// <c>--password-env</c>, whose default is the canonical
/// <c>MXGATEWAY_VERIFY_PASSWORD</c> shared by all five CLIs.
/// </summary>
/// <param name="passwordEnvArgument">The value passed to <c>--password-env</c>, or null to use the default.</param>
/// <param name="environmentName">The environment variable that holds the credential.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
[Theory]
[InlineData(null, "MXGATEWAY_VERIFY_PASSWORD")]
@@ -340,7 +345,7 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>
/// CLI-45: the pre-rename names stay usable for one release — the deprecated
/// the pre-rename names stay usable for one release — the deprecated
/// <c>--verify-user-password</c> flag and the deprecated
/// <c>MXGATEWAY_VERIFY_USER_PASSWORD</c> environment variable both still resolve.
/// </summary>
@@ -413,7 +418,7 @@ public sealed class MxGatewayClientCliTests
}
/// <summary>
/// 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.
/// </summary>
@@ -463,6 +468,9 @@ public sealed class MxGatewayClientCliTests
private readonly string _name;
private readonly string? _original;
/// <summary>Sets the environment variable and remembers its original value.</summary>
/// <param name="name">The environment variable name.</param>
/// <param name="value">The temporary value, or null to clear it.</param>
public EnvironmentVariableScope(string name, string? value)
{
_name = name;
@@ -470,6 +478,7 @@ public sealed class MxGatewayClientCliTests
Environment.SetEnvironmentVariable(name, value);
}
/// <summary>Restores the original environment variable value.</summary>
public void Dispose()
{
Environment.SetEnvironmentVariable(_name, _original);
@@ -588,7 +597,7 @@ public sealed class MxGatewayClientCliTests
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
@@ -228,6 +228,7 @@ public sealed class MxGatewayClientSessionTests
/// <see cref="MxEventStreamItem"/> with the gap populated, while normal
/// events pass through unchanged with IsReplayGap false.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task StreamEventItemsAsync_SurfacesReplayGapSentinel()
{
@@ -430,6 +431,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that unregister builds an unregister command with the server handle.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnregisterAsync_BuildsUnregisterCommand()
{
@@ -451,6 +453,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that advise-supervisory builds the supervisory advise command.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AdviseSupervisoryAsync_BuildsAdviseSupervisoryCommand()
{
@@ -473,6 +476,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that add-buffered-item returns the item handle from the typed reply.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AddBufferedItemAsync_BuildsCommandAndReturnsItemHandle()
{
@@ -498,6 +502,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that set-buffered-update-interval builds the command with the interval.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SetBufferedUpdateIntervalAsync_BuildsCommandWithInterval()
{
@@ -520,6 +525,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that suspend builds the command and returns the reply status.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SuspendAsync_BuildsCommandAndReturnsStatus()
{
@@ -545,6 +551,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that activate builds the command and returns the reply status.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ActivateAsync_BuildsCommandAndReturnsStatus()
{
@@ -568,6 +575,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that write-secured builds a WriteSecured command with value and user ids.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteSecuredAsync_BuildsWriteSecuredCommand()
{
@@ -598,6 +606,7 @@ public sealed class MxGatewayClientSessionTests
/// natively. The client must surface that scripted failure (as an
/// <see cref="MxAccessException"/>) rather than pre-validating it away.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteSecuredAsync_SurfacesNativeFailureWhenNotAuthenticated()
{
@@ -621,6 +630,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that write-secured2 builds a WriteSecured2 command with value and timestamp.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteSecured2Async_BuildsWriteSecured2Command()
{
@@ -647,6 +657,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that authenticate-user builds the command and returns the resolved user id.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AuthenticateUserAsync_FailureDoesNotLeakCredentialInErrorMessage()
{
@@ -698,6 +710,7 @@ public sealed class MxGatewayClientSessionTests
}
/// <summary>Verifies that archestra-user-to-id builds the command and returns the resolved user id.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ArchestraUserToIdAsync_BuildsCommandAndReturnsUserId()
{
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
/// </summary>
public sealed class MxGatewaySecretRedactionTests
{
/// <summary>Test: Redact replaces every occurrence of secret.</summary>
[Fact]
public void Redact_ReplacesEveryOccurrenceOfSecret()
{
@@ -19,6 +20,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal("pw=<redacted> retry pw=<redacted> again <redacted>", result);
}
/// <summary>Test: Redact scrubs both secrets when one is substring of the other.</summary>
[Fact]
public void Redact_ScrubsBothSecretsWhenOneIsSubstringOfTheOther()
{
@@ -33,6 +35,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.DoesNotContain("secret", result, StringComparison.Ordinal);
}
/// <summary>Test: Redact with null secrets array returns message unchanged.</summary>
[Fact]
public void Redact_WithNullSecretsArray_ReturnsMessageUnchanged()
{
@@ -43,6 +46,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
/// <summary>Test: Redact with empty secrets array returns message unchanged.</summary>
[Fact]
public void Redact_WithEmptySecretsArray_ReturnsMessageUnchanged()
{
@@ -53,6 +57,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
/// <summary>Test: Redact ignores whitespace only secret.</summary>
[Fact]
public void Redact_IgnoresWhitespaceOnlySecret()
{
@@ -64,6 +69,7 @@ public sealed class MxGatewaySecretRedactionTests
Assert.Equal(message, result);
}
/// <summary>Test: Redacted preserves concrete subtype and does not chain secret bearing original.</summary>
[Fact]
public void Redacted_PreservesConcreteSubtypeAndDoesNotChainSecretBearingOriginal()
{
@@ -4,15 +4,16 @@ using ZB.MOM.WW.MxGateway.Contracts.Proto;
namespace ZB.MOM.WW.MxGateway.Client.Tests;
/// <summary>
/// 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.
/// </summary>
public sealed class MxGatewaySessionReplyContractTests
{
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AuthenticateUserAsync_RedactsEchoedCredentialInFailureMessage()
{
@@ -33,13 +34,14 @@ public sealed class MxGatewaySessionReplyContractTests
}
/// <summary>
/// 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 — <see cref="MxAccessException.Reply"/> (protocol message, diagnostic
/// message, and each MXSTATUS_PROXY diagnostic text) and <see cref="MxGatewayException.Statuses"/>
/// all carry the server-echoed credential verbatim before the fix. Both the OK+negative-HRESULT
/// and the MXACCESS_FAILURE reply route to <see cref="MxAccessException"/>, so both must scrub.
/// </summary>
/// <param name="fixture">The echoed-credential reply fixture to drive.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
[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
}
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AuthenticateUserAsync_MissingPayloadAndReturnValue_ThrowsMalformedReply()
{
@@ -87,9 +90,10 @@ public sealed class MxGatewaySessionReplyContractTests
}
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AuthenticateUserAsync_ReturnValueOnly_ResolvesReturnValue()
{
@@ -104,9 +108,10 @@ public sealed class MxGatewaySessionReplyContractTests
}
/// <summary>
/// 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.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AddBufferedItemAsync_MissingPayloadAndReturnValue_ThrowsMalformedReply()
{
@@ -32,6 +32,9 @@ public sealed class MxStatusProxyExtensionsTests
}
/// <summary>Verifies that the raw success member never overrides the authoritative category.</summary>
/// <param name="category">The status category under test.</param>
/// <param name="success">The raw success member, which must not influence the result.</param>
/// <param name="expected">The expected <c>IsSuccess</c> result.</param>
[Theory]
[InlineData(MxStatusCategory.Ok, 0, true)]
[InlineData(MxStatusCategory.Ok, 1, true)]
@@ -96,7 +96,8 @@ internal sealed class WireFakeGatewayServer : IAsyncDisposable
DefaultCallTimeout = TimeSpan.FromSeconds(30),
});
/// <inheritdoc />
/// <summary>Stops and disposes the underlying web application.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
public async ValueTask DisposeAsync()
{
await _app.StopAsync().ConfigureAwait(false);
@@ -854,6 +854,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// </summary>
/// <param name="serverHandle">The ServerHandle from register.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task UnregisterAsync(
int serverHandle,
CancellationToken cancellationToken = default)
@@ -888,6 +889,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// <param name="serverHandle">The ServerHandle from register.</param>
/// <param name="itemHandle">The ItemHandle from add-item.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task AdviseSupervisoryAsync(
int serverHandle,
int itemHandle,
@@ -985,6 +987,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// <param name="serverHandle">The ServerHandle from register.</param>
/// <param name="updateIntervalMilliseconds">The buffered update interval, in milliseconds.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task SetBufferedUpdateIntervalAsync(
int serverHandle,
int updateIntervalMilliseconds,
@@ -1125,6 +1128,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// <param name="currentUserId">The current operator user id.</param>
/// <param name="verifierUserId">The verifier (secondary approver) user id.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task WriteSecuredAsync(
int serverHandle,
int itemHandle,
@@ -1204,6 +1208,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// <param name="currentUserId">The current operator user id.</param>
/// <param name="verifierUserId">The verifier (secondary approver) user id.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task WriteSecured2Async(
int serverHandle,
int itemHandle,