docs+ui: backfill XML doc comments and finish dashboard layout pass

Adds missing <summary>/<param> XML docs across 99 server, worker, and test
files so CommentChecker reports zero issues (TreatWarningsAsErrors needs the
analyzer clean). Bundles in WIP dashboard work: NavSection extraction,
MainLayout/site.css/js styling alignment, and DashboardOptions/Auth tweaks.
This commit is contained in:
Joseph Doherty
2026-05-27 14:20:10 -04:00
parent 382861c602
commit 615b487a77
110 changed files with 1473 additions and 192 deletions
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardApiKeyManagementServiceTests
{
/// <summary>Verifies that unauthorized users cannot create API keys.</summary>
[Fact]
public async Task CreateAsync_UnauthorizedUser_DoesNotCallStore()
{
@@ -25,6 +26,7 @@ public sealed class DashboardApiKeyManagementServiceTests
Assert.Equal(0, adminStore.CreateCount);
}
/// <summary>Verifies that authorized users can create keys with secret hashing and audit trail.</summary>
[Fact]
public async Task CreateAsync_AuthorizedUser_StoresHashOfSecretAndAudits()
{
@@ -54,6 +56,7 @@ public sealed class DashboardApiKeyManagementServiceTests
&& entry.KeyId == "operator01");
}
/// <summary>Verifies that unauthorized users cannot revoke API keys.</summary>
[Fact]
public async Task RevokeAsync_UnauthorizedUser_DoesNotCallStore()
{
@@ -69,6 +72,7 @@ public sealed class DashboardApiKeyManagementServiceTests
Assert.Equal(0, adminStore.RevokeCount);
}
/// <summary>Verifies that authorized users can revoke keys with audit trail.</summary>
[Fact]
public async Task RevokeAsync_AuthorizedUser_RevokesAndAudits()
{
@@ -89,6 +93,7 @@ public sealed class DashboardApiKeyManagementServiceTests
&& entry.Details == "revoked");
}
/// <summary>Verifies that authorized users can rotate secret hashes with audit trail.</summary>
[Fact]
public async Task RotateAsync_AuthorizedUser_RotatesHashAndAudits()
{
@@ -112,6 +117,7 @@ public sealed class DashboardApiKeyManagementServiceTests
&& entry.Details == "rotated");
}
/// <summary>Verifies that unauthorized users cannot delete API keys.</summary>
[Fact]
public async Task DeleteAsync_UnauthorizedUser_DoesNotCallStore()
{
@@ -127,6 +133,7 @@ public sealed class DashboardApiKeyManagementServiceTests
Assert.Equal(0, adminStore.DeleteCount);
}
/// <summary>Verifies that authorized users can delete revoked keys with audit trail.</summary>
[Fact]
public async Task DeleteAsync_AuthorizedUser_DeletesRevokedKeyAndAudits()
{
@@ -181,6 +188,7 @@ public sealed class DashboardApiKeyManagementServiceTests
/// <c>ValidateKeyId</c> after the authorisation check. A blank key id must fail with the
/// shared "API key id is required." message before any store or audit call runs.
/// </summary>
/// <param name="blankKeyId">A blank or whitespace key identifier.</param>
[Theory]
[InlineData("")]
[InlineData(" ")]
@@ -269,26 +277,37 @@ public sealed class DashboardApiKeyManagementServiceTests
private sealed class FakeApiKeyAdminStore : IApiKeyAdminStore
{
/// <summary>Gets the count of create operations performed.</summary>
public int CreateCount { get; private set; }
/// <summary>Gets the count of revoke operations performed.</summary>
public int RevokeCount { get; private set; }
/// <summary>Gets the count of delete operations performed.</summary>
public int DeleteCount { get; private set; }
/// <summary>Gets or sets the result value returned by revoke operations.</summary>
public bool RevokeResult { get; init; }
/// <summary>Gets or sets the result value returned by rotate operations.</summary>
public bool RotateResult { get; init; }
/// <summary>Gets or sets the result value returned by delete operations.</summary>
public bool DeleteResult { get; init; }
/// <summary>Gets the last key ID revoked.</summary>
public string? LastRevokedKeyId { get; private set; }
/// <summary>Gets the last key ID deleted.</summary>
public string? LastDeletedKeyId { get; private set; }
/// <summary>Gets the last secret hash rotated.</summary>
public byte[]? LastRotatedSecretHash { get; private set; }
/// <summary>Gets the list of create requests received.</summary>
public List<ApiKeyCreateRequest> CreatedRequests { get; } = [];
/// <inheritdoc />
public Task CreateAsync(ApiKeyCreateRequest request, CancellationToken cancellationToken)
{
CreateCount++;
@@ -296,11 +315,13 @@ public sealed class DashboardApiKeyManagementServiceTests
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<IReadOnlyList<ApiKeyRecord>> ListAsync(CancellationToken cancellationToken)
{
return Task.FromResult<IReadOnlyList<ApiKeyRecord>>([]);
}
/// <inheritdoc />
public Task<bool> RevokeAsync(
string keyId,
DateTimeOffset revokedUtc,
@@ -311,6 +332,7 @@ public sealed class DashboardApiKeyManagementServiceTests
return Task.FromResult(RevokeResult);
}
/// <inheritdoc />
public Task<bool> RotateAsync(
string keyId,
byte[] secretHash,
@@ -321,6 +343,7 @@ public sealed class DashboardApiKeyManagementServiceTests
return Task.FromResult(RotateResult);
}
/// <inheritdoc />
public Task<bool> DeleteAsync(string keyId, CancellationToken cancellationToken)
{
DeleteCount++;
@@ -331,14 +354,17 @@ public sealed class DashboardApiKeyManagementServiceTests
private sealed class FakeApiKeyAuditStore : IApiKeyAuditStore
{
/// <summary>Gets the list of audit entries appended.</summary>
public List<ApiKeyAuditEntry> Entries { get; } = [];
/// <inheritdoc />
public Task AppendAsync(ApiKeyAuditEntry entry, CancellationToken cancellationToken)
{
Entries.Add(entry);
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<IReadOnlyList<ApiKeyAuditRecord>> ListRecentAsync(
int count,
CancellationToken cancellationToken)
@@ -349,8 +375,10 @@ public sealed class DashboardApiKeyManagementServiceTests
private sealed class FakeApiKeySecretHasher : IApiKeySecretHasher
{
/// <summary>Gets the last secret hashed.</summary>
public string? LastSecret { get; private set; }
/// <inheritdoc />
public byte[] HashSecret(string secret)
{
LastSecret = secret;