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:
@@ -79,7 +79,7 @@ public static class AuditQueryParamParsers
|
||||
/// the filter dimension stays unconstrained.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Register row 99 (closure defect fixed by arch-review 2026-08-19 P6-3). Three
|
||||
/// Register row 99. Three
|
||||
/// traps this closes that a bare
|
||||
/// <see cref="Enum.TryParse{TEnum}(string, bool, out TEnum)"/> does not:
|
||||
/// <list type="number">
|
||||
|
||||
@@ -4,8 +4,15 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
|
||||
/// <summary>Bounded replay data with independently retained chain-root and truncation metadata.</summary>
|
||||
public sealed record TraceEventBatch(Guid RootExecutionId, IReadOnlyList<AuditEvent> Events, bool Truncated) : IReadOnlyList<AuditEvent>
|
||||
{
|
||||
/// <summary>Gets the trace event at the given position.</summary>
|
||||
/// <param name="index">Zero-based position in <see cref="Events"/>.</param>
|
||||
/// <returns>The event at <paramref name="index"/>.</returns>
|
||||
public AuditEvent this[int index] => Events[index];
|
||||
/// <summary>Gets the number of events in the batch.</summary>
|
||||
public int Count => Events.Count;
|
||||
/// <summary>Returns an enumerator over the batch's events.</summary>
|
||||
/// <returns>An enumerator over <see cref="Events"/>.</returns>
|
||||
public IEnumerator<AuditEvent> GetEnumerator() => Events.GetEnumerator();
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public static class OpcUaReferenceForm
|
||||
/// prefix, or empty/whitespace (nothing to warn about). False only for a bare
|
||||
/// server-namespace index (<c>ns=<n>;…</c> with n ≥ 1).
|
||||
/// </summary>
|
||||
/// <param name="reference">The OPC UA node reference string to classify.</param>
|
||||
/// <returns><see langword="true"/> when the reference is index-durable; otherwise <see langword="false"/>.</returns>
|
||||
public static bool IsDurable(string? reference)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reference))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Debugging;
|
||||
|
||||
/// <summary>
|
||||
/// Flow Debugger (final review M1): the ONE parser for the header line of a captured
|
||||
/// Flow Debugger: the ONE parser for the header line of a captured
|
||||
/// exception detail. A .NET <c>Exception.ToString()</c> opens with
|
||||
/// <c>Namespace.Type: message</c>, and a wrapper (an <c>AggregateException</c>, a rethrow)
|
||||
/// chains its inner exceptions on that same first line with <c>" ---> "</c>.
|
||||
|
||||
@@ -59,6 +59,10 @@ public static class FlowGraphBuilder
|
||||
/// Builds the graph. <paramref name="truncated"/> and <paramref name="logsTruncated"/> are passed
|
||||
/// through to <see cref="FlowGraph.Truncated"/> / <see cref="FlowGraph.LogsTruncated"/>.
|
||||
/// </summary>
|
||||
/// <param name="events">The audit events to project into the graph.</param>
|
||||
/// <param name="truncated">Whether the event set was truncated.</param>
|
||||
/// <param name="logsTruncated">Whether the log rows were truncated.</param>
|
||||
/// <returns>The built flow graph.</returns>
|
||||
public static FlowGraph Build(IReadOnlyList<AuditEvent> events, bool truncated = false, bool logsTruncated = false)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(events);
|
||||
@@ -338,8 +342,10 @@ public static class FlowGraphBuilder
|
||||
/// A step the script did not wait for: a notification, or a cached operation — any API / DB step whose
|
||||
/// first lifecycle row is not the sync one-shot kind (<c>ApiCall</c> / <c>DbWrite</c>), the same rule the
|
||||
/// projector uses for the <c>sync</c> / <c>cached</c> subtitle. Such steps hang off the chain on an
|
||||
/// <see cref="FlowEdge.Async"/> edge (D4).
|
||||
/// <see cref="FlowEdge.Async"/> edge.
|
||||
/// </summary>
|
||||
/// <param name="step">The step to classify.</param>
|
||||
/// <returns>True when the step is not awaited by the script.</returns>
|
||||
public static bool IsAsync(FlowStep step)
|
||||
{
|
||||
if (step.Kind == FlowStepKind.Notify) return true;
|
||||
@@ -352,9 +358,12 @@ public static class FlowGraphBuilder
|
||||
|
||||
/// <summary>
|
||||
/// Orders the rows of one outbound operation when timestamps tie: submit before attempts before the
|
||||
/// resolve, then non-terminal before terminal statuses — so "first" and "latest" (D3) never fall back
|
||||
/// resolve, then non-terminal before terminal statuses — so "first" and "latest" never fall back
|
||||
/// to GUID order for rows written in the same tick.
|
||||
/// </summary>
|
||||
/// <param name="kind">The audit row kind.</param>
|
||||
/// <param name="status">The audit row status.</param>
|
||||
/// <returns>The rank used to order the rows.</returns>
|
||||
public static int LifecycleRank(string? kind, string? status)
|
||||
{
|
||||
var k = kind switch
|
||||
@@ -444,6 +453,8 @@ public static class FlowGraphBuilder
|
||||
}
|
||||
|
||||
/// <summary>Display rank used to break timestamp ties: spawners before what they spawn.</summary>
|
||||
/// <param name="kind">The step kind.</param>
|
||||
/// <returns>The display rank for the kind.</returns>
|
||||
public static int KindRank(FlowStepKind kind) => kind switch
|
||||
{
|
||||
FlowStepKind.InboundRequest => 0,
|
||||
|
||||
@@ -14,12 +14,18 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Debugging;
|
||||
public static class FlowStepProjector
|
||||
{
|
||||
/// <summary>Projects an audit event onto a flow step.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <returns>The projected flow step.</returns>
|
||||
public static FlowStep Project(AuditEvent evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
return Project(evt, AuditDetailsCodec.Deserialize(evt.DetailsJson));
|
||||
}
|
||||
|
||||
/// <summary>Projects an audit event and its already-deserialized details onto a flow step.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <param name="d">The deserialized audit details of <paramref name="evt"/>.</param>
|
||||
/// <returns>The projected flow step.</returns>
|
||||
internal static FlowStep Project(AuditEvent evt, AuditDetails d)
|
||||
{
|
||||
var extra = ScriptTraceExtra.TryParse(d.Extra);
|
||||
@@ -52,6 +58,8 @@ public static class FlowStepProjector
|
||||
}
|
||||
|
||||
/// <summary>True for a <c>ScriptTrace.ScriptLog</c> row — a log line, never a step.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <returns><see langword="true"/> when the event is a script log line.</returns>
|
||||
public static bool IsLogLine(AuditEvent evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
@@ -59,6 +67,9 @@ public static class FlowStepProjector
|
||||
return IsLogLine(d);
|
||||
}
|
||||
|
||||
/// <summary>True when the details describe a <c>ScriptTrace.ScriptLog</c> row.</summary>
|
||||
/// <param name="d">The deserialized audit details of the event.</param>
|
||||
/// <returns><see langword="true"/> when the details describe a script log line.</returns>
|
||||
internal static bool IsLogLine(AuditDetails d)
|
||||
{
|
||||
return string.Equals(d.Channel, nameof(AuditChannel.ScriptTrace), StringComparison.Ordinal)
|
||||
@@ -66,12 +77,18 @@ public static class FlowStepProjector
|
||||
}
|
||||
|
||||
/// <summary>Projects a <c>ScriptLog</c> row onto its line. Level/source default to <c>info</c>/<c>script</c> when the extra is missing.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <returns>The projected log line.</returns>
|
||||
public static FlowLogLine ToLogLine(AuditEvent evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
return ToLogLine(evt, AuditDetailsCodec.Deserialize(evt.DetailsJson));
|
||||
}
|
||||
|
||||
/// <summary>Projects a <c>ScriptLog</c> row and its already-deserialized details onto its line.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <param name="d">The deserialized audit details of <paramref name="evt"/>.</param>
|
||||
/// <returns>The projected log line.</returns>
|
||||
internal static FlowLogLine ToLogLine(AuditEvent evt, AuditDetails d)
|
||||
{
|
||||
var x = ScriptTraceExtra.TryParse(d.Extra);
|
||||
@@ -89,12 +106,18 @@ public static class FlowStepProjector
|
||||
}
|
||||
|
||||
/// <summary>Projects one outbound audit row onto its lifecycle entry (<see cref="FlowStep.Lifecycle"/>).</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <returns>The projected lifecycle row.</returns>
|
||||
public static FlowLifecycleRow ToLifecycleRow(AuditEvent evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
return ToLifecycleRow(evt, AuditDetailsCodec.Deserialize(evt.DetailsJson));
|
||||
}
|
||||
|
||||
/// <summary>Projects one outbound audit row and its already-deserialized details onto its lifecycle entry.</summary>
|
||||
/// <param name="evt">The audit event.</param>
|
||||
/// <param name="d">The deserialized audit details of <paramref name="evt"/>.</param>
|
||||
/// <returns>The projected lifecycle row.</returns>
|
||||
internal static FlowLifecycleRow ToLifecycleRow(AuditEvent evt, AuditDetails d)
|
||||
{
|
||||
return new FlowLifecycleRow(
|
||||
@@ -109,6 +132,9 @@ public static class FlowStepProjector
|
||||
}
|
||||
|
||||
/// <summary>Maps a channel/kind string pair onto a step kind.</summary>
|
||||
/// <param name="channel">The audit channel name.</param>
|
||||
/// <param name="kind">The audit kind name.</param>
|
||||
/// <returns>The matching step kind, or <see cref="FlowStepKind.Unknown"/>.</returns>
|
||||
public static FlowStepKind ResolveKind(string? channel, string? kind)
|
||||
{
|
||||
if (string.Equals(channel, nameof(AuditChannel.ScriptTrace), StringComparison.Ordinal))
|
||||
@@ -138,6 +164,9 @@ public static class FlowStepProjector
|
||||
}
|
||||
|
||||
/// <summary>Lane rule: route call / inbound / response → Central; script run / wait → Site; write → Tags; outbound API / DB / notify → External.</summary>
|
||||
/// <param name="kind">The step kind.</param>
|
||||
/// <param name="sourceSiteId">The originating site id, used to place unknown kinds.</param>
|
||||
/// <returns>The lane the step is drawn on.</returns>
|
||||
public static FlowLane ResolveLane(FlowStepKind kind, string? sourceSiteId) => kind switch
|
||||
{
|
||||
FlowStepKind.InboundRequest or FlowStepKind.RouteCall or FlowStepKind.Response => FlowLane.Central,
|
||||
@@ -148,6 +177,8 @@ public static class FlowStepProjector
|
||||
};
|
||||
|
||||
/// <summary>True for the three outbound kinds that live on the External lane.</summary>
|
||||
/// <param name="kind">The step kind.</param>
|
||||
/// <returns><see langword="true"/> for an API call, DB call or notification.</returns>
|
||||
public static bool IsOutbound(FlowStepKind kind)
|
||||
=> kind is FlowStepKind.ApiCall or FlowStepKind.DbCall or FlowStepKind.Notify;
|
||||
|
||||
|
||||
@@ -92,6 +92,9 @@ public sealed class FlowTraceCollector
|
||||
/// the inline copy is filtered through. A null <paramref name="redactor"/> — a host that
|
||||
/// never called <c>AddAuditLog</c>, or a test — collects raw but is still capped.
|
||||
/// </summary>
|
||||
/// <param name="maxEvents">The maximum number of events kept inline.</param>
|
||||
/// <param name="maxBytes">The maximum summed size of the events' details, in bytes.</param>
|
||||
/// <param name="redactor">The redactor applied to the inline copy; null collects raw.</param>
|
||||
public FlowTraceCollector(
|
||||
int maxEvents = DefaultMaxEvents,
|
||||
int maxBytes = DefaultMaxBytes,
|
||||
@@ -142,6 +145,7 @@ public sealed class FlowTraceCollector
|
||||
/// where it builds <c>ScriptCallResult.TraceEvents</c>. Idempotent: a second call returns
|
||||
/// the same contents.
|
||||
/// </summary>
|
||||
/// <returns>The collected events in emission order.</returns>
|
||||
public IReadOnlyList<AuditEvent> Complete()
|
||||
{
|
||||
lock (_gate)
|
||||
@@ -159,6 +163,7 @@ public sealed class FlowTraceCollector
|
||||
/// test-only peek. A reply path must use <see cref="Complete"/>, otherwise an un-awaited call
|
||||
/// finishing after the reply could mutate the list the reply was built from.
|
||||
/// </summary>
|
||||
/// <returns>A copy of the events collected so far.</returns>
|
||||
public IReadOnlyList<AuditEvent> Snapshot()
|
||||
{
|
||||
lock (_gate) return _events.ToArray();
|
||||
|
||||
@@ -68,9 +68,12 @@ public sealed record ScriptTraceExtra
|
||||
};
|
||||
|
||||
/// <summary>Serializes to the compact camelCase JSON stored in <c>AuditDetails.Extra</c>.</summary>
|
||||
/// <returns>The serialized JSON string.</returns>
|
||||
public string ToJson() => JsonSerializer.Serialize(this, JsonOptions);
|
||||
|
||||
/// <summary>Parses <c>AuditDetails.Extra</c>; returns <c>null</c> for null/blank/invalid JSON — never throws.</summary>
|
||||
/// <param name="json">The raw <c>AuditDetails.Extra</c> JSON text.</param>
|
||||
/// <returns>The parsed value, or <c>null</c> when the input is null, blank or invalid.</returns>
|
||||
public static ScriptTraceExtra? TryParse(string? json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json)) return null;
|
||||
|
||||
@@ -2,7 +2,7 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
/// <summary>
|
||||
/// Which leg of a reset-aware <c>Attributes.WriteBatchAndWaitAsync</c> handshake a
|
||||
/// <see cref="HandshakeResult"/> describes (Gitea #36, design 2026-09-10 §4).
|
||||
/// <see cref="HandshakeResult"/> describes.
|
||||
/// </summary>
|
||||
public enum HandshakePhase
|
||||
{
|
||||
@@ -14,7 +14,7 @@ public enum HandshakePhase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of the reset-aware <c>Attributes.WriteBatchAndWaitAsync</c> overload (Gitea #36):
|
||||
/// Result of the reset-aware <c>Attributes.WriteBatchAndWaitAsync</c> overload:
|
||||
/// like <see cref="WaitResult"/>, plus the <see cref="Phase"/> the outcome belongs to so a
|
||||
/// script can report "timed out waiting for the reset echo" separately from "timed out
|
||||
/// waiting for the device to complete". A reset that is never echoed means the batch and
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi;
|
||||
/// How a KPI metric must be folded when an hour of one-minute
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Entities.Kpi.KpiSample"/> rows is
|
||||
/// aggregated into a single <c>KpiRollupHourly</c> row ("KPI History & Trends"
|
||||
/// hourly rollups, deferred #22). The correct fold differs by metric semantics, and
|
||||
/// hourly rollups). The correct fold differs by metric semantics, and
|
||||
/// choosing the wrong one silently corrupts long-range trend charts.
|
||||
/// </summary>
|
||||
public enum KpiRollupAggregation
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Scripts;
|
||||
public static class ScriptTriggerAttribute
|
||||
{
|
||||
/// <summary>True for the trigger kinds the Flow Debugger fires by WRITING the monitored attribute.</summary>
|
||||
/// <param name="triggerType">The trigger type name.</param>
|
||||
/// <returns>True when the trigger type is a write kind.</returns>
|
||||
public static bool IsWriteKind(string? triggerType) =>
|
||||
string.Equals(triggerType, "ValueChange", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(triggerType, "Conditional", StringComparison.OrdinalIgnoreCase);
|
||||
@@ -20,6 +22,10 @@ public static class ScriptTriggerAttribute
|
||||
/// false (and null) for every other kind, and for a write kind whose config is missing,
|
||||
/// malformed, not an object, or names no attribute.
|
||||
/// </summary>
|
||||
/// <param name="triggerType">The trigger type name.</param>
|
||||
/// <param name="triggerConfigurationJson">The trigger configuration JSON.</param>
|
||||
/// <param name="attribute">Receives the monitored attribute name, or null.</param>
|
||||
/// <returns>True when a monitored attribute was read.</returns>
|
||||
public static bool TryRead(string? triggerType, string? triggerConfigurationJson, out string? attribute)
|
||||
{
|
||||
attribute = null;
|
||||
|
||||
@@ -20,7 +20,7 @@ public static class SecretReferenceScanner
|
||||
/// <summary>
|
||||
/// The single parser for a <c>secret:<name></c> reference value, shared by this scanner
|
||||
/// (what central ships) and every adapter that resolves the reference at connect time (what
|
||||
/// the site looks up), so both sides always agree on the name (final review M3). The value is
|
||||
/// the site looks up), so both sides always agree on the name. The value is
|
||||
/// trimmed, the <c>secret:</c> prefix matches ordinal-ignore-case, and the remainder is
|
||||
/// trimmed; an empty remainder is not a reference. The config-expander form
|
||||
/// <c>${secret:…}</c> is a different syntax and never matches.
|
||||
@@ -45,6 +45,8 @@ public static class SecretReferenceScanner
|
||||
/// string values and returns the distinct names found, ordinal-sorted, each with the ordinal-sorted,
|
||||
/// de-duplicated list of connection names that referenced it.
|
||||
/// </summary>
|
||||
/// <param name="connections">The data connection artifacts to scan.</param>
|
||||
/// <returns>The distinct referenced secrets, each with the connections that reference it.</returns>
|
||||
public static IReadOnlyList<SecretReference> Scan(IEnumerable<DataConnectionArtifact> connections)
|
||||
{
|
||||
var found = new SortedDictionary<string, SortedSet<string>>(StringComparer.Ordinal);
|
||||
|
||||
Reference in New Issue
Block a user