docs(src): fix CommentChecker findings across src/ — 1,032 → 5 (all false positives)
Comment/XML-doc changes only, no code logic: - strip project-tracking references (WP*, P*-*, row-NN, #NN, Task N) from comments, keeping the explanatory rationale - add missing summaries, <param>, <returns>, <typeparam> and <inheritdoc/> - replace misused <inheritdoc/> with real docs; where <inheritdoc/> was combined with useful remarks, move the rationale into // comments - drop stale replicationActor <param> on DeploymentManagerActor ctor Remaining 5 are false positives (CWE-1236 x2, failures-1, year-0001, M365). Build 0 errors / 0 warnings.
This commit is contained in:
@@ -763,7 +763,7 @@ public static class AuditEndpoints
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// CSV helpers — 24 columns, same order/naming as the JSONL export
|
||||
// (AuditExportRow property declaration order; arch-review 2026-08-19 P6-7)
|
||||
// (AuditExportRow property declaration order)
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
public const string CsvHeader =
|
||||
@@ -783,7 +783,7 @@ public static class AuditEndpoints
|
||||
/// <see cref="AuditExportRow.ResponseSummary"/>, <see cref="AuditExportRow.Extra"/>) are run
|
||||
/// through <see cref="NeedsFormulaNeutralization"/> before RFC 4180 quoting so a leading
|
||||
/// <c>=</c>/<c>+</c>/<c>-</c>/<c>@</c>/TAB/CR can't be interpreted as a formula or DDE
|
||||
/// trigger by a spreadsheet application (CWE-1236). GUID/enum/numeric/date/bool columns the
|
||||
/// trigger by a spreadsheet application (CSV formula injection). GUID/enum/numeric/date/bool columns the
|
||||
/// exporter formats itself are never neutralized — none of them can start with a trigger
|
||||
/// character, and neutralizing a signed numeric column would corrupt it.
|
||||
/// </summary>
|
||||
@@ -833,7 +833,7 @@ public static class AuditEndpoints
|
||||
return;
|
||||
}
|
||||
|
||||
// OWASP CSV-injection neutralization (CWE-1236): a free-text cell whose
|
||||
// OWASP CSV-injection neutralization (CSV formula injection): a free-text cell whose
|
||||
// first character would be interpreted by a spreadsheet application as a
|
||||
// formula/DDE trigger is prefixed with a literal single quote. Applied
|
||||
// BEFORE RFC 4180 quoting, and only to free-text columns — never to the
|
||||
|
||||
@@ -18,6 +18,9 @@ internal static class ConfigSecretScrubber
|
||||
private static readonly string[] SecretNameFragments =
|
||||
["password", "secret", "token", "apikey", "credential", "passphrase"];
|
||||
|
||||
/// <summary>Determines whether a property name looks like it holds a secret.</summary>
|
||||
/// <param name="propertyName">The property name to test.</param>
|
||||
/// <returns>True when the name contains a secret-like fragment.</returns>
|
||||
internal static bool IsSecretName(string propertyName)
|
||||
{
|
||||
foreach (var fragment in SecretNameFragments)
|
||||
|
||||
@@ -193,7 +193,7 @@ public class DebugStreamHub : Hub
|
||||
CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
|
||||
});
|
||||
|
||||
// arch-review 2026-08-19 P6-6: the client may have disconnected while
|
||||
// The client may have disconnected while
|
||||
// StartStreamAsync was in flight (up to 30s). OnDisconnectedAsync already ran
|
||||
// and found no session id to release, so publishing it here would leave the
|
||||
// session registered in the singleton DebugStreamService — whose keepalive
|
||||
@@ -255,7 +255,7 @@ public class DebugStreamHub : Hub
|
||||
/// <summary>
|
||||
/// Atomically removes and returns the session id registered for this connection, so a
|
||||
/// release path and the late publish in <see cref="SubscribeInstance"/> cannot both
|
||||
/// claim (or both miss) the same session — see P6-6 there.
|
||||
/// claim (or both miss) the same session — see there.
|
||||
/// </summary>
|
||||
/// <returns>The session id that was registered, or <see langword="null"/> if none was.</returns>
|
||||
private string? TakeSessionId()
|
||||
@@ -274,7 +274,7 @@ public class DebugStreamHub : Hub
|
||||
/// <inheritdoc />
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
// P6-6: mark the connection gone BEFORE releasing, so a SubscribeInstance still
|
||||
// Mark the connection gone BEFORE releasing, so a SubscribeInstance still
|
||||
// awaiting StartStreamAsync sees the flag and stops its own session rather than
|
||||
// registering it against a connection nothing will ever unsubscribe.
|
||||
lock (Context.Items)
|
||||
|
||||
@@ -96,12 +96,16 @@ public sealed class FlowDebugRunner
|
||||
private readonly Func<DateTimeOffset> _now;
|
||||
|
||||
/// <summary>Creates the runner.</summary>
|
||||
/// <param name="logger">Logger for run diagnostics.</param>
|
||||
public FlowDebugRunner(ILogger<FlowDebugRunner> logger)
|
||||
: this(logger, Task.Delay, () => DateTimeOffset.UtcNow)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Creates the runner with an injectable delay and clock (tests).</summary>
|
||||
/// <param name="logger">Logger for run diagnostics.</param>
|
||||
/// <param name="delay">Delay function used for polling waits.</param>
|
||||
/// <param name="now">Clock returning the current UTC time.</param>
|
||||
public FlowDebugRunner(
|
||||
ILogger<FlowDebugRunner> logger,
|
||||
Func<TimeSpan, CancellationToken, Task> delay,
|
||||
@@ -125,6 +129,11 @@ public sealed class FlowDebugRunner
|
||||
/// registered none (a test composition root) collects raw but is still capped.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="sp">The request-scoped service provider.</param>
|
||||
/// <param name="cmd">The command to execute.</param>
|
||||
/// <param name="user">The authenticated operator.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>The run result with the collected trace rows.</returns>
|
||||
public Task<FlowDebugRunResult> RunMethodAsync(
|
||||
IServiceProvider sp, FlowDebugRunMethodCommand cmd, AuthenticatedUser user, CancellationToken ct)
|
||||
=> WithinCommandBudgetAsync(sp, (deadline, token) => RunMethodCoreAsync(sp, cmd, user, deadline, token), ct);
|
||||
@@ -233,6 +242,11 @@ public sealed class FlowDebugRunner
|
||||
/// Live run of a value-change trigger (design §5.3/§5.4): traced routed write through the
|
||||
/// site's normal path, then poll the site's trace rows for the spawned run(s).
|
||||
/// </summary>
|
||||
/// <param name="sp">The request-scoped service provider.</param>
|
||||
/// <param name="cmd">The command to execute.</param>
|
||||
/// <param name="user">The authenticated operator.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>The run result with the collected trace rows.</returns>
|
||||
public Task<FlowDebugRunResult> RunValueChangeAsync(
|
||||
IServiceProvider sp, FlowDebugRunValueChangeCommand cmd, AuthenticatedUser user, CancellationToken ct)
|
||||
=> WithinCommandBudgetAsync(sp, (deadline, token) => RunValueChangeCoreAsync(sp, cmd, user, deadline, token), ct);
|
||||
@@ -269,6 +283,11 @@ public sealed class FlowDebugRunner
|
||||
/// rather than through <see cref="RouteHelper"/> is deliberate: the helper emits its own
|
||||
/// always-on RouteCall row with no operator actor, which would give the graph two roots.
|
||||
/// </summary>
|
||||
/// <param name="sp">The request-scoped service provider.</param>
|
||||
/// <param name="cmd">The command to execute.</param>
|
||||
/// <param name="user">The authenticated operator.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>The run result with the collected trace rows.</returns>
|
||||
public Task<FlowDebugRunResult> RunScriptAsync(
|
||||
IServiceProvider sp, FlowDebugRunScriptCommand cmd, AuthenticatedUser user, CancellationToken ct)
|
||||
=> WithinCommandBudgetAsync(sp, (deadline, token) => RunScriptCoreAsync(sp, cmd, user, deadline, token), ct);
|
||||
@@ -570,6 +589,11 @@ public sealed class FlowDebugRunner
|
||||
}
|
||||
|
||||
/// <summary>Replay (design §7.1): the stored ScriptTrace chain for any execution id.</summary>
|
||||
/// <param name="sp">The request-scoped service provider.</param>
|
||||
/// <param name="cmd">The replay command naming the execution.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <param name="user">The authenticated operator.</param>
|
||||
/// <returns>The reconstructed run result read from the stored trace rows.</returns>
|
||||
public async Task<FlowDebugRunResult> ReplayAsync(
|
||||
IServiceProvider sp, FlowDebugReplayCommand cmd, CancellationToken ct, AuthenticatedUser user)
|
||||
{
|
||||
@@ -627,8 +651,11 @@ public sealed class FlowDebugRunner
|
||||
|
||||
private sealed class TraceReadBatch(Guid[] executionIds, DateTime sinceUtc)
|
||||
{
|
||||
/// <summary>Execution ids whose trace rows are being read.</summary>
|
||||
public Guid[] ExecutionIds { get; } = executionIds;
|
||||
/// <summary>Lower bound (UTC) for the next read.</summary>
|
||||
public DateTime SinceUtc { get; set; } = sinceUtc;
|
||||
/// <summary>Keyset cursor: the last event id already consumed, or null.</summary>
|
||||
public string? AfterEventId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,11 @@ public class ManagementActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>Audited database-only application boundary shared by UI and management envelopes.</summary>
|
||||
/// <param name="services">Scoped service provider used to resolve handlers and repositories.</param>
|
||||
/// <param name="command">The configuration command to execute.</param>
|
||||
/// <param name="user">The authenticated user the command runs as.</param>
|
||||
/// <param name="clientIp">Optional client IP address recorded in the audit entry.</param>
|
||||
/// <returns>The command's result object, or <c>null</c> when the command produces none.</returns>
|
||||
public static async Task<object?> ExecuteConfigurationCommandAsync(IServiceProvider services, object command, AuthenticatedUser user, string? clientIp = null)
|
||||
{
|
||||
if (!IsConfigurationCommand(command)) throw new ArgumentException("Not a configuration command.", nameof(command));
|
||||
@@ -1496,8 +1501,8 @@ public class ManagementActor : ReceiveActor
|
||||
// submit device writes to their permitted sites — same rule C2 applies to
|
||||
// DeployArtifacts, on a higher-consequence path. Checked before the row exists.
|
||||
//
|
||||
// The unresolvable case is fail-CLOSED and answered BEFORE the "not found"
|
||||
// (arch-review 2026-08-19 P6-5): resolving first and reporting not-found made
|
||||
// The unresolvable case is fail-CLOSED and answered BEFORE the "not found":
|
||||
// resolving first and reporting not-found made
|
||||
// this handler a site-identifier existence oracle for an out-of-scope caller,
|
||||
// who now gets the same scope denial whether or not the site exists.
|
||||
var siteRepo = sp.GetRequiredService<ISiteRepository>();
|
||||
@@ -1560,7 +1565,7 @@ public class ManagementActor : ReceiveActor
|
||||
// the row's target site — checked BEFORE the TTL/self-approval/CAS chain so an
|
||||
// out-of-scope verifier can neither consume the Pending transition nor relay.
|
||||
//
|
||||
// It is also checked BEFORE the status test (arch-review 2026-08-19 P6-5): the
|
||||
// It is also checked BEFORE the status test: the
|
||||
// "is 'Executed', not Pending" message told an out-of-scope caller both that the
|
||||
// id existed and what had happened to it. An out-of-scope caller now gets the
|
||||
// same scope denial for every id, existing or not.
|
||||
@@ -1701,7 +1706,7 @@ public class ManagementActor : ReceiveActor
|
||||
row.ExecutionError = error;
|
||||
|
||||
// UpdateAsync overwrites all columns -> pass the fully-populated entity.
|
||||
// Safe as a blind write (arch-review 2026-08-19 P6-1): winning the
|
||||
// Safe as a blind write: winning the
|
||||
// Pending->Approved CAS above gives this leg EXCLUSIVE ownership of the row from
|
||||
// that point on. Every other writer transitions only out of Pending —
|
||||
// TryMarkApprovedAsync, TryMarkRejectedAsync and TryMarkExpiredAsync (both the
|
||||
@@ -1738,8 +1743,7 @@ public class ManagementActor : ReceiveActor
|
||||
// Site scope (arch-review R2 N3): the rejecting Verifier must be permitted on
|
||||
// the row's target site — checked BEFORE the TTL/self-approval chain, and (as on
|
||||
// approve) BEFORE the status test, so the not-found/status errors stop being an
|
||||
// existence-and-status oracle for an out-of-scope caller (arch-review 2026-08-19
|
||||
// P6-5). The CAS below is unchanged.
|
||||
// existence-and-status oracle for an out-of-scope caller. The CAS below is unchanged.
|
||||
await EnforceSiteScopeForIdentifier(sp, user, entity.SiteId);
|
||||
|
||||
if (!string.Equals(entity.Status, "Pending", StringComparison.Ordinal))
|
||||
@@ -1759,7 +1763,7 @@ public class ManagementActor : ReceiveActor
|
||||
"A secured write cannot be verified by its submitter.");
|
||||
|
||||
// Compare-and-swap: guards the approve-vs-reject race exactly as approve's own
|
||||
// CAS guards the two-verifier race (arch-review 2026-08-19 P6-1). The status
|
||||
// CAS guards the two-verifier race. The status
|
||||
// check above is a stale read — commands run concurrently, each on its own DI
|
||||
// scope and across both central nodes on one shared MS SQL — so a concurrent
|
||||
// approve can win its CAS and enter its multi-second WriteTagAsync relay in the
|
||||
@@ -2003,8 +2007,8 @@ public class ManagementActor : ReceiveActor
|
||||
/// Lists data connections, constrained to the caller's permitted sites.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Arch-review 2026-08-19 P6-4. The list used to take no user at all and return
|
||||
/// EVERY site's connections, which nullified the row-98 fail-closed gate on
|
||||
/// The list used to take no user at all and return
|
||||
/// EVERY site's connections, which nullified the fail-closed gate on
|
||||
/// <see cref="HandleGetDataConnection"/> — Get denied exactly what List handed
|
||||
/// over, and the secret-elided <see cref="DataConnectionPublicShape"/> still
|
||||
/// leaked site topology plus an id-existence oracle. Scoping now mirrors
|
||||
@@ -3872,7 +3876,7 @@ public class ManagementActor : ReceiveActor
|
||||
|
||||
private static async Task<object?> HandleDebugSnapshot(IServiceProvider sp, DebugSnapshotCommand cmd, AuthenticatedUser user)
|
||||
{
|
||||
// Fail-CLOSED before the not-found (arch-review 2026-08-19 P6-5): reporting
|
||||
// Fail-CLOSED before the not-found: reporting
|
||||
// "Instance {id} not found" ahead of the scope check made this handler an
|
||||
// instance-id existence oracle for an out-of-scope caller. The scope denial is
|
||||
// now the same answer whether or not the instance exists.
|
||||
|
||||
@@ -19,7 +19,7 @@ public static class ManagementEndpoints
|
||||
|
||||
/// <summary>
|
||||
/// Shared options for the per-request command payload JSON parse in
|
||||
/// <see cref="ParseCommand"/> (perf remediation, arch-review WP1.5) — avoids
|
||||
/// <see cref="ParseCommand"/> — avoids
|
||||
/// allocating a new <see cref="JsonSerializerOptions"/> per inbound management
|
||||
/// request. Settings preserved exactly.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user