diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs index 8ab1d61e..dd000050 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/AuditLogPartitionMaintenanceService.cs @@ -76,7 +76,12 @@ public sealed class AuditLogPartitionMaintenanceService : IHostedService, IDispo _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - /// + /// + /// Starts the background maintenance loop, firing an immediate first tick and then + /// repeating every . + /// + /// Cancellation token provided by the host. + /// A completed task; the loop runs independently on a background thread. public Task StartAsync(CancellationToken ct) { // Linked CTS lets StopAsync's cancellation AND the host's shutdown @@ -136,14 +141,21 @@ public sealed class AuditLogPartitionMaintenanceService : IHostedService, IDispo } } - /// + /// + /// Signals the maintenance loop to stop by cancelling its linked token, + /// then returns the loop task so the host can await its completion. + /// + /// Cancellation token provided by the host (unused — the internal CTS is cancelled directly). + /// The background loop task, or a completed task if the loop was never started. public Task StopAsync(CancellationToken ct) { _cts?.Cancel(); return _loop ?? Task.CompletedTask; } - /// + /// + /// Disposes the internal used to stop the maintenance loop. + /// public void Dispose() { _cts?.Dispose(); diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullAuditEventsClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullAuditEventsClient.cs index e1d8f59f..52ebf083 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullAuditEventsClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/IPullAuditEventsClient.cs @@ -41,6 +41,7 @@ public interface IPullAuditEventsClient /// Only events with an OccurredAtUtc at or after this cursor time are returned. /// Maximum number of events to return per call. /// Cancellation token. + /// A task that resolves to the next reconciliation batch with a MoreAvailable flag. Task PullAsync( string siteId, DateTime sinceUtc, diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ISiteEnumerator.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ISiteEnumerator.cs index dd36cfec..cc8cae1f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ISiteEnumerator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/ISiteEnumerator.cs @@ -23,6 +23,7 @@ public interface ISiteEnumerator /// — the actor calls this once per tick. /// /// Cancellation token for the async enumeration. + /// A task that resolves to the current set of site entries to poll on the next reconciliation tick. Task> EnumerateAsync(CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs index 4aa2fe81..51ec202c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/SiteAuditTelemetryStalledTracker.cs @@ -133,6 +133,7 @@ public sealed class SiteAuditTelemetryStalledTracker : IDisposable /// Returns a defensive copy of the per-site latched stalled state. /// Absent sites are interpreted as Stalled=false by consumers. /// + /// A snapshot dictionary mapping each known site ID to its current stalled state. public IReadOnlyDictionary Snapshot() => new Dictionary(_state); diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs index 1a13bf72..dfbd0764 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRedactionPrimitives.cs @@ -71,6 +71,11 @@ internal static class AuditRedactionPrimitives /// field is over-redacted with and /// is invoked. /// + /// The raw JSON string to redact; null passes through as null. + /// Header names (case-insensitive) whose values should be replaced. + /// Logger for warning diagnostics on redactor faults. + /// Callback invoked when the redactor stage faults; used to increment health counters. + /// The re-serialized JSON with redacted header values, the original string if nothing was redacted, or on fault. public static string? RedactHeaders( string? json, IList redactList, @@ -152,6 +157,11 @@ internal static class AuditRedactionPrimitives /// with and /// is invoked — the user-facing action is never aborted. /// + /// The string to redact; null passes through as null. + /// Compiled body-redaction regexes applied in order. + /// Logger for warning diagnostics on redactor faults. + /// Callback invoked when a regex match faults; used to increment health counters. + /// The value with all regex matches replaced by , or on fault. public static string? RedactBody( string? value, IReadOnlyList regexes, @@ -192,6 +202,11 @@ internal static class AuditRedactionPrimitives /// is over-redacted with and /// is invoked. /// + /// The raw JSON string to redact; null passes through as null. + /// Compiled regex matched against each SQL parameter name. + /// Logger for warning diagnostics on redactor faults. + /// Callback invoked when the redactor stage faults; used to increment health counters. + /// The re-serialized JSON with matched parameter values replaced by , the original string if no parameters matched, or on fault. public static string? RedactSqlParameters( string? json, Regex paramNameRegex, @@ -277,6 +292,10 @@ internal static class AuditRedactionPrimitives /// setting to true when the value was /// shortened. Null passes through as null. /// + /// The string to truncate; null passes through as null. + /// Maximum number of UTF-8 bytes to retain. + /// Set to true when the value was shortened; unchanged otherwise. + /// The truncated string, the original string if within the cap, or null if the input was null. public static string? TruncateField(string? value, int cap, ref bool truncated) { if (value is null) @@ -299,6 +318,9 @@ internal static class AuditRedactionPrimitives /// (byte & 0xC0 == 0x80), and decodes the resulting prefix — /// guaranteeing the returned string never splits a multi-byte sequence. /// + /// The string to truncate. + /// Maximum number of UTF-8 bytes in the returned string. + /// The truncated string guaranteed not to split a multi-byte UTF-8 sequence, or the original string if within the cap. public static string TruncateUtf8(string value, int capBytes) { if (string.IsNullOrEmpty(value)) diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs index dfefb7d3..143e6624 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Payload/AuditRegexCache.cs @@ -35,6 +35,8 @@ internal sealed class AuditRegexCache private readonly ConcurrentDictionary _cache = new(); private readonly ILogger _logger; + /// Initializes the cache with the logger used to report compile failures. + /// Logger for recording invalid or slow-compile pattern warnings. public AuditRegexCache(ILogger logger) => _logger = logger; /// @@ -44,6 +46,9 @@ internal sealed class AuditRegexCache /// compile time "invalid"); the failure is logged once and the sentinel /// cache entry prevents repeat compile attempts. /// + /// The regex pattern string to look up or compile. + /// The compiled , or null if the pattern is invalid. + /// true if the pattern compiled successfully; false if it is invalid or too slow to compile. public bool TryGet(string pattern, out Regex? regex) { var entry = _cache.GetOrAdd(pattern, Compile); @@ -88,8 +93,11 @@ internal sealed class AuditRegexCache { public static readonly CompiledRegex Invalid = new(null); + /// The compiled regex, or null when this entry represents an invalid pattern. public Regex? Regex { get; } + /// Initializes the entry with the compiled regex (or null for the invalid sentinel). + /// The compiled , or null for a failed compile. public CompiledRegex(Regex? regex) => Regex = regex; } } diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/SafeDefaultAuditRedactor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/SafeDefaultAuditRedactor.cs index 6ca47fe3..77314706 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/SafeDefaultAuditRedactor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/SafeDefaultAuditRedactor.cs @@ -37,7 +37,15 @@ public sealed class SafeDefaultAuditRedactor : IAuditRedactor private SafeDefaultAuditRedactor() { } - /// + /// + /// Applies line-oriented header redaction to the default sensitive headers + /// (Authorization, X-Api-Key, Cookie, Set-Cookie) + /// found in RequestSummary and ResponseSummary inside + /// .DetailsJson. Never throws; over-redacts on + /// any internal failure. + /// + /// The audit event whose details JSON is to be redacted. + /// A new with sensitive headers replaced by the redacted marker, or an over-redacted sentinel on failure. public AuditEvent Apply(AuditEvent rawEvent) { ArgumentNullException.ThrowIfNull(rawEvent); diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/ScadaBridgeAuditRedactor.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/ScadaBridgeAuditRedactor.cs index a2e93e9a..20df75da 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/ScadaBridgeAuditRedactor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Redaction/ScadaBridgeAuditRedactor.cs @@ -73,7 +73,12 @@ public sealed class ScadaBridgeAuditRedactor : IAuditRedactor _regexCache = new AuditRegexCache(_logger); } - /// + /// + /// Applies the full redaction pipeline to and returns a + /// filtered copy; returns the same instance unchanged on the fast path. Never throws. + /// + /// The raw audit event to redact. + /// A redacted copy of , or the original instance when no changes are needed. public AuditEvent Apply(AuditEvent rawEvent) { try diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs index f2728fb0..d54cf27d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/RingBufferFallback.cs @@ -96,6 +96,7 @@ public sealed class RingBufferFallback /// must call first. /// /// Cancellation token to abort the async enumeration. + /// An async sequence of buffered values in FIFO order. public async IAsyncEnumerable DrainAsync( [EnumeratorCancellation] CancellationToken cancellationToken) { diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs index 51e23328..ff0c5e23 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SiteAuditBacklogReporter.cs @@ -69,7 +69,9 @@ public sealed class SiteAuditBacklogReporter : IHostedService, IDisposable _refreshInterval = refreshInterval ?? DefaultRefreshInterval; } - /// + /// Starts the background polling loop, running an immediate first probe before entering the timed cycle. + /// Cancellation token signalling host shutdown. + /// A task that represents the asynchronous operation. public Task StartAsync(CancellationToken ct) { // Linked CTS lets StopAsync's cancellation AND the host's shutdown @@ -123,14 +125,16 @@ public sealed class SiteAuditBacklogReporter : IHostedService, IDisposable } } - /// + /// Signals the polling loop to stop and waits for it to complete. + /// Cancellation token (not used; the internal CTS governs shutdown). + /// A task that represents the asynchronous operation. public Task StopAsync(CancellationToken ct) { _cts?.Cancel(); return _loop ?? Task.CompletedTask; } - /// + /// Releases the internal used to stop the polling loop. public void Dispose() { _cts?.Dispose(); diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs index 1885771f..954282df 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs @@ -244,7 +244,13 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable cmd.ExecuteNonQuery(); } - /// + /// + /// Enqueues an audit event for asynchronous batched persistence to SQLite. + /// Back-pressure is applied when the write channel is full. + /// + /// The audit event to persist. + /// Cancellation token. + /// A task that completes when the event has been persisted. public Task WriteAsync(AuditEvent evt, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(evt); @@ -469,7 +475,13 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable return CachedTelemetryKinds.Contains(kind); } - /// + /// + /// Returns up to non-cached pending audit events, oldest first. + /// Cached-lifecycle kinds are excluded; use for those. + /// + /// Maximum number of rows to return. + /// Cancellation token. + /// A task that resolves to a read-only list of pending audit events. public Task> ReadPendingAsync(int limit, CancellationToken ct = default) { if (limit <= 0) @@ -512,7 +524,13 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable } } - /// + /// + /// Returns up to pending cached-lifecycle audit events, oldest first. + /// Only rows with cached-call kinds (CachedSubmit, ApiCallCached, DbWriteCached, CachedResolve) are included. + /// + /// Maximum number of rows to return. + /// Cancellation token. + /// A task that resolves to a read-only list of pending cached-telemetry audit events. public Task> ReadPendingCachedTelemetryAsync( int limit, CancellationToken ct = default) { @@ -560,6 +578,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable /// /// Maximum number of rows to return. /// Cancellation token. + /// A task that resolves to a read-only list of forwarded audit events. public Task> ReadForwardedAsync(int limit, CancellationToken ct = default) { if (limit <= 0) @@ -645,7 +664,15 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable } } - /// + /// + /// Returns up to pending or forwarded audit events + /// with >= , oldest first. + /// Used by the M6 reconciliation-pull handler. + /// + /// Lower bound timestamp (UTC) for event occurrence. + /// Maximum number of rows to return. + /// Cancellation token. + /// A task that resolves to a read-only list of audit events since the given timestamp. public Task> ReadPendingSinceAsync( DateTime sinceUtc, int batchSize, CancellationToken ct = default) { @@ -867,6 +894,7 @@ public class SqliteAuditWriter : IAuditWriter, ISiteAuditQueue, IAsyncDisposable } /// Asynchronously disposes the audit writer and releases resources. + /// A that completes when all resources have been released. public async ValueTask DisposeAsync() { Task? writerLoop; diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs index 0cc880e6..019f9611 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ClusterClientSiteAuditClient.cs @@ -44,6 +44,9 @@ public sealed class ClusterClientSiteAuditClient : ISiteStreamAuditClient private readonly IActorRef _siteCommunicationActor; private readonly TimeSpan _askTimeout; + /// + /// Initializes a new instance that forwards audit telemetry to central via the site's SiteCommunicationActor. + /// /// /// The site's SiteCommunicationActor — it forwards the ingest command /// over the registered central ClusterClient and routes the reply back to diff --git a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs index 76d05e32..7a17dd50 100644 --- a/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/Telemetry/ISiteStreamAuditClient.cs @@ -22,6 +22,7 @@ public interface ISiteStreamAuditClient /// /// The batch of audit events to forward. /// Cancellation token for the operation. + /// A task that resolves to the ingest acknowledgement containing accepted event IDs. Task IngestAuditEventsAsync(AuditEventBatch batch, CancellationToken ct); /// @@ -42,5 +43,6 @@ public interface ISiteStreamAuditClient /// /// The batch of cached-call telemetry packets to forward. /// Cancellation token for the operation. + /// A task that resolves to the ingest acknowledgement containing accepted event IDs. Task IngestCachedTelemetryAsync(CachedTelemetryBatch batch, CancellationToken ct); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ApiMethodCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ApiMethodCommands.cs index 190494bd..780b6144 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ApiMethodCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ApiMethodCommands.cs @@ -13,6 +13,7 @@ public static class ApiMethodCommands /// Global option for the output format. /// Global option for the authentication username. /// Global option for the authentication password. + /// The configured api-method command with all subcommands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("api-method") { Description = "Manage inbound API methods" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs index 5f5ce5cc..9b588e35 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditCommands.cs @@ -18,6 +18,7 @@ public static class AuditCommands /// Global --format option for output format. /// Global --username option for authentication. /// Global --password option for authentication. + /// The configured audit with all sub-commands attached. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("audit") { Description = "Query and export the centralized audit log" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs index 3528662d..2e929ab6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditExportHelpers.cs @@ -74,6 +74,7 @@ public static class AuditExportHelpers /// /// The export arguments containing filters and format. /// The current time for resolving relative time specifications. + /// The full query string (including the leading ?) for the export endpoint. public static string BuildQueryString(AuditExportArgs args, DateTimeOffset now) { var parts = new List(); @@ -116,6 +117,7 @@ public static class AuditExportHelpers /// The export arguments containing filters and output file path. /// Text writer for command output messages. /// The current time for resolving relative time specifications. + /// 0 on success, 1 on general error, or 2 on authorization failure. public static async Task RunExportAsync( ManagementHttpClient client, AuditExportArgs args, TextWriter output, DateTimeOffset now) { @@ -178,6 +180,8 @@ public static class AuditExportHelpers /// to extract the code field. Returns null if the body is empty, not valid JSON, or /// has no code property — callers fall back to "ERROR" in that case. /// + /// The HTTP response body string to parse for an error code. + /// The code string from the JSON error envelope, or null if absent or unparseable. internal static string? TryExtractErrorCode(string body) { if (string.IsNullOrWhiteSpace(body)) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs index 577269ce..0bff72fb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditFormatter.cs @@ -43,6 +43,7 @@ public static class AuditFormatterFactory /// /// Format name; table selects the table formatter, any other value selects JSONL. /// Writer for notice messages emitted during formatting. + /// The appropriate for the requested format. public static IAuditFormatter Create(string format, TextWriter notices) { if (string.Equals(format, "table", StringComparison.OrdinalIgnoreCase)) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs index 2ba8eaa1..cfe3acfa 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditLogCommands.cs @@ -50,6 +50,7 @@ public static class AuditLogCommands /// Global output format option. /// Global username option. /// Global password option. + /// The configured audit-config command with all sub-commands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("audit-config") { Description = "Query the configuration-change audit log" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs index a05c0bae..0dd4dbf9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditQueryHelpers.cs @@ -61,6 +61,7 @@ public static class AuditQueryHelpers /// The time specification string. /// The current time used as reference for relative specs. /// The spec is neither a known relative form nor a parseable ISO-8601 timestamp. + /// The resolved absolute in UTC. public static DateTimeOffset ResolveTimeSpec(string spec, DateTimeOffset now) { if (string.IsNullOrWhiteSpace(spec)) @@ -103,6 +104,7 @@ public static class AuditQueryHelpers /// The current time for resolving relative time specs. /// Optional keyset cursor timestamp. /// Optional keyset cursor event ID. + /// A URL query string (starting with ?) containing the encoded filter parameters, or an empty string if no parameters are set. public static string BuildQueryString( AuditQueryArgs args, DateTimeOffset now, DateTimeOffset? afterOccurredAtUtc, string? afterEventId) { @@ -169,6 +171,7 @@ public static class AuditQueryHelpers /// The audit result formatter. /// The output writer for results. /// The current time for resolving relative time specs. + /// A task that resolves to 0 on success, 1 on HTTP/transport error, or 2 on authorization failure. public static async Task RunQueryAsync( ManagementHttpClient client, AuditQueryArgs args, diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditVerifyChainHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditVerifyChainHelpers.cs index e41ca284..cc6dcb38 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditVerifyChainHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/AuditVerifyChainHelpers.cs @@ -14,6 +14,7 @@ public static class AuditVerifyChainHelpers /// with a real month (01-12). A malformed month (e.g. 2026-13) is rejected. /// /// The month string to validate in YYYY-MM format. + /// true if the string is a well-formed YYYY-MM value with a real month; otherwise false. public static bool IsValidMonth(string? month) => !string.IsNullOrWhiteSpace(month) && DateTime.TryParseExact(month, "yyyy-MM", CultureInfo.InvariantCulture, diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs index efea33c0..f3564e86 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/BundleCommands.cs @@ -307,6 +307,13 @@ public static class BundleCommands // for the post-write summary line. internal const int Base64StreamChunkChars = 1024 * 1024; // 1 MB of base64 chars ≈ 768 KB decoded + /// + /// Decodes a base64 string into in chunked fashion to avoid + /// large intermediate allocations. Returns the total number of decoded bytes written. + /// + /// The base64-encoded content to decode and write. + /// Destination file path; created or overwritten. + /// Total number of bytes written to the output file. internal static long StreamBase64ToFile(string base64, string outputPath) { if (base64 is null) throw new ArgumentNullException(nameof(base64)); diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CliOptions.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CliOptions.cs index 24d1f6c7..90c8e906 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CliOptions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CliOptions.cs @@ -17,6 +17,7 @@ internal static class CliOptions /// typo (e.g. --format tabel) is rejected with a clear parse error rather /// than silently falling through to JSON. /// + /// The configured --format option constrained to "json" or "table". internal static Option CreateFormatOption() { var formatOption = new Option("--format") diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs index 52fd949d..d99f0f88 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/CommandHelpers.cs @@ -30,6 +30,7 @@ internal static class CommandHelpers /// () is preserved on the error path either way, /// closing CLI-017's regression. /// + /// A task that resolves to the process exit code (0 = success, 1 = error, 2 = authorization failure). internal static async Task ExecuteCommandAsync( ParseResult result, Option urlOption, @@ -110,6 +111,7 @@ internal static class CommandHelpers /// Parsed command-line result. /// The --format option definition. /// Loaded CLI configuration providing the default format fallback. + /// The resolved format string (e.g. "json" or "table"). internal static string ResolveFormat(ParseResult result, Option formatOption, CliConfig config) { // GetResult returns non-null only when the option was actually present on the @@ -130,6 +132,7 @@ internal static class CommandHelpers /// /// Value supplied on the command line, or null if absent. /// Fallback value from the config file or environment variable. + /// The command-line value when non-empty; otherwise the environment fallback (may be null). internal static string? ResolveCredential(string? commandLineValue, string? envValue) => string.IsNullOrWhiteSpace(commandLineValue) ? envValue : commandLineValue; @@ -140,6 +143,7 @@ internal static class CommandHelpers /// an unhandled . /// /// URL string to validate. + /// true when the URL is an absolute http or https URL; otherwise false. internal static bool IsValidManagementUrl(string? url) { if (string.IsNullOrWhiteSpace(url)) @@ -154,6 +158,7 @@ internal static class CommandHelpers /// /// Response received from the management API. /// Output format (json or table). + /// The process exit code (0 = success, 1 = error, 2 = authorization failure). internal static int HandleResponse(ManagementResponse response, string format) { if (response.JsonData != null) @@ -192,6 +197,8 @@ internal static class CommandHelpers /// both channels are honoured. (Authentication failure — HTTP 401 / bad credentials /// — is deliberately not treated as authorization failure; it is exit 1.) /// + /// The management response to inspect for authorization failure signals. + /// true when the response signals an authorization failure (HTTP 403 or FORBIDDEN/UNAUTHORIZED code). internal static bool IsAuthorizationFailure(ManagementResponse response) { if (response.StatusCode == 403) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DataConnectionCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DataConnectionCommands.cs index 10600024..74ef08f0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DataConnectionCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DataConnectionCommands.cs @@ -13,6 +13,7 @@ public static class DataConnectionCommands /// Global output format option. /// Global username option. /// Global password option. + /// The configured data-connection with all subcommands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("data-connection") { Description = "Manage data connections" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs index 06e7ceed..a936cd44 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugCommands.cs @@ -15,6 +15,7 @@ public static class DebugCommands /// Shared output format option. /// Shared username option for authentication. /// Shared password option for authentication. + /// The configured debug command with snapshot and stream subcommands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("debug") { Description = "Runtime debugging" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs index 5639396f..a5910e7e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DebugStreamHelpers.cs @@ -27,6 +27,7 @@ internal static class DebugStreamHelpers /// /// The exception thrown by HubConnection.StartAsync. /// True when the user requested cancellation (Ctrl+C) before the exception was thrown. + /// A describing whether the failure was a cancellation and the appropriate exit code. internal static ConnectFailure ClassifyConnectFailure(Exception ex, bool cancellationRequested) { if (cancellationRequested && ex is OperationCanceledException) @@ -43,6 +44,7 @@ internal static class DebugStreamHelpers /// result is ever produced (pure Ctrl+C), the stream ended gracefully — exit 0. /// /// The task whose result is the intended exit code, set by OnStreamTerminated or the Closed handler. + /// A task that resolves to the process exit code (0 for graceful exit or pure Ctrl+C, non-zero for error). internal static async Task ResolveStreamExitCodeAsync(Task exitTask) { if (exitTask.IsCompletedSuccessfully) diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DeployCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DeployCommands.cs index f7cee3a1..f014f784 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DeployCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/DeployCommands.cs @@ -13,6 +13,7 @@ public static class DeployCommands /// Global output format option. /// Global username option. /// Global password option. + /// The configured deploy with all sub-commands attached. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("deploy") { Description = "Deployment operations" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs index 69eaf266..889828c2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/ExternalSystemCommands.cs @@ -13,6 +13,7 @@ public static class ExternalSystemCommands /// Global option for the output format. /// Global option for the authentication username. /// Global option for the authentication password. + /// The fully configured external-system with all subcommands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("external-system") { Description = "Manage external systems" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/HealthCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/HealthCommands.cs index c5a5481b..770435bb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/HealthCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/HealthCommands.cs @@ -13,6 +13,7 @@ public static class HealthCommands /// Global --format option for output format. /// Global --username option for authentication. /// Global --password option for authentication. + /// The configured health command with all sub-commands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("health") { Description = "Health monitoring" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/NotificationCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/NotificationCommands.cs index b4891aa4..ac97adf9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/NotificationCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/NotificationCommands.cs @@ -13,6 +13,7 @@ public static class NotificationCommands /// Global --format option for output format. /// Global --username option for authentication. /// Global --password option for authentication. + /// The configured notification command with all sub-commands registered. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("notification") { Description = "Manage notification lists" }; @@ -131,6 +132,7 @@ public static class NotificationCommands /// null when omitted so the server-side handler preserves the existing values. /// /// The parsed command-line result from the smtp update invocation. + /// An populated from the parsed result. internal static UpdateSmtpConfigCommand BuildUpdateSmtpConfigCommand(ParseResult result) { var id = result.GetValue(SmtpIdOption); diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SecurityCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SecurityCommands.cs index 50e2da93..d4cd7ffe 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SecurityCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SecurityCommands.cs @@ -13,6 +13,7 @@ public static class SecurityCommands /// Shared output format option. /// Shared username option for authentication. /// Shared password option for authentication. + /// The configured security command with all subcommands attached. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("security") { Description = "Manage security settings" }; @@ -125,6 +126,7 @@ public static class SecurityCommands /// The advisory line is written to stderr so that piping stdout captures only the token. /// /// The JSON success body returned by the management API. + /// Exit code 0. internal static int PrintCreatedKey(string json) { using var doc = System.Text.Json.JsonDocument.Parse(json); diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs index 496095bb..9e92b79e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs @@ -13,6 +13,7 @@ public static class SiteCommands /// Global output format option. /// Global username option. /// Global password option. + /// The configured site command with all subcommands attached. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("site") { Description = "Manage sites" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs index a6fe8cf5..9d88a4fa 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CLI/Commands/TemplateCommands.cs @@ -11,6 +11,7 @@ public static class TemplateCommands /// Shared output format option. /// Shared username option for authentication. /// Shared password option for authentication. + /// The fully configured template command with all its subcommands. public static Command Build(Option urlOption, Option formatOption, Option usernameOption, Option passwordOption) { var command = new Command("template") { Description = "Manage templates" }; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs index 22d48d90..b0f71a03 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Audit/AuditExportEndpoints.cs @@ -61,6 +61,7 @@ public static class AuditExportEndpoints /// /// The HTTP context for the current request. /// The export service used to stream audit rows as CSV. + /// A task representing the asynchronous export streaming operation. internal static async Task HandleExportAsync(HttpContext context, IAuditLogExportService exportService) { var filter = ParseFilter(context.Request.Query); @@ -94,6 +95,7 @@ public static class AuditExportEndpoints /// its own CLI / UI URL builder — so do NOT "fix" the two to one key name. /// /// The query string parameters from the HTTP request. + /// An populated from the query string values. internal static AuditLogQueryFilter ParseFilter(IQueryCollection query) { var channels = AuditQueryParamParsers.ParseEnumList(query["channel"]); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs index d00acde2..ac235eba 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/AuthEndpoints.cs @@ -19,6 +19,7 @@ public static class AuthEndpoints { /// Registers the /auth/login, /auth/logout, and /auth/ping endpoints on the given route builder. /// The route builder to add the endpoints to. + /// The same instance, for call chaining. public static IEndpointRouteBuilder MapAuthEndpoints(this IEndpointRouteBuilder endpoints) { endpoints.MapPost("/auth/login", async (HttpContext context) => @@ -198,6 +199,7 @@ public static class AuthEndpoints /// server-side. See CentralUI-020. /// /// The current HTTP context used to check authentication state and write the response. + /// A task that represents the asynchronous operation. public static Task HandlePing(HttpContext context) { context.Response.StatusCode = context.User.Identity?.IsAuthenticated == true @@ -219,6 +221,7 @@ public static class AuthEndpoints /// is left unset (null) /// so the middleware is free to slide the expiry on activity. /// + /// An instance with set to true and no fixed expiry. public static AuthenticationProperties BuildSignInProperties() => new() { IsPersistent = true diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs index 84d4fc68..b7c0c9ed 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/ClaimsPrincipalExtensions.cs @@ -20,6 +20,7 @@ public static class ClaimsPrincipalExtensions /// when the claim is absent. /// /// The claims principal to read the username from. + /// The username claim value, or if absent. public static string GetUsername(this ClaimsPrincipal principal) => principal.FindFirst(JwtTokenService.UsernameClaimType)?.Value ?? UnknownUser; @@ -28,6 +29,7 @@ public static class ClaimsPrincipalExtensions /// the claim is absent. /// /// The claims principal to read the display name from. + /// The display name claim value, or null if the claim is absent. public static string? GetDisplayName(this ClaimsPrincipal principal) => principal.FindFirst(JwtTokenService.DisplayNameClaimType)?.Value; @@ -37,6 +39,7 @@ public static class ClaimsPrincipalExtensions /// ten components (CentralUI-024). /// /// The Blazor authentication state provider to read from. + /// A task that resolves to the current user's audit username, or if not authenticated. public static async Task GetCurrentUsernameAsync( this AuthenticationStateProvider authStateProvider) { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs index f470bd2e..143d7bde 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Auth/SiteScopeService.cs @@ -38,6 +38,7 @@ public sealed class SiteScopeService /// True when the user is not restricted to a site subset (no SiteId /// claims). System-wide users see and act on every site. /// + /// A task that resolves to true if the user has no site-scope restriction. public async Task IsSystemWideAsync() => (await ResolveAsync()).IsSystemWide; @@ -46,6 +47,7 @@ public sealed class SiteScopeService /// system-wide user (callers should consult /// or use the filter/allowed helpers, which already account for that). /// + /// A task that resolves to the set of permitted site IDs (empty for system-wide users). public async Task> PermittedSiteIdsAsync() => (await ResolveAsync()).Sites; @@ -54,6 +56,7 @@ public sealed class SiteScopeService /// see. A system-wide user gets the full list back unchanged. /// /// The full set of sites to filter. + /// A task that resolves to the filtered list of sites the user is permitted to see. public async Task> FilterSitesAsync(IEnumerable sites) { var (isSystemWide, allowed) = await ResolveAsync(); @@ -67,6 +70,7 @@ public sealed class SiteScopeService /// Must be re-checked server-side before any mutating cross-site command. /// /// The Site.Id to check. + /// A task that resolves to true when the user may operate on the given site. public async Task IsSiteAllowedAsync(int siteId) { var (isSystemWide, allowed) = await ResolveAsync(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs index 7a3e53b5..512beec5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditQueryModel.cs @@ -114,6 +114,7 @@ public sealed class AuditQueryModel /// With one or more Channels selected, the union of the channel-specific kind /// lists is returned (deduplicated and order-stable on first-seen). /// + /// The deduplicated, order-stable list of values applicable to the selected channels. public IReadOnlyList VisibleKinds() { if (Channels.Count == 0) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs index 7f3174f4..8f082aca 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor.cs @@ -411,6 +411,7 @@ public partial class AuditResultsGrid : IAsyncDisposable /// /// The stable key of the resized column. /// The new column width in pixels. + /// A task that completes when the column width has been persisted and the component re-rendered. [JSInvokable] public async Task OnColumnResized(string columnKey, int widthPx) { @@ -431,6 +432,7 @@ public partial class AuditResultsGrid : IAsyncDisposable /// /// The stable key of the column being dragged. /// The stable key of the target column drop slot. + /// A task that completes when the column order has been persisted and the component re-rendered. [JSInvokable] public async Task OnColumnReordered(string fromKey, string toKey) { @@ -472,6 +474,7 @@ public partial class AuditResultsGrid : IAsyncDisposable /// /// Releases the .NET object reference held for JS interop callbacks. /// + /// A completed value task. public ValueTask DisposeAsync() { _selfRef?.Dispose(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs index 4baa1cab..093ad06d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs @@ -254,6 +254,7 @@ public partial class AuditLogPage : IDisposable /// Builds the CSV export URL for the given filter, encoding all active filter dimensions as query parameters. /// /// Currently applied filter; null returns the bare export endpoint. + /// The relative URL with encoded filter dimensions as query parameters. internal static string BuildExportUrl(AuditLogQueryFilter? filter) { const string basePath = "/api/centralui/audit/export"; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs index a0e0b807..7cf1acf7 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor.cs @@ -182,6 +182,7 @@ public partial class TransportExport : ComponentBase /// importer enforces its own strength + lockout policies. /// /// The passphrase string to score. + /// An integer from 0 (blank) to 4 (long, mixed case, digits, and symbols). internal static int PassphraseStrength(string s) { if (string.IsNullOrEmpty(s)) return 0; @@ -261,6 +262,7 @@ public partial class TransportExport : ComponentBase /// knows exactly what an unencrypted export would leak. /// /// The resolved export closure whose secret fields are counted. + /// The total number of non-empty secret fields across all external systems, SMTP configs, and database connections. internal static int CountSecrets(ResolvedExport resolved) { var count = 0; @@ -367,6 +369,7 @@ public partial class TransportExport : ComponentBase /// /// The environment label to embed in the filename (sanitised to filename-safe characters). /// Timestamp to use for the datetime segment; defaults to when null. + /// A filename of the form scadabundle-{env}-{yyyy-MM-dd-HHmmss}.scadabundle. internal static string BuildFilename(string sourceEnvironment, DateTimeOffset? nowUtc = null) { var safe = SanitizeForFilename(sourceEnvironment); @@ -427,6 +430,7 @@ public partial class TransportExport : ComponentBase /// The full resolved list including both seed and auto-included items. /// The set of explicitly selected item ids. /// Function that extracts the integer id from an item. + /// Items from whose ids are not in (auto-included dependencies). internal static IReadOnlyList AutoIncluded(IReadOnlyList all, IReadOnlyCollection seed, Func idOf) { return all.Where(x => !seed.Contains(idOf(x))).ToList(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/DurationInput.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/DurationInput.cs index 3b18fc30..a9865236 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/DurationInput.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/DurationInput.cs @@ -18,6 +18,7 @@ internal static class DurationInput /// sec unit. /// /// The duration to split, or null for unset. + /// A tuple of the numeric string and unit token (ms/sec/min), or (null, "sec") for null or non-positive input. internal static (string? Value, string Unit) Split(TimeSpan? duration) { if (duration is not { } d || d <= TimeSpan.Zero) return (null, "sec"); @@ -34,6 +35,7 @@ internal static class DurationInput /// /// The numeric string entered by the user. /// The selected unit token (ms, sec, or min). + /// The composed , or null for blank, unparseable, or non-positive input. internal static TimeSpan? Compose(string? value, string unit) { if (!long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var n) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/IDialogService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/IDialogService.cs index 404cc5f3..9b9f9059 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/IDialogService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/IDialogService.cs @@ -18,6 +18,7 @@ public interface IDialogService /// When true, the confirm button renders in /// btn-danger styling with the label "Delete"; otherwise a primary /// "Confirm" button is shown. + /// A task that resolves to true when the user confirms, or false when cancelled. Task ConfirmAsync(string title, string message, bool danger = false); /// @@ -28,5 +29,6 @@ public interface IDialogService /// Label rendered above the input field. /// Pre-populated value for the input field. /// Optional placeholder shown when the input is empty. + /// A task that resolves to the entered string, or null if the user cancels. Task PromptAsync(string title, string label, string initialValue = "", string? placeholder = null); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/SchemaBuilderModel.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/SchemaBuilderModel.cs index 4efe8133..3235a4a6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/SchemaBuilderModel.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/SchemaBuilderModel.cs @@ -46,6 +46,7 @@ internal static class SchemaBuilderModel /// /// JSON Schema string to parse, or null/empty to return the fallback. /// The to return when the input cannot be parsed. + /// The parsed tree, or if the input is empty or malformed. public static SchemaNode Parse(string? json, SchemaNode fallback) { if (string.IsNullOrWhiteSpace(json)) return fallback; @@ -66,15 +67,18 @@ internal static class SchemaBuilderModel } /// Default empty object schema (parameters mode default). + /// A new with type object. public static SchemaNode NewObject() => new() { Type = "object" }; /// Default scalar schema (return mode default). + /// A new with type string. public static SchemaNode NewValue() => new() { Type = "string" }; /// /// Serializes a tree to its canonical JSON Schema string. /// /// The schema node to serialize. + /// The canonical JSON Schema string representing the node tree. public static string Serialize(SchemaNode node) { using var stream = new System.IO.MemoryStream(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptParameterNames.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptParameterNames.cs index 515596f2..93f227b1 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptParameterNames.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptParameterNames.cs @@ -13,6 +13,7 @@ public static class ScriptParameterNames /// Parses a parameter definitions JSON Schema and returns the declared parameter names. /// /// JSON Schema or legacy flat-array string; null/empty returns an empty list. + /// A read-only list of declared parameter names. public static IReadOnlyList Parse(string? json) => JsonSchemaShapeParser.ParseParameters(json) .Select(p => p.Name) @@ -23,6 +24,7 @@ public static class ScriptParameterNames /// Parses a parameter definitions JSON Schema and returns the full parameter shape objects. /// /// JSON Schema or legacy flat-array string; null/empty returns an empty list. + /// A read-only list of parameter shape objects with name and type information. public static IReadOnlyList ParseShapes(string? json) => JsonSchemaShapeParser.ParseParameters(json); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs index 9be63854..550c1cf1 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ScriptTriggerConfigCodec.cs @@ -68,6 +68,7 @@ internal static class ScriptTriggerConfigCodec /// Classifies a raw TriggerType string (case-insensitive). /// The raw trigger type string from the template script entity. + /// The matching , or for null/empty. internal static ScriptTriggerKind ParseKind(string? triggerType) { if (string.IsNullOrWhiteSpace(triggerType)) return ScriptTriggerKind.None; @@ -89,6 +90,7 @@ internal static class ScriptTriggerConfigCodec /// (invoked explicitly, never throttled), and None/Unknown. /// /// The raw trigger type string to classify. + /// if the trigger honours MinTimeBetweenRuns; otherwise . internal static bool SupportsMinTimeBetweenRuns(string? triggerType) => ParseKind(triggerType) is ScriptTriggerKind.ValueChange or ScriptTriggerKind.Conditional @@ -96,6 +98,7 @@ internal static class ScriptTriggerConfigCodec /// Canonical TriggerType string for a kind; null for None/Unknown. /// The trigger kind to convert. + /// The canonical trigger-type string, or null for /. internal static string? KindToString(ScriptTriggerKind kind) => kind switch { ScriptTriggerKind.Interval => "Interval", @@ -113,6 +116,7 @@ internal static class ScriptTriggerConfigCodec /// /// The raw JSON trigger configuration string. /// The trigger kind, used to determine which fields to parse. + /// A populated from the JSON; defaults are used for absent or malformed fields. internal static ScriptTriggerModel Parse(string? json, ScriptTriggerKind kind) { var model = new ScriptTriggerModel(); @@ -161,6 +165,7 @@ internal static class ScriptTriggerConfigCodec /// /// The trigger model to serialize. /// The trigger kind, used to determine which fields to emit. + /// The JSON configuration string, or null for /. internal static string? Serialize(ScriptTriggerModel model, ScriptTriggerKind kind) { if (kind is ScriptTriggerKind.None or ScriptTriggerKind.Unknown) return null; @@ -214,6 +219,7 @@ internal static class ScriptTriggerConfigCodec /// Returns if it is a recognized operator, else ">". /// The raw operator string to normalize. + /// A valid operator string from ; defaults to ">" for unrecognized input. internal static string NormalizeOperator(string? raw) { var op = raw?.Trim(); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/TriggerAttributeMapper.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/TriggerAttributeMapper.cs index 2d574dcd..bab273d2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/TriggerAttributeMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/TriggerAttributeMapper.cs @@ -19,6 +19,7 @@ public static class TriggerAttributeMapper { /// Direct and inherited attributes, exposed as Attributes["..."]. /// The full flattened attribute choice list from the trigger editor. + /// The list of s for Direct and Inherited attributes. public static IReadOnlyList SelfAttributes( IReadOnlyList choices) => choices @@ -32,6 +33,7 @@ public static class TriggerAttributeMapper /// are skipped (no child scope to attach them to). /// /// The full flattened attribute choice list from the trigger editor. + /// The list of s, one per distinct composition-instance name. public static IReadOnlyList Children( IReadOnlyList choices) => choices diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/EndpointExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/EndpointExtensions.cs index b2df6453..90adc1b3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/EndpointExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/EndpointExtensions.cs @@ -15,6 +15,7 @@ public static class EndpointExtensions /// /// The root Blazor App component type, supplied by the Host assembly. /// The endpoint route builder to register routes on. + /// The same instance, for call chaining. public static IEndpointRouteBuilder MapCentralUI(this IEndpointRouteBuilder endpoints) where TApp : Microsoft.AspNetCore.Components.IComponent { diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ISharedScriptCatalog.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ISharedScriptCatalog.cs index 166d1820..130a072c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ISharedScriptCatalog.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ISharedScriptCatalog.cs @@ -9,6 +9,7 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis; public interface ISharedScriptCatalog { /// Returns the parameter and return shapes for all registered shared scripts. + /// A task that resolves to the list of all shared script shapes. Task> GetShapesAsync(); /// @@ -18,6 +19,7 @@ public interface ISharedScriptCatalog /// /// Name of the shared script to retrieve. /// Cancellation token for the async lookup. + /// A task that resolves to the matching shared script source, or null if none exists. Task GetByNameAsync(string name, CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs index 7fc6b8b4..fda5d3d4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/InboundScriptHost.cs @@ -32,6 +32,7 @@ public class InboundScriptHost /// Targets a specific instance for method invocation. /// /// The instance code to target. + /// A scoped to the specified instance. public RouteTarget To(string instanceCode) => new(); } @@ -44,6 +45,7 @@ public class InboundScriptHost /// The name of the script to call. /// Optional parameters to pass to the script. /// Cancellation token. + /// A task that resolves to the script's return value, or null. public System.Threading.Tasks.Task Call( string scriptName, object? parameters = null, @@ -55,6 +57,7 @@ public class InboundScriptHost /// /// The name of the attribute to retrieve. /// Cancellation token. + /// A task that resolves to the attribute value, or null if not found. public System.Threading.Tasks.Task GetAttribute( string attributeName, System.Threading.CancellationToken cancellationToken = default) => @@ -65,6 +68,7 @@ public class InboundScriptHost /// /// The names of the attributes to retrieve. /// Cancellation token. + /// A task that resolves to a dictionary mapping attribute names to their values. public System.Threading.Tasks.Task> GetAttributes( IEnumerable attributeNames, System.Threading.CancellationToken cancellationToken = default) => @@ -77,6 +81,7 @@ public class InboundScriptHost /// The name of the attribute to set. /// The value to set. /// Cancellation token. + /// A task representing the asynchronous operation. public System.Threading.Tasks.Task SetAttribute( string attributeName, string value, @@ -88,6 +93,7 @@ public class InboundScriptHost /// /// Dictionary of attribute names to values. /// Cancellation token. + /// A task representing the asynchronous operation. public System.Threading.Tasks.Task SetAttributes( IReadOnlyDictionary attributeValues, System.Threading.CancellationToken cancellationToken = default) => diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/JsonSchemaShapeParser.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/JsonSchemaShapeParser.cs index 33ae73b6..e8808f60 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/JsonSchemaShapeParser.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/JsonSchemaShapeParser.cs @@ -20,6 +20,7 @@ public static class JsonSchemaShapeParser { /// Parses a JSON Schema or legacy flat-array parameters definition and returns the resulting parameter shapes. /// The JSON string to parse; null or whitespace returns an empty list. + /// A read-only list of instances parsed from the definition; empty on null, whitespace, or malformed input. public static IReadOnlyList ParseParameters(string? json) { if (string.IsNullOrWhiteSpace(json)) return Array.Empty(); @@ -41,6 +42,7 @@ public static class JsonSchemaShapeParser /// Parses a JSON Schema or legacy return-type definition and returns the normalised type name, or null if absent or unrecognised. /// The JSON string to parse; null or whitespace returns null. + /// The normalised type name string (e.g. "Boolean", "List<Integer>"), or null if the input is null, whitespace, malformed, or unrecognised. public static string? ParseReturnType(string? json) { if (string.IsNullOrWhiteSpace(json)) return null; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxConsoleCapture.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxConsoleCapture.cs index af9bd4be..2b2d34ab 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxConsoleCapture.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxConsoleCapture.cs @@ -41,6 +41,7 @@ internal sealed class SandboxConsoleCapture : TextWriter /// once for the process. Idempotent and /// thread-safe. Subsequent calls return the already-installed instances. /// + /// The installed instances for stdout and stderr. public static (SandboxConsoleCapture Out, SandboxConsoleCapture Error) Install() { if (_outInstance != null && _errorInstance != null) @@ -72,6 +73,7 @@ internal sealed class SandboxConsoleCapture : TextWriter /// other call-trees are unaffected. /// /// The writer that receives console output for this scope. + /// A that, when disposed, restores the previous capture state. public CaptureScope BeginCapture(StringWriter buffer) { var previous = _current.Value; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxHostHelpers.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxHostHelpers.cs index 0ec32276..2d4a5c50 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxHostHelpers.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxHostHelpers.cs @@ -32,6 +32,7 @@ public class SandboxExternalHelper /// The method name to invoke. /// Optional method parameters. /// Cancellation token. + /// A task that resolves to the from the external system. public Task Call( string systemName, string methodName, @@ -49,6 +50,7 @@ public class SandboxExternalHelper /// The method name to invoke. /// Optional method parameters. /// Cancellation token. + /// A task that resolves to the from the external system. public Task CachedCall( string systemName, string methodName, @@ -80,6 +82,7 @@ public class SandboxDatabaseHelper /// Gets a database connection by name. /// The database connection name. /// Cancellation token. + /// A task that resolves to the open for the named database. public Task Connection(string name, CancellationToken cancellationToken = default) { if (_gateway == null) @@ -93,6 +96,7 @@ public class SandboxDatabaseHelper /// The SQL statement to execute. /// Optional SQL parameters. /// Cancellation token. + /// A task that represents the asynchronous operation. public Task CachedWrite( string name, string sql, @@ -123,6 +127,7 @@ public class SandboxNotifyHelper { /// Selects the notification list to send to. /// The notification list name. + /// A for the specified list. public SandboxNotifyTarget To(string listName) => new(); @@ -133,6 +138,7 @@ public class SandboxNotifyHelper /// NotifyHelper.Status. /// /// The notification ID to check status for. + /// A task that resolves to a placeholder with status "Unknown". public Task Status(string notificationId) => Task.FromResult(new NotificationDeliveryStatus("Unknown", 0, null, null)); } @@ -156,6 +162,7 @@ public class SandboxNotifyTarget /// The notification subject. /// The notification message. /// Cancellation token. + /// A task that resolves to a fake notification ID string (a random GUID). public Task Send(string subject, string message, CancellationToken cancellationToken = default) => Task.FromResult(Guid.NewGuid().ToString("N")); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxInboundScriptHost.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxInboundScriptHost.cs index 73be99fa..639a0f40 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxInboundScriptHost.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxInboundScriptHost.cs @@ -30,6 +30,7 @@ public class SandboxInboundScriptHost /// Creates a sandbox route target that throws on every operation. /// /// The instance code (used only in the exception message). + /// A sandbox route target bound to . public RouteTarget To(string instanceCode) => new(instanceCode); } @@ -50,6 +51,7 @@ public class SandboxInboundScriptHost /// Script name (included in the exception message). /// Unused parameters. /// Unused token. + /// Never returns; always throws . public Task Call( string scriptName, object? parameters = null, @@ -61,6 +63,7 @@ public class SandboxInboundScriptHost /// /// Attribute name (included in the exception message). /// Unused token. + /// Never returns; always throws . public Task GetAttribute( string attributeName, CancellationToken cancellationToken = default) => @@ -71,6 +74,7 @@ public class SandboxInboundScriptHost /// /// Attribute names (unused). /// Unused token. + /// Never returns; always throws . public Task> GetAttributes( IEnumerable attributeNames, CancellationToken cancellationToken = default) => @@ -82,6 +86,7 @@ public class SandboxInboundScriptHost /// Attribute name (included in the exception message). /// Unused value. /// Unused token. + /// Never returns; always throws . public Task SetAttribute( string attributeName, string value, @@ -93,6 +98,7 @@ public class SandboxInboundScriptHost /// /// Unused attribute values. /// Unused token. + /// Never returns; always throws . public Task SetAttributes( IReadOnlyDictionary attributeValues, CancellationToken cancellationToken = default) => diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs index c0fc79ed..a2367b83 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/SandboxScriptHost.cs @@ -102,6 +102,7 @@ public interface ISandboxInstanceGateway /// The canonical name of the attribute. /// The value to set. /// Cancellation token. + /// A task that represents the asynchronous operation. Task SetAttributeAsync(string canonicalName, string value, CancellationToken ct); /// diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ScriptShapeParser.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ScriptShapeParser.cs index 402a206b..89418efe 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ScriptShapeParser.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ScriptAnalysis/ScriptShapeParser.cs @@ -12,6 +12,7 @@ public static class ScriptShapeParser /// The canonical script name. /// The JSON Schema or legacy flat-array parameters definition, or null for parameterless scripts. /// The JSON Schema or legacy return-type definition, or null for void scripts. + /// A describing the script's parameter list and return type. public static ScriptShape Parse(string name, string? parametersJson, string? returnJson) { var parameters = JsonSchemaShapeParser.ParseParameters(parametersJson); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ServiceCollectionExtensions.cs index aa802860..48ae823d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/ServiceCollectionExtensions.cs @@ -14,6 +14,7 @@ public static class ServiceCollectionExtensions /// Registers all Central UI services including Blazor, auth state, dialogs, audit query, and script analysis. /// /// The service collection to configure. + /// The instance for chaining. public static IServiceCollection AddCentralUI(this IServiceCollection services) { services.AddRazorComponents() diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/ApiMethodKeyScopeReconciler.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/ApiMethodKeyScopeReconciler.cs index 900e5788..70fe6f78 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/ApiMethodKeyScopeReconciler.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/ApiMethodKeyScopeReconciler.cs @@ -45,6 +45,7 @@ public static class ApiMethodKeyScopeReconciler /// Each affected key's CURRENT full scope set, keyed by KeyId. /// Read fresh from the seam right before reconciling so concurrent edits do not get clobbered. /// Display names by KeyId, for human-readable empty-scope messages. + /// A with the scope updates to apply and any empty-scope warnings. public static ReconcileResult Reconcile( string methodName, IReadOnlySet selectedKeyIds, diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditEventView.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditEventView.cs index 2aada8e4..2b82a602 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditEventView.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditEventView.cs @@ -70,6 +70,8 @@ public sealed record AuditEventView /// /// Decomposes a canonical into a flat view for the UI. /// + /// The canonical audit event to decompose. + /// A flat populated from the event's top-level and details fields. public static AuditEventView From(AuditEvent evt) { var r = AuditRowProjection.Decompose(evt); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditLogExportService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditLogExportService.cs index ae98f237..4769d27c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditLogExportService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditLogExportService.cs @@ -42,6 +42,7 @@ public interface IAuditLogExportService /// enough to amortise the per-query overhead, small enough that one page in /// memory is bounded. /// + /// A task that completes when all matching rows (up to ) have been written to . Task ExportAsync( AuditLogQueryFilter filter, int maxRows, @@ -176,6 +177,7 @@ public sealed class AuditLogExportService : IAuditLogExportService /// cleanly on another. /// /// The audit event view to format as a CSV row. + /// An RFC 4180 CSV row string (no trailing newline) for the supplied event. internal static string FormatCsvRow(AuditEventView evt) { var sb = new StringBuilder(256); diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IAuditLogQueryService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IAuditLogQueryService.cs index 8bc87f6d..9a7d7c70 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IAuditLogQueryService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IAuditLogQueryService.cs @@ -28,6 +28,7 @@ public interface IAuditLogQueryService /// Filter criteria applied to the audit log query. /// Optional paging cursor; defaults to first page when null. /// Cancellation token. + /// A task that resolves to a page of audit event views matching the filter. Task> QueryAsync( AuditLogQueryFilter filter, AuditLogPaging? paging = null, @@ -57,6 +58,7 @@ public interface IAuditLogQueryService /// dashboard. /// /// Cancellation token. + /// A task that resolves to the current audit KPI snapshot. Task GetKpiSnapshotAsync(CancellationToken ct = default); /// @@ -76,6 +78,7 @@ public interface IAuditLogQueryService /// /// Any execution id in the chain to look up. /// Cancellation token. + /// A task that resolves to the flat list of execution tree nodes in the chain. Task> GetExecutionTreeAsync( Guid executionId, CancellationToken ct = default); @@ -90,5 +93,6 @@ public interface IAuditLogQueryService /// filter affordance. /// /// Cancellation token. + /// A task that resolves to the distinct non-null source node names present in the audit log. Task> GetDistinctSourceNodesAsync(CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBindingTester.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBindingTester.cs index 028987e8..2005fc7b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBindingTester.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBindingTester.cs @@ -31,6 +31,7 @@ public interface IBindingTester /// Name of the site-local data connection — the site's DataConnectionManagerActor indexes its children by name. /// Tag paths to read. /// Cancellation token. + /// A task that resolves to the read outcomes for all requested tag paths. Task ReadAsync( string siteId, string connectionName, diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBrowseService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBrowseService.cs index f70f2025..8e45feba 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBrowseService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/IBrowseService.cs @@ -29,6 +29,7 @@ public interface IBrowseService /// Name of the site-local data connection to browse against — the site's DataConnectionManagerActor indexes its children by name. /// Node to browse, or null to browse from the server root. /// Cancellation token. + /// A task that resolves to a containing child nodes or a on error. Task BrowseChildrenAsync( string siteId, string connectionName, diff --git a/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ClusterOptionsValidator.cs b/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ClusterOptionsValidator.cs index 9e4b6290..7416f2eb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ClusterOptionsValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ClusterOptionsValidator.cs @@ -18,11 +18,7 @@ public sealed class ClusterOptionsValidator : OptionsValidatorBase - /// Validates the cluster options, recording a failure if any critical settings are misconfigured. - /// - /// The accumulator to record failures on. - /// The cluster options to validate. + /// protected override void Validate(ValidationBuilder builder, ClusterOptions options) { // CI-012: design doc states "both nodes are seed nodes — each node lists diff --git a/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ServiceCollectionExtensions.cs index 4ad073a9..4e9fb9bd 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ClusterInfrastructure/ServiceCollectionExtensions.cs @@ -23,6 +23,7 @@ public static class ServiceCollectionExtensions /// /// /// The service collection to register into. + /// The same instance, for call chaining. public static IServiceCollection AddClusterInfrastructure(this IServiceCollection services) { services.TryAddEnumerable( diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IAlarmSubscribableConnection.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IAlarmSubscribableConnection.cs index c9c18b25..f02dae67 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IAlarmSubscribableConnection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IAlarmSubscribableConnection.cs @@ -20,9 +20,17 @@ public interface IAlarmSubscribableConnection /// currently-active conditions (Snapshot…SnapshotComplete) on every /// (re)subscribe. Returns a subscription id for . /// + /// The source object reference to subscribe alarms for. + /// Optional condition name filter; null subscribes to all conditions. + /// Delegate invoked on each incoming alarm transition. + /// Cancellation token. + /// A task that resolves to the subscription id for use with . Task SubscribeAlarmsAsync(string sourceReference, string? conditionFilter, AlarmTransitionCallback callback, CancellationToken cancellationToken = default); /// Cancels an active alarm subscription by its id. + /// The subscription id returned by . + /// Cancellation token. + /// A task that represents the asynchronous operation. Task UnsubscribeAlarmsAsync(string subscriptionId, CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IBrowsableDataConnection.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IBrowsableDataConnection.cs index ff7ae19c..740af83a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IBrowsableDataConnection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IBrowsableDataConnection.cs @@ -14,6 +14,7 @@ public interface IBrowsableDataConnection /// /// Node id whose children to browse, or null for the server root (OPC UA ObjectsFolder). /// Cancellation token; on cancellation the implementation should throw . + /// A task that resolves to the child nodes and a flag indicating whether results were truncated. Task BrowseChildrenAsync( string? parentNodeId, CancellationToken cancellationToken = default); @@ -44,5 +45,7 @@ public enum BrowseNodeClass { Object, Variable, Method, Other } /// public sealed class ConnectionNotConnectedException : InvalidOperationException { + /// Initializes a new with the specified error message. + /// Message describing why the connection is not currently connected. public ConnectionNotConnectedException(string message) : base(message) { } } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IDataConnection.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IDataConnection.cs index 9edba96c..44ea692a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IDataConnection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Protocol/IDataConnection.cs @@ -18,9 +18,11 @@ public interface IDataConnection : IAsyncDisposable /// Establishes the protocol connection using the provided connection details. /// Protocol-specific key-value configuration pairs. /// Cancellation token. + /// A task that represents the asynchronous operation. Task ConnectAsync(IDictionary connectionDetails, CancellationToken cancellationToken = default); /// Gracefully terminates the protocol connection. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DisconnectAsync(CancellationToken cancellationToken = default); /// Subscribes to value-change notifications for a tag path; returns a subscription ID. /// The tag path to subscribe to. @@ -31,6 +33,7 @@ public interface IDataConnection : IAsyncDisposable /// Cancels an active subscription by its ID. /// The subscription ID returned by . /// Cancellation token. + /// A task that represents the asynchronous operation. Task UnsubscribeAsync(string subscriptionId, CancellationToken cancellationToken = default); /// Reads the current value of a single tag. /// The tag path to read. diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IAuditLogRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IAuditLogRepository.cs index ffefb926..d709661a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IAuditLogRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IAuditLogRepository.cs @@ -31,6 +31,7 @@ public interface IAuditLogRepository /// /// The audit event to insert. /// Cancellation token. + /// A task that represents the asynchronous operation. Task InsertIfNotExistsAsync(AuditEvent evt, CancellationToken ct = default); /// @@ -44,6 +45,7 @@ public interface IAuditLogRepository /// Filter criteria to apply to the query. /// Paging cursor and page size. /// Cancellation token. + /// A task that resolves to the matching audit events for the requested page, ordered by (OccurredAtUtc DESC, EventId DESC). Task> QueryAsync( AuditLogQueryFilter filter, AuditLogPaging paging, @@ -82,6 +84,7 @@ public interface IAuditLogRepository /// /// Lower-bound datetime of the monthly partition to switch out. /// Cancellation token. + /// A task that resolves to the approximate number of rows discarded by the partition switch. Task SwitchOutPartitionAsync(DateTime monthBoundary, CancellationToken ct = default); /// @@ -94,6 +97,7 @@ public interface IAuditLogRepository /// /// Only partitions whose data is entirely older than this UTC datetime are returned. /// Cancellation token. + /// A task that resolves to the list of partition lower-bound boundaries eligible for purge. Task> GetPartitionBoundariesOlderThanAsync( DateTime threshold, CancellationToken ct = default); @@ -183,6 +187,7 @@ public interface IAuditLogRepository /// /// Any execution id in the chain; the implementation walks to the root and back down. /// Cancellation token. + /// A task that resolves to the full execution tree rooted at the topmost ancestor, one node per distinct execution. Task> GetExecutionTreeAsync( Guid executionId, CancellationToken ct = default); @@ -194,5 +199,6 @@ public interface IAuditLogRepository /// for ~60s so the repository is hit at most once per minute per circuit. /// /// Cancellation token. + /// A task that resolves to the distinct, non-null source node names in ascending order. Task> GetDistinctSourceNodesAsync(CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ICentralUiRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ICentralUiRepository.cs index 2fab7331..5c73de68 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ICentralUiRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ICentralUiRepository.cs @@ -10,30 +10,37 @@ public interface ICentralUiRepository { /// Returns all configured sites. /// Cancellation token. + /// A task that resolves to a read-only list of all sites. Task> GetAllSitesAsync(CancellationToken cancellationToken = default); /// Returns all data connections for the specified site. /// The site database ID to filter by. /// Cancellation token. + /// A task that resolves to a read-only list of data connections for the site. Task> GetDataConnectionsBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); /// Returns all data connections across all sites. /// Cancellation token. + /// A task that resolves to a read-only list of all data connections. Task> GetAllDataConnectionsAsync(CancellationToken cancellationToken = default); /// Returns the full template tree including folders and templates. /// Cancellation token. + /// A task that resolves to a read-only list of templates. Task> GetTemplateTreeAsync(CancellationToken cancellationToken = default); /// Returns instances filtered by optional site, template, or search term. /// Optional site ID to filter by. /// Optional template ID to filter by. /// Optional keyword to filter instance names. /// Cancellation token. + /// A task that resolves to a read-only list of matching instances. Task> GetInstancesFilteredAsync(int? siteId = null, int? templateId = null, string? searchTerm = null, CancellationToken cancellationToken = default); /// Returns the most recent deployment records up to the specified count. /// Maximum number of records to return. /// Cancellation token. + /// A task that resolves to a read-only list of recent deployment records. Task> GetRecentDeploymentsAsync(int count, CancellationToken cancellationToken = default); /// Returns the area tree for the specified site. /// The site database ID. /// Cancellation token. + /// A task that resolves to a read-only list of areas for the site. Task> GetAreaTreeBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); // Audit log queries @@ -51,6 +58,7 @@ public interface ICentralUiRepository /// One-based page number. /// Number of entries per page. /// Cancellation token. + /// A task that resolves to a tuple of the matching entries and the total count. Task<(IReadOnlyList Entries, int TotalCount)> GetAuditLogEntriesAsync( string? user = null, string? entityType = null, @@ -66,5 +74,6 @@ public interface ICentralUiRepository /// Persists pending changes to the underlying store. /// Cancellation token. + /// A task that resolves to the number of entities written. Task SaveChangesAsync(CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IExternalSystemRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IExternalSystemRepository.cs index 10a4be7b..a8de5ae4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IExternalSystemRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IExternalSystemRepository.cs @@ -36,6 +36,7 @@ public interface IExternalSystemRepository /// /// The external system definition to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddExternalSystemAsync(ExternalSystemDefinition definition, CancellationToken cancellationToken = default); /// @@ -43,6 +44,7 @@ public interface IExternalSystemRepository /// /// The external system definition to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateExternalSystemAsync(ExternalSystemDefinition definition, CancellationToken cancellationToken = default); /// @@ -50,6 +52,7 @@ public interface IExternalSystemRepository /// /// The external system ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteExternalSystemAsync(int id, CancellationToken cancellationToken = default); // ExternalSystemMethod @@ -86,6 +89,7 @@ public interface IExternalSystemRepository /// /// The external system method to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddExternalSystemMethodAsync(ExternalSystemMethod method, CancellationToken cancellationToken = default); /// @@ -93,6 +97,7 @@ public interface IExternalSystemRepository /// /// The external system method to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateExternalSystemMethodAsync(ExternalSystemMethod method, CancellationToken cancellationToken = default); /// @@ -100,6 +105,7 @@ public interface IExternalSystemRepository /// /// The method ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteExternalSystemMethodAsync(int id, CancellationToken cancellationToken = default); // DatabaseConnectionDefinition @@ -135,6 +141,7 @@ public interface IExternalSystemRepository /// /// The database connection definition to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddDatabaseConnectionAsync(DatabaseConnectionDefinition definition, CancellationToken cancellationToken = default); /// @@ -142,6 +149,7 @@ public interface IExternalSystemRepository /// /// The database connection definition to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateDatabaseConnectionAsync(DatabaseConnectionDefinition definition, CancellationToken cancellationToken = default); /// @@ -149,6 +157,7 @@ public interface IExternalSystemRepository /// /// The database connection ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteDatabaseConnectionAsync(int id, CancellationToken cancellationToken = default); /// diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IInboundApiRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IInboundApiRepository.cs index f12e3c65..6fb01e44 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IInboundApiRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/IInboundApiRepository.cs @@ -14,28 +14,35 @@ public interface IInboundApiRepository /// Retrieves an API method by ID. /// The API method ID. /// Cancellation token. + /// A task that resolves to the matching , or null if not found. Task GetApiMethodByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves all API methods. /// Cancellation token. + /// A task that resolves to a read-only list of all entities. Task> GetAllApiMethodsAsync(CancellationToken cancellationToken = default); /// Retrieves an API method by name. /// The API method name. /// Cancellation token. + /// A task that resolves to the matching , or null if not found. Task GetMethodByNameAsync(string name, CancellationToken cancellationToken = default); /// Adds a new API method. /// The API method to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddApiMethodAsync(ApiMethod method, CancellationToken cancellationToken = default); /// Updates an existing API method. /// The API method to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateApiMethodAsync(ApiMethod method, CancellationToken cancellationToken = default); /// Deletes an API method by ID. /// The API method ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteApiMethodAsync(int id, CancellationToken cancellationToken = default); /// Saves pending changes to the database. /// Cancellation token. + /// A task that resolves to the number of state entries written to the database. Task SaveChangesAsync(CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationOutboxRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationOutboxRepository.cs index 58f85989..45e38b0d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationOutboxRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationOutboxRepository.cs @@ -51,6 +51,7 @@ public interface INotificationOutboxRepository /// /// The notification to update. /// Cancellation token. + /// A task that completes when the notification has been persisted. Task UpdateAsync(Notification n, CancellationToken cancellationToken = default); /// diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationRepository.cs index 657ad44f..f95390b0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/INotificationRepository.cs @@ -25,16 +25,19 @@ public interface INotificationRepository /// Adds a new notification list. /// The notification list to add. /// Cancellation token. + /// A task representing the asynchronous operation. Task AddNotificationListAsync(NotificationList list, CancellationToken cancellationToken = default); /// Updates an existing notification list. /// The notification list to update. /// Cancellation token. + /// A task representing the asynchronous operation. Task UpdateNotificationListAsync(NotificationList list, CancellationToken cancellationToken = default); /// Deletes a notification list by ID. /// The notification list ID. /// Cancellation token. + /// A task representing the asynchronous operation. Task DeleteNotificationListAsync(int id, CancellationToken cancellationToken = default); // NotificationRecipient @@ -53,16 +56,19 @@ public interface INotificationRepository /// Adds a new notification recipient. /// The recipient to add. /// Cancellation token. + /// A task representing the asynchronous operation. Task AddRecipientAsync(NotificationRecipient recipient, CancellationToken cancellationToken = default); /// Updates an existing notification recipient. /// The recipient to update. /// Cancellation token. + /// A task representing the asynchronous operation. Task UpdateRecipientAsync(NotificationRecipient recipient, CancellationToken cancellationToken = default); /// Deletes a notification recipient by ID. /// The recipient ID. /// Cancellation token. + /// A task representing the asynchronous operation. Task DeleteRecipientAsync(int id, CancellationToken cancellationToken = default); // SmtpConfiguration @@ -80,16 +86,19 @@ public interface INotificationRepository /// Adds a new SMTP configuration. /// The SMTP configuration to add. /// Cancellation token. + /// A task representing the asynchronous operation. Task AddSmtpConfigurationAsync(SmtpConfiguration configuration, CancellationToken cancellationToken = default); /// Updates an existing SMTP configuration. /// The SMTP configuration to update. /// Cancellation token. + /// A task representing the asynchronous operation. Task UpdateSmtpConfigurationAsync(SmtpConfiguration configuration, CancellationToken cancellationToken = default); /// Deletes an SMTP configuration by ID. /// The SMTP configuration ID. /// Cancellation token. + /// A task representing the asynchronous operation. Task DeleteSmtpConfigurationAsync(int id, CancellationToken cancellationToken = default); /// Saves pending changes to the repository. diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteCallAuditRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteCallAuditRepository.cs index 3b7bef80..87f949f5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteCallAuditRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteCallAuditRepository.cs @@ -39,6 +39,7 @@ public interface ISiteCallAuditRepository /// /// The site call row to insert or monotonically update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpsertAsync(SiteCall siteCall, CancellationToken ct = default); /// @@ -46,6 +47,7 @@ public interface ISiteCallAuditRepository /// /// The tracked operation id to look up. /// Cancellation token. + /// A task that resolves to the matching , or null if no row exists. Task GetAsync(TrackedOperationId id, CancellationToken ct = default); /// @@ -58,6 +60,7 @@ public interface ISiteCallAuditRepository /// Filter criteria for the query. /// Keyset paging parameters. /// Cancellation token. + /// A task that resolves to a page of rows matching the filter, ordered by creation time descending. Task> QueryAsync( SiteCallQueryFilter filter, SiteCallPaging paging, @@ -71,6 +74,7 @@ public interface ISiteCallAuditRepository /// /// UTC cutoff; terminal rows older than this are deleted. /// Cancellation token. + /// A task that resolves to the number of rows deleted. Task PurgeTerminalAsync(DateTime olderThanUtc, CancellationToken ct = default); /// @@ -84,6 +88,7 @@ public interface ISiteCallAuditRepository /// UTC threshold for classifying a row as stuck. /// UTC start of the delivered/failed interval window. /// Cancellation token. + /// A task that resolves to a global computed from the current table state. Task ComputeKpisAsync( DateTime stuckCutoff, DateTime intervalSince, @@ -97,6 +102,7 @@ public interface ISiteCallAuditRepository /// UTC threshold for classifying a row as stuck. /// UTC start of the delivered/failed interval window. /// Cancellation token. + /// A task that resolves to a per-site KPI list; sites with no rows are omitted. Task> ComputePerSiteKpisAsync( DateTime stuckCutoff, DateTime intervalSince, diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteRepository.cs index c92a1ea8..0a779a68 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ISiteRepository.cs @@ -12,59 +12,73 @@ public interface ISiteRepository /// Retrieves a site by its ID. /// The site primary key. /// Cancellation token. + /// A task that resolves to the matching , or null if not found. Task GetSiteByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves a site by its identifier. /// The unique site identifier string. /// Cancellation token. + /// A task that resolves to the matching , or null if not found. Task GetSiteByIdentifierAsync(string siteIdentifier, CancellationToken cancellationToken = default); /// Retrieves all sites. /// Cancellation token. + /// A task that resolves to a read-only list of all entities. Task> GetAllSitesAsync(CancellationToken cancellationToken = default); /// Adds a new site. /// The site entity to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddSiteAsync(Site site, CancellationToken cancellationToken = default); /// Updates an existing site. /// The site entity with updated values. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateSiteAsync(Site site, CancellationToken cancellationToken = default); /// Deletes a site. /// The site primary key. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteSiteAsync(int id, CancellationToken cancellationToken = default); // Data Connections /// Retrieves a data connection by its ID. /// The data connection primary key. /// Cancellation token. + /// A task that resolves to the matching , or null if not found. Task GetDataConnectionByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves all data connections. /// Cancellation token. + /// A task that resolves to a read-only list of all entities. Task> GetAllDataConnectionsAsync(CancellationToken cancellationToken = default); /// Retrieves all data connections for a site. /// The site primary key to filter by. /// Cancellation token. + /// A task that resolves to a read-only list of entities for the given site. Task> GetDataConnectionsBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); /// Adds a new data connection. /// The data connection entity to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddDataConnectionAsync(DataConnection connection, CancellationToken cancellationToken = default); /// Updates an existing data connection. /// The data connection entity with updated values. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateDataConnectionAsync(DataConnection connection, CancellationToken cancellationToken = default); /// Deletes a data connection. /// The data connection primary key. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteDataConnectionAsync(int id, CancellationToken cancellationToken = default); // Instances (for deletion constraint checks) /// Retrieves all instances deployed to a site. /// The site primary key to filter by. /// Cancellation token. + /// A task that resolves to a read-only list of entities for the given site. Task> GetInstancesBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); /// Saves all pending changes to the database. /// Cancellation token. + /// A task that resolves to the number of state entries written to the database. Task SaveChangesAsync(CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ITemplateEngineRepository.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ITemplateEngineRepository.cs index b666318f..c77ab885 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ITemplateEngineRepository.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Repositories/ITemplateEngineRepository.cs @@ -10,10 +10,12 @@ public interface ITemplateEngineRepository /// Retrieves a template by ID. /// The template ID. /// Cancellation token. + /// A task that resolves to the matching template, or if not found. Task GetTemplateByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves a template with its child entities by ID. /// The template ID. /// Cancellation token. + /// A task that resolves to the matching template with children loaded, or if not found. Task GetTemplateWithChildrenAsync(int id, CancellationToken cancellationToken = default); /// /// Bulk variant of @@ -26,9 +28,11 @@ public interface ITemplateEngineRepository /// /// Template names to load. Duplicate / null / empty names are filtered out. /// Cancellation token. + /// A task that resolves to a read-only list of matched templates with children loaded. Task> GetTemplatesWithChildrenAsync(IEnumerable names, CancellationToken cancellationToken = default); /// Retrieves all templates. /// Cancellation token. + /// A task that resolves to a read-only list of all templates. Task> GetAllTemplatesAsync(CancellationToken cancellationToken = default); /// /// Returns every template that contains a composition referencing @@ -38,293 +42,386 @@ public interface ITemplateEngineRepository /// /// The composed template ID. /// Cancellation token. + /// A task that resolves to a read-only list of parent templates that reference the composed template. Task> GetTemplatesComposingAsync(int composedTemplateId, CancellationToken cancellationToken = default); /// Adds a new template. /// The template to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateAsync(Template template, CancellationToken cancellationToken = default); /// Updates an existing template. /// The template to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateAsync(Template template, CancellationToken cancellationToken = default); /// Deletes a template by ID. /// The template ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateAsync(int id, CancellationToken cancellationToken = default); // TemplateAttribute /// Retrieves a template attribute by ID. /// The attribute ID. /// Cancellation token. + /// A task that resolves to the matching attribute, or if not found. Task GetTemplateAttributeByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves attributes for a template. /// The template ID. /// Cancellation token. + /// A task that resolves to a read-only list of attributes for the specified template. Task> GetAttributesByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Adds a new template attribute. /// The attribute to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateAttributeAsync(TemplateAttribute attribute, CancellationToken cancellationToken = default); /// Updates an existing template attribute. /// The attribute to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateAttributeAsync(TemplateAttribute attribute, CancellationToken cancellationToken = default); /// Deletes a template attribute by ID. /// The attribute ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateAttributeAsync(int id, CancellationToken cancellationToken = default); // TemplateAlarm /// Retrieves a template alarm by ID. /// The alarm ID. /// Cancellation token. + /// A task that resolves to the matching alarm, or if not found. Task GetTemplateAlarmByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves alarms for a template. /// The template ID. /// Cancellation token. + /// A task that resolves to a read-only list of alarms for the specified template. Task> GetAlarmsByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Adds a new template alarm. /// The alarm to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateAlarmAsync(TemplateAlarm alarm, CancellationToken cancellationToken = default); /// Updates an existing template alarm. /// The alarm to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateAlarmAsync(TemplateAlarm alarm, CancellationToken cancellationToken = default); /// Deletes a template alarm by ID. /// The alarm ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateAlarmAsync(int id, CancellationToken cancellationToken = default); // TemplateNativeAlarmSource /// Retrieves a template native alarm source by ID. + /// The native alarm source ID. + /// Cancellation token. + /// A task that resolves to the matching native alarm source, or if not found. Task GetTemplateNativeAlarmSourceByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves native alarm sources for a template. + /// The template ID. + /// Cancellation token. + /// A task that resolves to a read-only list of native alarm sources for the specified template. Task> GetNativeAlarmSourcesByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Adds a new template native alarm source. + /// The native alarm source to add. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateNativeAlarmSourceAsync(TemplateNativeAlarmSource source, CancellationToken cancellationToken = default); /// Updates an existing template native alarm source. + /// The native alarm source to update. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateNativeAlarmSourceAsync(TemplateNativeAlarmSource source, CancellationToken cancellationToken = default); /// Deletes a template native alarm source by ID. + /// The native alarm source ID. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateNativeAlarmSourceAsync(int id, CancellationToken cancellationToken = default); // TemplateScript /// Retrieves a template script by ID. /// The script ID. /// Cancellation token. + /// A task that resolves to the matching script, or if not found. Task GetTemplateScriptByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves scripts for a template. /// The template ID. /// Cancellation token. + /// A task that resolves to a read-only list of scripts for the specified template. Task> GetScriptsByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Adds a new template script. /// The script to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateScriptAsync(TemplateScript script, CancellationToken cancellationToken = default); /// Updates an existing template script. /// The script to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateScriptAsync(TemplateScript script, CancellationToken cancellationToken = default); /// Deletes a template script by ID. /// The script ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateScriptAsync(int id, CancellationToken cancellationToken = default); // TemplateComposition /// Retrieves a template composition by ID. /// The composition ID. /// Cancellation token. + /// A task that resolves to the matching composition, or if not found. Task GetTemplateCompositionByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves compositions for a template. /// The template ID. /// Cancellation token. + /// A task that resolves to a read-only list of compositions for the specified template. Task> GetCompositionsByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Adds a new template composition. /// The composition to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddTemplateCompositionAsync(TemplateComposition composition, CancellationToken cancellationToken = default); /// Updates an existing template composition. /// The composition to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateTemplateCompositionAsync(TemplateComposition composition, CancellationToken cancellationToken = default); /// Deletes a template composition by ID. /// The composition ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteTemplateCompositionAsync(int id, CancellationToken cancellationToken = default); // Instance /// Retrieves an instance by ID. /// The instance ID. /// Cancellation token. + /// A task that resolves to the matching instance, or if not found. Task GetInstanceByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves all instances. /// Cancellation token. + /// A task that resolves to a read-only list of all instances. Task> GetAllInstancesAsync(CancellationToken cancellationToken = default); /// Retrieves instances for a template. /// The template ID. /// Cancellation token. + /// A task that resolves to a read-only list of instances for the specified template. Task> GetInstancesByTemplateIdAsync(int templateId, CancellationToken cancellationToken = default); /// Retrieves instances for a site. /// The site ID. /// Cancellation token. + /// A task that resolves to a read-only list of instances for the specified site. Task> GetInstancesBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); /// Retrieves an instance by unique name. /// The unique instance name. /// Cancellation token. + /// A task that resolves to the matching instance, or if not found. Task GetInstanceByUniqueNameAsync(string uniqueName, CancellationToken cancellationToken = default); /// Adds a new instance. /// The instance to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddInstanceAsync(Instance instance, CancellationToken cancellationToken = default); /// Updates an existing instance. /// The instance to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateInstanceAsync(Instance instance, CancellationToken cancellationToken = default); /// Deletes an instance by ID. /// The instance ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteInstanceAsync(int id, CancellationToken cancellationToken = default); // InstanceAttributeOverride /// Retrieves attribute overrides for an instance. /// The instance ID. /// Cancellation token. + /// A task that resolves to a read-only list of attribute overrides for the specified instance. Task> GetOverridesByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default); /// Adds a new instance attribute override. /// The override to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddInstanceAttributeOverrideAsync(InstanceAttributeOverride attributeOverride, CancellationToken cancellationToken = default); /// Updates an existing instance attribute override. /// The override to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateInstanceAttributeOverrideAsync(InstanceAttributeOverride attributeOverride, CancellationToken cancellationToken = default); /// Deletes an instance attribute override by ID. /// The override ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteInstanceAttributeOverrideAsync(int id, CancellationToken cancellationToken = default); // InstanceAlarmOverride /// Retrieves alarm overrides for an instance. /// The instance ID. /// Cancellation token. + /// A task that resolves to a read-only list of alarm overrides for the specified instance. Task> GetAlarmOverridesByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default); /// Retrieves an alarm override by instance and alarm name. /// The instance ID. /// The alarm canonical name. /// Cancellation token. + /// A task that resolves to the matching alarm override, or if not found. Task GetAlarmOverrideAsync(int instanceId, string alarmCanonicalName, CancellationToken cancellationToken = default); /// Adds a new instance alarm override. /// The override to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddInstanceAlarmOverrideAsync(InstanceAlarmOverride alarmOverride, CancellationToken cancellationToken = default); /// Updates an existing instance alarm override. /// The override to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateInstanceAlarmOverrideAsync(InstanceAlarmOverride alarmOverride, CancellationToken cancellationToken = default); /// Deletes an instance alarm override by ID. /// The override ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteInstanceAlarmOverrideAsync(int id, CancellationToken cancellationToken = default); // InstanceNativeAlarmSourceOverride /// Retrieves native alarm source overrides for an instance. + /// The instance ID. + /// Cancellation token. + /// A task that resolves to a read-only list of native alarm source overrides for the specified instance. Task> GetNativeAlarmSourceOverridesByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default); /// Retrieves a single native alarm source override by instance + source canonical name. + /// The instance ID. + /// The canonical name of the native alarm source. + /// Cancellation token. + /// A task that resolves to the matching override, or if not found. Task GetNativeAlarmSourceOverrideAsync(int instanceId, string sourceCanonicalName, CancellationToken cancellationToken = default); /// Adds a new instance native alarm source override. + /// The override to add. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddInstanceNativeAlarmSourceOverrideAsync(InstanceNativeAlarmSourceOverride ovr, CancellationToken cancellationToken = default); /// Updates an existing instance native alarm source override. + /// The override to update. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateInstanceNativeAlarmSourceOverrideAsync(InstanceNativeAlarmSourceOverride ovr, CancellationToken cancellationToken = default); /// Deletes an instance native alarm source override by ID. + /// The override ID. + /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteInstanceNativeAlarmSourceOverrideAsync(int id, CancellationToken cancellationToken = default); // InstanceConnectionBinding /// Retrieves connection bindings for an instance. /// The instance ID. /// Cancellation token. + /// A task that resolves to a read-only list of connection bindings for the specified instance. Task> GetBindingsByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default); /// Adds a new instance connection binding. /// The binding to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddInstanceConnectionBindingAsync(InstanceConnectionBinding binding, CancellationToken cancellationToken = default); /// Updates an existing instance connection binding. /// The binding to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateInstanceConnectionBindingAsync(InstanceConnectionBinding binding, CancellationToken cancellationToken = default); /// Deletes an instance connection binding by ID. /// The binding ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteInstanceConnectionBindingAsync(int id, CancellationToken cancellationToken = default); // Area /// Retrieves an area by ID. /// The area ID. /// Cancellation token. + /// A task that resolves to the matching area, or if not found. Task GetAreaByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves areas for a site. /// The site ID. /// Cancellation token. + /// A task that resolves to a read-only list of areas for the specified site. Task> GetAreasBySiteIdAsync(int siteId, CancellationToken cancellationToken = default); /// Adds a new area. /// The area to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddAreaAsync(Area area, CancellationToken cancellationToken = default); /// Updates an existing area. /// The area to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateAreaAsync(Area area, CancellationToken cancellationToken = default); /// Deletes an area by ID. /// The area ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteAreaAsync(int id, CancellationToken cancellationToken = default); // SharedScript /// Retrieves a shared script by ID. /// The script ID. /// Cancellation token. + /// A task that resolves to the matching shared script, or if not found. Task GetSharedScriptByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves a shared script by name. /// The script name. /// Cancellation token. + /// A task that resolves to the matching shared script, or if not found. Task GetSharedScriptByNameAsync(string name, CancellationToken cancellationToken = default); /// Retrieves all shared scripts. /// Cancellation token. + /// A task that resolves to a read-only list of all shared scripts. Task> GetAllSharedScriptsAsync(CancellationToken cancellationToken = default); /// Adds a new shared script. /// The script to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddSharedScriptAsync(SharedScript sharedScript, CancellationToken cancellationToken = default); /// Updates an existing shared script. /// The script to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateSharedScriptAsync(SharedScript sharedScript, CancellationToken cancellationToken = default); /// Deletes a shared script by ID. /// The script ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteSharedScriptAsync(int id, CancellationToken cancellationToken = default); // TemplateFolder /// Retrieves a template folder by ID. /// The folder ID. /// Cancellation token. + /// A task that resolves to the matching folder, or if not found. Task GetFolderByIdAsync(int id, CancellationToken cancellationToken = default); /// Retrieves all template folders. /// Cancellation token. + /// A task that resolves to a read-only list of all template folders. Task> GetAllFoldersAsync(CancellationToken cancellationToken = default); /// Adds a new template folder. /// The folder to add. /// Cancellation token. + /// A task that represents the asynchronous operation. Task AddFolderAsync(TemplateFolder folder, CancellationToken cancellationToken = default); /// Updates an existing template folder. /// The folder to update. /// Cancellation token. + /// A task that represents the asynchronous operation. Task UpdateFolderAsync(TemplateFolder folder, CancellationToken cancellationToken = default); /// Deletes a template folder by ID. /// The folder ID. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DeleteFolderAsync(int id, CancellationToken cancellationToken = default); /// Saves pending changes to the database. /// Cancellation token. + /// A task that resolves to the number of rows written to the database. Task SaveChangesAsync(CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Security/IInboundApiKeyAdmin.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Security/IInboundApiKeyAdmin.cs index ac1db4c1..1b6d70db 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Security/IInboundApiKeyAdmin.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Security/IInboundApiKeyAdmin.cs @@ -45,31 +45,54 @@ public interface IInboundApiKeyAdmin { /// Creates a new key scoped to and returns its /// identifier plus the bearer token (shown once). + /// Operator-facing display name for the new key. + /// API method names the key is permitted to call. + /// Token to observe for cancellation. + /// A task that resolves to the new key identifier and the one-time bearer token. Task CreateAsync( string name, IReadOnlyCollection methods, CancellationToken ct = default); /// Lists all inbound keys (hash-free projection). + /// Token to observe for cancellation. + /// A task that resolves to the full list of inbound API key records. Task> ListAsync(CancellationToken ct = default); /// Enables or disables a key without changing its secret. Returns false if /// the key does not exist. + /// Identifier of the key to update. + /// True to enable the key; false to disable it. + /// Token to observe for cancellation. + /// A task that resolves to true if the key was updated; false if the key does not exist. Task SetEnabledAsync(string keyId, bool enabled, CancellationToken ct = default); /// Replaces the method-scope set on a key without changing its secret. /// Returns false if the key does not exist. + /// Identifier of the key to update. + /// Replacement set of API method names the key may call. + /// Token to observe for cancellation. + /// A task that resolves to true if the key's method scope was replaced; false if the key does not exist. Task SetMethodsAsync( string keyId, IReadOnlyCollection methods, CancellationToken ct = default); /// Removes a key (revoke-then-delete). Returns false if the key could not be /// deleted. + /// Identifier of the key to delete. + /// Token to observe for cancellation. + /// A task that resolves to true if the key was deleted; false if it could not be deleted. Task DeleteAsync(string keyId, CancellationToken ct = default); /// Returns the method-scope set for a key, or an empty list if not found. /// Enumerates the full key list (O(n)); intended for admin-scale use, not hot paths. + /// Identifier of the key whose method scope to retrieve. + /// Token to observe for cancellation. + /// A task that resolves to the method names the key is scoped to, or an empty list if the key does not exist. Task> GetMethodsForKeyAsync(string keyId, CancellationToken ct = default); /// Returns the identifiers of all keys whose scopes contain /// . /// Enumerates the full key list (O(n)); intended for admin-scale use, not hot paths. + /// API method name to search for across all key scopes. + /// Token to observe for cancellation. + /// A task that resolves to the identifiers of all keys whose scopes include . Task> GetKeysForMethodAsync(string methodName, CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditService.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditService.cs index 8c986a23..f76b56ad 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditService.cs @@ -12,5 +12,6 @@ public interface IAuditService /// The display name of the affected entity. /// The entity state after the action; may be null for deletes. /// Cancellation token for the log write. + /// A task that represents the asynchronous operation. Task LogAsync(string user, string action, string entityType, string entityId, string entityName, object? afterState, CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditWriter.cs index c49f07ca..82601e38 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IAuditWriter.cs @@ -21,5 +21,6 @@ public interface IAuditWriter /// /// The audit event to persist. /// Cancellation token. + /// A task representing the asynchronous write operation. Task WriteAsync(AuditEvent evt, CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallLifecycleObserver.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallLifecycleObserver.cs index 5218fb98..e04e6b1e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallLifecycleObserver.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallLifecycleObserver.cs @@ -36,6 +36,7 @@ public interface ICachedCallLifecycleObserver /// /// Per-attempt context including the tracking id, outcome, and audit provenance fields. /// Cancellation token for the observation operation. + /// A task that represents the asynchronous operation. Task OnAttemptCompletedAsync(CachedCallAttemptContext context, CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallTelemetryForwarder.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallTelemetryForwarder.cs index f0cb9f96..ff82ae5e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallTelemetryForwarder.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICachedCallTelemetryForwarder.cs @@ -32,5 +32,6 @@ public interface ICachedCallTelemetryForwarder /// /// The combined-telemetry packet to fan out. /// Cancellation token. + /// A task that represents the asynchronous operation. Task ForwardAsync(CachedCallTelemetry telemetry, CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICentralAuditWriter.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICentralAuditWriter.cs index c30d41e5..cffc616a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICentralAuditWriter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ICentralAuditWriter.cs @@ -14,5 +14,6 @@ public interface ICentralAuditWriter /// /// The audit event to persist. /// Cancellation token. + /// A task that represents the asynchronous operation. Task WriteAsync(AuditEvent evt, CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IDatabaseGateway.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IDatabaseGateway.cs index 25b382fb..a39a361c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IDatabaseGateway.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IDatabaseGateway.cs @@ -16,6 +16,7 @@ public interface IDatabaseGateway /// /// Name of the configured database connection to open. /// Cancellation token for the async open operation. + /// A task that resolves to an open ; the caller is responsible for disposing it. Task GetConnectionAsync( string connectionName, CancellationToken cancellationToken = default); @@ -55,6 +56,7 @@ public interface IDatabaseGateway /// Optional SQL parameters for the statement. /// Optional name of the instance that originated the write. /// Cancellation token for the buffering operation. + /// A task that represents the asynchronous operation. Task CachedWriteAsync( string connectionName, string sql, diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IInstanceLocator.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IInstanceLocator.cs index 287223a2..f23f9b34 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IInstanceLocator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IInstanceLocator.cs @@ -12,6 +12,7 @@ public interface IInstanceLocator /// /// System-wide unique name of the instance to look up. /// Cancellation token. + /// A task that resolves to the site identifier for the instance, or null if the instance is not found. Task GetSiteIdForInstanceAsync( string instanceUniqueName, CancellationToken cancellationToken = default); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IOperationTrackingStore.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IOperationTrackingStore.cs index fc59fc84..b85bff5c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IOperationTrackingStore.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IOperationTrackingStore.cs @@ -47,6 +47,7 @@ public interface IOperationTrackingStore /// Optional name of the source script. /// Optional source node identifier. /// Cancellation token. + /// A task that represents the asynchronous operation. Task RecordEnqueueAsync( TrackedOperationId id, string kind, @@ -68,6 +69,7 @@ public interface IOperationTrackingStore /// Optional error message from the last attempt. /// Optional HTTP status code from the last attempt. /// Cancellation token. + /// A task that represents the asynchronous operation. Task RecordAttemptAsync( TrackedOperationId id, string status, @@ -86,6 +88,7 @@ public interface IOperationTrackingStore /// Optional final error message. /// Optional final HTTP status code. /// Cancellation token. + /// A task that represents the asynchronous operation. Task RecordTerminalAsync( TrackedOperationId id, string status, @@ -111,6 +114,7 @@ public interface IOperationTrackingStore /// /// Cutoff timestamp; rows terminal before this are deleted. /// Cancellation token. + /// A task that represents the asynchronous operation. Task PurgeTerminalAsync( DateTime olderThanUtc, CancellationToken ct = default); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IPartitionMaintenance.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IPartitionMaintenance.cs index ddb28de9..f5de52b6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IPartitionMaintenance.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/IPartitionMaintenance.cs @@ -44,6 +44,7 @@ public interface IPartitionMaintenance /// /// Number of future monthly boundaries to ensure exist. /// Cancellation token for the SQL operation. + /// A task that resolves to the list of boundary values actually added, in chronological order. Task> EnsureLookaheadAsync(int lookaheadMonths, CancellationToken ct = default); /// @@ -53,5 +54,6 @@ public interface IPartitionMaintenance /// has no boundaries. /// /// Cancellation token for the SQL operation. + /// A task that resolves to the highest boundary value, or null when the partition function has no boundaries. Task GetMaxBoundaryAsync(CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ISiteAuditQueue.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ISiteAuditQueue.cs index b8df0cc0..dcd3dc35 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ISiteAuditQueue.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/ISiteAuditQueue.cs @@ -47,6 +47,7 @@ public interface ISiteAuditQueue /// /// Maximum number of rows to return. /// Cancellation token. + /// A task that resolves to the oldest pending non-cached audit events, up to . Task> ReadPendingAsync(int limit, CancellationToken ct = default); /// @@ -77,6 +78,7 @@ public interface ISiteAuditQueue /// /// Maximum number of rows to return. /// Cancellation token. + /// A task that resolves to the oldest pending cached-lifecycle audit events, up to . Task> ReadPendingCachedTelemetryAsync(int limit, CancellationToken ct = default); /// @@ -87,6 +89,7 @@ public interface ISiteAuditQueue /// /// Event IDs to mark as forwarded. /// Cancellation token. + /// A task that represents the asynchronous operation. Task MarkForwardedAsync(IReadOnlyList eventIds, CancellationToken ct = default); /// @@ -107,6 +110,7 @@ public interface ISiteAuditQueue /// Lower bound timestamp (UTC). /// Maximum number of rows to return. /// Cancellation token. + /// A task that resolves to audit events at or after in pending or forwarded state, up to . Task> ReadPendingSinceAsync( DateTime sinceUtc, int batchSize, CancellationToken ct = default); @@ -121,6 +125,7 @@ public interface ISiteAuditQueue /// /// Event IDs to mark as reconciled. /// Cancellation token. + /// A task that represents the asynchronous operation. Task MarkReconciledAsync(IReadOnlyList eventIds, CancellationToken ct = default); /// @@ -135,5 +140,6 @@ public interface ISiteAuditQueue /// the hot-path INSERT batch and the drain queries. /// /// Cancellation token. + /// A task that resolves to a point-in-time snapshot of the site audit queue's pending count, oldest timestamp, and on-disk file size. Task GetBacklogStatsAsync(CancellationToken ct = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleExporter.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleExporter.cs index 52cecab5..3e5a884c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleExporter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleExporter.cs @@ -12,6 +12,7 @@ public interface IBundleExporter /// Environment label stamped in the bundle manifest. /// Optional passphrase to encrypt the bundle; null produces an unencrypted bundle. /// Cancellation token. + /// A task that resolves to a seeked-to-start stream containing the bundle ZIP archive. Task ExportAsync( ExportSelection selection, string user, diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleImporter.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleImporter.cs index 52af6196..78df5513 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleImporter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleImporter.cs @@ -10,6 +10,7 @@ public interface IBundleImporter /// Stream containing the bundle zip archive. /// Optional passphrase for decrypting an encrypted bundle. /// Cancellation token. + /// A task that resolves to session metadata for the loaded bundle. Task LoadAsync(Stream bundleStream, string? passphrase, CancellationToken ct = default); /// @@ -17,6 +18,7 @@ public interface IBundleImporter /// /// Session id returned by . /// Cancellation token. + /// A task that resolves to a per-artifact import preview with conflict details. Task PreviewAsync(Guid sessionId, CancellationToken ct = default); /// @@ -26,6 +28,7 @@ public interface IBundleImporter /// Per-artifact conflict resolutions from the preview step. /// Username of the operator performing the import, stamped in audit rows. /// Cancellation token. + /// A task that resolves to the result of the committed import transaction. Task ApplyAsync( Guid sessionId, IReadOnlyList resolutions, diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleSessionStore.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleSessionStore.cs index d3a778dd..cdc493ec 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleSessionStore.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Transport/IBundleSessionStore.cs @@ -6,9 +6,11 @@ public interface IBundleSessionStore { /// Stores the session and returns it; overwrites any existing session with the same id. /// The session to store. + /// The stored session (same reference as ). BundleSession Open(BundleSession session); /// Returns the session for the given id, or null if not found or expired. /// The session identifier to look up. + /// The matching , or null if not found or expired. BundleSession? Get(Guid sessionId); /// Removes the session for the given id, if present. /// The session identifier to remove. @@ -31,6 +33,7 @@ public interface IBundleSessionStore /// against identical bundle bytes are throttled regardless of client. /// /// SHA-256 hex from BundleManifest.ContentHash. + /// The new unlock-failure count after incrementing. int IncrementUnlockFailureCount(string bundleContentHash); /// diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ManagementCommandRegistry.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ManagementCommandRegistry.cs index 9411ec2d..0f3a0ec6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ManagementCommandRegistry.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/ManagementCommandRegistry.cs @@ -29,6 +29,7 @@ public static class ManagementCommandRegistry /// Resolves a management command wire name to its CLR type, or null if not registered. /// /// The wire name of the management command (without the "Command" suffix). + /// The CLR for the command, or null if not registered. public static Type? Resolve(string commandName) { return Commands.GetValueOrDefault(commandName); @@ -45,6 +46,7 @@ public static class ManagementCommandRegistry /// symmetric with : it never yields a name that /// cannot turn back into the same type. /// + /// The registered wire name for . public static string GetCommandName(Type commandType) { ArgumentNullException.ThrowIfNull(commandType); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/MxGatewayEndpointConfigSerializer.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/MxGatewayEndpointConfigSerializer.cs index 40282828..baaa29ee 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/MxGatewayEndpointConfigSerializer.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/MxGatewayEndpointConfigSerializer.cs @@ -21,11 +21,13 @@ public static class MxGatewayEndpointConfigSerializer /// Serializes a config to the typed JSON shape. /// The endpoint configuration to serialize. + /// A camelCase JSON string representing the endpoint configuration. public static string Serialize(MxGatewayEndpointConfig config) => JsonSerializer.Serialize(config, JsonOpts); /// Parses stored config JSON; null/blank/malformed yields a default config. /// The stored JSON string. + /// The deserialized , or a default instance if the input is null, blank, or malformed. public static MxGatewayEndpointConfig Deserialize(string? json) { if (string.IsNullOrWhiteSpace(json)) return new MxGatewayEndpointConfig(); @@ -35,6 +37,7 @@ public static class MxGatewayEndpointConfigSerializer /// Flattens the typed config to the key-value shape the adapter consumes. /// The endpoint configuration to flatten. + /// A string-keyed dictionary containing all endpoint configuration properties. public static IDictionary ToFlatDict(MxGatewayEndpointConfig c) => new Dictionary { ["Endpoint"] = c.Endpoint, @@ -49,6 +52,7 @@ public static class MxGatewayEndpointConfigSerializer /// Reconstructs a config from the flat key-value shape; invalid numerics fall back to defaults. /// The flat dictionary. + /// A populated from the dictionary; missing or invalid entries use default values. public static MxGatewayEndpointConfig FromFlatDict(IDictionary d) { var c = new MxGatewayEndpointConfig(); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/OpcUaEndpointConfigSerializer.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/OpcUaEndpointConfigSerializer.cs index 2af26d36..55d1d107 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/OpcUaEndpointConfigSerializer.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Serialization/OpcUaEndpointConfigSerializer.cs @@ -118,6 +118,7 @@ public static class OpcUaEndpointConfigSerializer /// /// /// The stored JSON string to parse; null or blank yields a default typed result. + /// An containing the parsed config and the detected parse status. public static OpcUaConfigParseResult Deserialize(string? json) { if (string.IsNullOrWhiteSpace(json)) @@ -175,6 +176,7 @@ public static class OpcUaEndpointConfigSerializer /// used by OpcUaDataConnection so the adapter can keep that interface. /// /// The endpoint configuration to flatten. + /// A dictionary mapping connection-parameter key names to their string values. public static IDictionary ToFlatDict(OpcUaEndpointConfig config) { var dict = new Dictionary diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Alarms/AlarmConditionStateFactory.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Alarms/AlarmConditionStateFactory.cs index 1e0f36cb..427e6fcc 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Alarms/AlarmConditionStateFactory.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Alarms/AlarmConditionStateFactory.cs @@ -10,6 +10,9 @@ public static class AlarmConditionStateFactory /// auto-acked, never shelved or suppressed, not confirmable, and their /// severity is the configured priority. Active mirrors the alarm State. /// + /// The current alarm state used to derive the Active flag. + /// Configured priority mapped to the Severity field (0–1000). + /// An reflecting the computed alarm's lifecycle (auto-acked, unshelved, not suppressed). public static AlarmConditionState ForComputed(AlarmState state, int priority) => new(Active: state == AlarmState.Active, Acknowledged: true, Confirmed: null, Shelve: AlarmShelveState.Unshelved, Suppressed: false, Severity: priority); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditDetailsCodec.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditDetailsCodec.cs index a55a5458..0419c872 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditDetailsCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditDetailsCodec.cs @@ -46,6 +46,8 @@ public static class AuditDetailsCodec /// Serializes to a compact, deterministic JSON string /// suitable for storage in AuditEvent.DetailsJson. /// + /// The audit details instance to serialize. + /// A compact, deterministic JSON string representing the audit details. public static string Serialize(AuditDetails details) => JsonSerializer.Serialize(details, Options); @@ -54,6 +56,8 @@ public static class AuditDetailsCodec /// Returns an empty (all-null) when /// is null, empty, or whitespace — never throws. /// + /// The JSON string to deserialize; null or whitespace returns an empty instance. + /// The deserialized , or an empty instance on null/invalid input. public static AuditDetails Deserialize(string? json) { if (string.IsNullOrWhiteSpace(json)) diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditFieldBuilders.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditFieldBuilders.cs index b6c6bc57..a4a59547 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditFieldBuilders.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditFieldBuilders.cs @@ -22,12 +22,17 @@ public static class AuditFieldBuilders /// /// Returns the canonical Action string: "{channel}.{kind}". /// + /// The audit channel (e.g. ExternalSystem, Notification). + /// The audit kind (e.g. Sync, Cached, InboundAuthFailure). + /// A dot-separated string in the form "{channel}.{kind}". public static string BuildAction(AuditChannel channel, AuditKind kind) => $"{channel}.{kind}"; /// /// Returns the canonical Category string: the channel name. /// + /// The audit channel whose name becomes the category. + /// The channel enum name as a string (e.g. "ApiOutbound"). public static string BuildCategory(AuditChannel channel) => channel.ToString(); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditOutcomeProjector.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditOutcomeProjector.cs index 4bbf193e..c6458430 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditOutcomeProjector.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditOutcomeProjector.cs @@ -26,6 +26,9 @@ public static class AuditOutcomeProjector /// Projects + onto the canonical /// . /// + /// The audit status of the operation. + /// The audit kind; takes precedence over status. + /// The projected value. public static AuditOutcome Project(AuditStatus status, AuditKind kind) { // Auth-failure kind takes absolute precedence — checked before any status rule. diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditRowProjection.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditRowProjection.cs index ad2263b4..7a90d3d6 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditRowProjection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/AuditRowProjection.cs @@ -64,6 +64,8 @@ public static class AuditRowProjection /// ); a missing/unparseable discriminator /// falls back to the first enum member (defensive — production rows always carry them). /// + /// The canonical audit event to decompose. + /// An struct containing the typed column values extracted from the event. public static AuditRowValues Decompose(AuditEvent evt) { ArgumentNullException.ThrowIfNull(evt); @@ -115,6 +117,8 @@ public static class AuditRowProjection /// are rebuilt via the field builders / outcome projector, and every domain field is /// re-serialized into DetailsJson via . /// + /// The typed column values to recompose into a canonical event. + /// A reconstructed canonical with domain fields re-serialized into DetailsJson. public static AuditEvent Recompose(in AuditRowValues v) { var details = new AuditDetails @@ -163,6 +167,9 @@ public static class AuditRowProjection /// record, so the central ingest paths stamp it here rather than on a top-level /// property as the legacy bespoke record allowed. /// + /// The canonical audit event to update. + /// The central-side ingest timestamp to stamp into the event. + /// A new with IngestedAtUtc set inside DetailsJson. public static AuditEvent WithIngestedAtUtc(AuditEvent evt, DateTimeOffset ingestedAtUtc) { ArgumentNullException.ThrowIfNull(evt); @@ -179,6 +186,10 @@ public static class AuditRowProjection /// or does not match any declared member name — so callers never throw on an /// unknown/renamed enum string (legacy or corrupt rows degrade gracefully). /// + /// The enum type to parse into. + /// The string to parse; null or empty triggers the fallback. + /// Value returned when is null, empty, or unrecognised. + /// The parsed value, or when the input is null, empty, or unrecognised. public static TEnum ParseEnum(string? value, TEnum fallback) where TEnum : struct, Enum => !string.IsNullOrEmpty(value) && Enum.TryParse(value, ignoreCase: false, out var parsed) ? parsed @@ -194,6 +205,8 @@ public static class AuditRowProjection public static class AuditEventRowExtensions { /// Decomposes this canonical record into its typed 24-field view. + /// The canonical audit event to decompose. + /// An struct with all domain fields extracted from the event. public static AuditRowProjection.AuditRowValues AsRow(this AuditEvent evt) => AuditRowProjection.Decompose(evt); } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/ScadaBridgeAuditEventFactory.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/ScadaBridgeAuditEventFactory.cs index 75b34112..36e4ef69 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/ScadaBridgeAuditEventFactory.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Audit/ScadaBridgeAuditEventFactory.cs @@ -59,6 +59,7 @@ public static class ScadaBridgeAuditEventFactory /// True when summaries were truncated to the payload cap (DetailsJson). /// Free-form JSON extension for channel-specific extras (DetailsJson). /// UTC ingest timestamp (central-set; DetailsJson). + /// A fully-populated with the top-level fields and serialized DetailsJson set. public static AuditEvent Create( AuditChannel channel, AuditKind kind, diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Flattening/ValidationResult.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Flattening/ValidationResult.cs index 61a89979..4210b6b5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Flattening/ValidationResult.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Flattening/ValidationResult.cs @@ -13,15 +13,18 @@ public sealed record ValidationResult public IReadOnlyList Warnings { get; init; } = []; /// Returns a result with no errors or warnings. + /// A with empty error and warning lists. public static ValidationResult Success() => new(); /// Returns a result containing the given errors. /// The validation errors to include. + /// A whose list contains the supplied entries. public static ValidationResult FromErrors(params ValidationEntry[] errors) => new() { Errors = errors }; /// Merges multiple validation results into a single combined result. /// The results to merge. + /// A new with all errors and warnings from every supplied result combined. public static ValidationResult Merge(params ValidationResult[] results) { var errors = new List(); @@ -54,6 +57,7 @@ public sealed record ValidationEntry /// The validation category. /// The error message. /// The canonical name of the entity that caused the error, if any. + /// A new representing an error. public static ValidationEntry Error(ValidationCategory category, string message, string? entityName = null) => new() { Category = category, Message = message, EntityName = entityName }; @@ -61,6 +65,7 @@ public sealed record ValidationEntry /// The validation category. /// The warning message. /// The canonical name of the entity that triggered the warning, if any. + /// A new representing a warning. public static ValidationEntry Warning(ValidationCategory category, string message, string? entityName = null) => new() { Category = category, Message = message, EntityName = entityName }; } diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Result.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Result.cs index d08d32c2..ab302f05 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Result.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/Result.cs @@ -49,6 +49,7 @@ public sealed class Result /// Non-blank error message describing the failure. /// is null. /// is empty or whitespace. + /// A failed carrying the error message. public static Result Failure(string error) => new(error); /// Pattern-matches the result, invoking either the success or failure delegate. diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/TrackedOperationId.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/TrackedOperationId.cs index 67ab4564..4bbfc53d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/TrackedOperationId.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/TrackedOperationId.cs @@ -22,6 +22,7 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Types; public readonly record struct TrackedOperationId(Guid Value) { /// Mint a fresh id at the call site (script-thread safe). + /// A new wrapping a freshly generated GUID. public static TrackedOperationId New() => new(Guid.NewGuid()); /// @@ -30,6 +31,7 @@ public readonly record struct TrackedOperationId(Guid Value) /// instead. /// /// GUID string to parse. + /// A wrapping the parsed GUID. public static TrackedOperationId Parse(string s) => new(Guid.Parse(s)); /// @@ -39,6 +41,7 @@ public readonly record struct TrackedOperationId(Guid Value) /// /// GUID string to parse, or null. /// Parsed value on success; default on failure. + /// true if the string was successfully parsed; otherwise false. public static bool TryParse(string? s, out TrackedOperationId result) { if (Guid.TryParse(s, out var g)) diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/ValueFormatter.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/ValueFormatter.cs index cd0201ec..c3bf8ab3 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Types/ValueFormatter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Types/ValueFormatter.cs @@ -14,6 +14,7 @@ public static class ValueFormatter /// scalars and comma-separated elements for array/collection types. /// /// The value to format; null returns an empty string. + /// The culture-invariant string representation of the value, or an empty string if is null. /// /// Formatting is culture-invariant: /// numbers and values render the same regardless of the diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/MxGatewayEndpointConfigValidator.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/MxGatewayEndpointConfigValidator.cs index 8443e77d..c71e90ac 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/MxGatewayEndpointConfigValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/MxGatewayEndpointConfigValidator.cs @@ -16,6 +16,7 @@ public static class MxGatewayEndpointConfigValidator /// /// The MxGateway endpoint configuration to validate. /// Optional prefix prepended to each field name in error entries (e.g., "Primary."). + /// A with errors for any invalid fields, or a success result when all fields are valid. public static ValidationResult Validate(MxGatewayEndpointConfig config, string fieldPrefix = "") { var errors = new List(); diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/OpcUaEndpointConfigValidator.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/OpcUaEndpointConfigValidator.cs index 2adcd010..97692fb2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/OpcUaEndpointConfigValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Validators/OpcUaEndpointConfigValidator.cs @@ -16,6 +16,7 @@ public static class OpcUaEndpointConfigValidator /// /// The OPC UA endpoint configuration to validate. /// Optional prefix prepended to each field name in error entries (e.g., "Primary."). + /// A containing field-level errors, or success if all fields are valid. public static ValidationResult Validate(OpcUaEndpointConfig config, string fieldPrefix = "") { var errors = new List(); diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs index 816ff8d3..30bd7457 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs @@ -85,6 +85,7 @@ public class CommunicationService /// /// Gets the central communication actor reference. Throws if not yet initialized. /// + /// The for the central communication actor. public IActorRef GetCommunicationActor() { return _centralCommunicationActor diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AlarmShelveStateCodec.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AlarmShelveStateCodec.cs index a1512e90..18d70e7e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AlarmShelveStateCodec.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AlarmShelveStateCodec.cs @@ -11,9 +11,13 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc; public static class AlarmShelveStateCodec { /// Returns the wire string for a shelve state (the enum member name). + /// The shelve state to encode as a wire string. + /// The enum member name as a string (e.g., "Unshelved", "OneShotShelved"). public static string ToWire(AlarmShelveState state) => state.ToString(); /// Parses a wire string back to a shelve state; defaults to . + /// The wire string to parse; empty or unrecognized values return . + /// The matching , or for unrecognized input. public static AlarmShelveState Parse(string? wire) => Enum.TryParse(wire, ignoreCase: true, out var state) ? state diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AuditEventDtoMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AuditEventDtoMapper.cs index 2d586366..4273fc44 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AuditEventDtoMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/AuditEventDtoMapper.cs @@ -38,6 +38,7 @@ public static class AuditEventDtoMapper /// fields collapse to empty strings; null integer fields leave the wrapper unset. /// /// The audit event to project to wire format. + /// A populated ready for transmission; null strings collapse to empty. public static AuditEventDto ToDto(AuditEvent evt) { ArgumentNullException.ThrowIfNull(evt); @@ -92,6 +93,7 @@ public static class AuditEventDtoMapper /// are intentionally left null — the central ingest actor sets the latter. /// /// The wire-format DTO to reconstruct into an . + /// A canonical with domain fields recomposed into DetailsJson; ForwardState and IngestedAtUtc are left null. public static AuditEvent FromDto(AuditEventDto dto) { ArgumentNullException.ThrowIfNull(dto); diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCallDtoMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCallDtoMapper.cs index eb184b02..ec7a0dbd 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCallDtoMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCallDtoMapper.cs @@ -46,6 +46,7 @@ public static class SiteCallDtoMapper /// share one instant. The value sent on the wire is informational only. /// /// The wire-format site call DTO to map. + /// A entity populated from the DTO fields. public static SiteCall FromDto(SiteCallOperationalDto dto) { ArgumentNullException.ThrowIfNull(dto); diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs index da1665e4..c6eae35f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs @@ -100,6 +100,7 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable /// Creates a test-only instance that has no gRPC channel. Used to test /// Unsubscribe and Dispose behavior without needing a real endpoint. /// + /// A with no channel or client, for testing only. internal static SiteStreamGrpcClient CreateForTesting() => new(); /// @@ -153,6 +154,7 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable /// Callback invoked for each domain event received from the stream. /// Callback invoked when the subscription encounters an error. /// Cancellation token to stop the subscription. + /// A task that represents the asynchronous operation. public virtual async Task SubscribeAsync( string correlationId, string instanceUniqueName, @@ -257,6 +259,8 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable }; /// Parses the wire "kind" string back to ; defaults to Computed. + /// The wire "kind" string from the gRPC payload; null or unrecognised defaults to . + /// The parsed , or when the value is null or unrecognised. internal static AlarmKind ParseAlarmKind(string? kind) => System.Enum.TryParse(kind, ignoreCase: true, out var k) ? k : AlarmKind.Computed; @@ -320,6 +324,7 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable /// /// Asynchronously disposes of the gRPC client and all subscriptions. /// + /// A completed after all subscriptions and the gRPC channel have been released. public virtual ValueTask DisposeAsync() { ReleaseResources(); diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClientFactory.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClientFactory.cs index e2fc0616..5cab1f1b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClientFactory.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClientFactory.cs @@ -48,6 +48,7 @@ public class SiteStreamGrpcClientFactory : IAsyncDisposable, IDisposable /// /// Unique site identifier used as the cache key. /// gRPC endpoint the returned client must be bound to. + /// The cached or newly-created client bound to . public virtual SiteStreamGrpcClient GetOrCreate(string siteIdentifier, string grpcEndpoint) { // Fast path: a client is cached and already bound to the requested endpoint. @@ -82,6 +83,7 @@ public class SiteStreamGrpcClientFactory : IAsyncDisposable, IDisposable /// caching and disposal machinery. /// /// gRPC endpoint the new client will connect to. + /// A new connected to . protected virtual SiteStreamGrpcClient CreateClient(string grpcEndpoint) { var logger = _loggerFactory.CreateLogger(); @@ -96,6 +98,7 @@ public class SiteStreamGrpcClientFactory : IAsyncDisposable, IDisposable /// cached gRPC client does not linger for the life of the process. /// /// Unique site identifier whose client should be removed. + /// A task that completes when the cached client has been removed and disposed. public async Task RemoveSiteAsync(string siteIdentifier) { if (_clients.TryRemove(siteIdentifier, out var client)) @@ -107,6 +110,7 @@ public class SiteStreamGrpcClientFactory : IAsyncDisposable, IDisposable /// /// Asynchronously disposes all cached clients and clears the cache. /// + /// A value task that completes when all clients have been disposed. public async ValueTask DisposeAsync() { foreach (var client in _clients.Values) diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs index a951ad0d..7cb82444 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs @@ -301,30 +301,7 @@ public class SiteStreamGrpcServer : SiteStreamService.SiteStreamServiceBase } } - /// - /// Audit Log (#23) M2 site→central push RPC. Decodes a site batch into - /// rows, Asks the central AuditLogIngestActor - /// proxy to persist them, and echoes the accepted EventIds back so the site - /// can flip its local rows to Forwarded. - /// - /// - /// - /// The DTO→entity conversion uses the shared - /// (hosted in ZB.MOM.WW.ScadaBridge.Communication so both this server and - /// ZB.MOM.WW.ScadaBridge.AuditLog share one implementation without a - /// project-reference cycle). - /// - /// - /// When is not yet wired (host startup - /// race window), the RPC returns an empty rather - /// than failing — the site treats the missing ack as a transient outcome - /// and retries on the next drain, which is the desired idempotent - /// behaviour. - /// - /// /// - /// The audit event batch to ingest. - /// The server call context. public override async Task IngestAuditEvents( AuditEventBatch request, ServerCallContext context) @@ -380,22 +357,7 @@ public class SiteStreamGrpcServer : SiteStreamService.SiteStreamServiceBase return ack; } - /// - /// Audit Log (#23) M3 site→central combined-telemetry push RPC. Decodes a - /// batch of entries into matched - /// (AuditEvent, SiteCall) pairs, Asks the central AuditLogIngestActor - /// proxy to persist them in dual-write transactions, and echoes the - /// AuditEvent EventIds that committed back so the site can flip its local - /// rows to Forwarded. - /// - /// - /// Same wiring-incomplete fallback as : when - /// the actor proxy has not been set the RPC replies with an empty ack so - /// sites treat the outcome as transient and retry, never a hard fault. - /// /// - /// The cached telemetry batch to ingest. - /// The server call context. public override async Task IngestCachedTelemetry( CachedTelemetryBatch request, ServerCallContext context) @@ -445,27 +407,7 @@ public class SiteStreamGrpcServer : SiteStreamService.SiteStreamServiceBase return ack; } - /// - /// Audit Log (#23) M6 reconciliation pull RPC. Central asks the site for any - /// AuditLog rows whose OccurredAtUtc >= since_utc and whose - /// ForwardState is still Pending or Forwarded (i.e. not - /// yet confirmed reconciled), bounded by batch_size. The site responds - /// with the rows AND flips them to - /// - /// AFTER serializing the response. The flip is best-effort — if it fails - /// (e.g. SQLite disposed mid-call), rows stay Pending/Forwarded and central - /// pulls them again on the next reconciliation cycle. Idempotent. - /// - /// - /// When is not wired (central-only host or a - /// composition-root test exercising the server in isolation) the RPC returns - /// an empty response — central treats that as "nothing to ship" and retries - /// on its next cycle, which is the same self-healing semantics as the - /// SetAuditIngestActor wiring race window. - /// /// - /// The pull request with time bounds and batch size. - /// The server call context. public override async Task PullAuditEvents( PullAuditEventsRequest request, ServerCallContext context) diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs index 73cad7e3..ed2d3d3f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs @@ -7,6 +7,7 @@ public static class ServiceCollectionExtensions { /// Registers communication services including options, , gRPC client factory, and debug stream. /// The DI service collection to register services into. + /// The same to allow chaining. public static IServiceCollection AddCommunication(this IServiceCollection services) { services.AddOptions() @@ -21,6 +22,7 @@ public static class ServiceCollectionExtensions /// Hook for registering additional DI services needed by communication actors; actor creation itself happens inside AkkaHostedService. /// The DI service collection to register services into. + /// The same to allow chaining. public static IServiceCollection AddCommunicationActors(this IServiceCollection services) { // Actor registration happens in AkkaHostedService.RegisterCentralActors/RegisterSiteActors. diff --git a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/DesignTimeDbContextFactory.cs b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/DesignTimeDbContextFactory.cs index 8c4eb1a1..28b582a2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/DesignTimeDbContextFactory.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/DesignTimeDbContextFactory.cs @@ -26,6 +26,7 @@ public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory for design-time EF Core tooling. /// /// Arguments passed by the EF tooling (unused). + /// A configured pointing at the resolved connection string. public ScadaBridgeDbContext CreateDbContext(string[] args) { var configurationBuilder = new ConfigurationBuilder(); diff --git a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/MigrationHelper.cs b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/MigrationHelper.cs index 3f981d26..c5b9ba73 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/MigrationHelper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/MigrationHelper.cs @@ -18,6 +18,7 @@ public static class MigrationHelper /// When true, auto-applies migrations. When false, validates schema version matches. /// Optional logger for readiness-wait diagnostics. /// Cancellation token. + /// A task that represents the asynchronous operation. public static async Task ApplyOrValidateMigrationsAsync( ScadaBridgeDbContext dbContext, bool isDevelopment, diff --git a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ServiceCollectionExtensions.cs index b05da487..8cf5d35b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ServiceCollectionExtensions.cs @@ -18,6 +18,7 @@ public static class ServiceCollectionExtensions /// /// The service collection to register into. /// SQL Server connection string for the central configuration database. + /// The same collection, for chaining. public static IServiceCollection AddConfigurationDatabase(this IServiceCollection services, string connectionString) { // The DbContext is constructed via the (options, IDataProtectionProvider) overload so @@ -85,6 +86,7 @@ public static class ServiceCollectionExtensions /// /// Always thrown. The connection string is required; there is no valid no-op registration. /// + /// Never returns; always throws . [Obsolete( "AddConfigurationDatabase() with no connection string registers nothing and is not a " + "valid configuration. Call AddConfigurationDatabase(connectionString) instead.", diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs index da59744c..02140a6b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs @@ -31,35 +31,42 @@ public interface IMxGatewayClient : IAsyncDisposable /// Opens the gateway session and registers the client (Register → serverHandle held internally). /// Resolved connection parameters. /// Cancellation token. + /// A task that represents the asynchronous operation. Task ConnectAsync(MxGatewayConnectionOptions options, CancellationToken ct = default); /// Closes the session. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DisconnectAsync(CancellationToken ct = default); /// AddItem + Advise; returns the gateway item handle (as a string subscription id). /// Tag address to subscribe to. /// Cancellation token. + /// A task that resolves to the gateway item handle (subscription id). Task SubscribeAsync(string tagPath, CancellationToken ct = default); /// UnAdvise + RemoveItem for a previously returned subscription id. /// Subscription id returned by . /// Cancellation token. + /// A task that represents the asynchronous operation. Task UnsubscribeAsync(string subscriptionId, CancellationToken ct = default); /// Snapshot read of one or more tags (ReadBulk). /// Tag addresses to read. /// Cancellation token. + /// A task that resolves to one outcome per requested tag path. Task> ReadAsync(IReadOnlyList tagPaths, CancellationToken ct = default); /// Write one or more tag/value pairs (WriteBulk with the configured WriteUserId). /// Tag/value pairs to write. /// Cancellation token. + /// A task that resolves to one outcome per requested write. Task> WriteAsync(IReadOnlyList<(string TagPath, object? Value)> writes, CancellationToken ct = default); /// One Galaxy browse level (BrowseChildren). null → root. /// Parent node id (Galaxy contained path), or null for root. /// Cancellation token. + /// A task that resolves to the child nodes and a flag indicating whether the result was truncated. Task<(IReadOnlyList Children, bool Truncated)> BrowseChildrenAsync(string? parentNodeId, CancellationToken ct = default); /// @@ -69,6 +76,7 @@ public interface IMxGatewayClient : IAsyncDisposable /// /// Callback invoked per advised-tag value change. /// Cancellation token; ends the loop when cancelled. + /// A task that represents the asynchronous operation. Task RunEventLoopAsync(Action onUpdate, CancellationToken ct = default); /// @@ -80,6 +88,7 @@ public interface IMxGatewayClient : IAsyncDisposable /// Optional source-reference prefix to scope the feed; null = gateway-wide. /// Callback invoked per native alarm transition. /// Cancellation token; ends the loop when cancelled. + /// A task that represents the asynchronous operation. Task RunAlarmStreamAsync(string? alarmFilterPrefix, Action onTransition, CancellationToken ct = default); } @@ -87,5 +96,6 @@ public interface IMxGatewayClient : IAsyncDisposable public interface IMxGatewayClientFactory { /// Creates a new, unconnected client instance. + /// A new ready to be connected. IMxGatewayClient Create(); } diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IOpcUaClient.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IOpcUaClient.cs index 8f2ac598..e4cc7665 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IOpcUaClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IOpcUaClient.cs @@ -89,6 +89,11 @@ public interface IOpcUaClient : IAsyncDisposable /// active conditions as Snapshot…SnapshotComplete transitions. Returns a /// handle for . /// + /// OPC UA node ID to monitor; null subscribes to the Server object. + /// Optional OPC UA condition type filter; null subscribes to all conditions. + /// Callback invoked for each alarm transition received from the server. + /// Token to observe for cancellation. + /// A task that resolves to a subscription handle string for use with . Task CreateAlarmSubscriptionAsync( string? sourceNodeId, string? conditionFilter, @@ -96,6 +101,9 @@ public interface IOpcUaClient : IAsyncDisposable CancellationToken cancellationToken = default); /// Removes an alarm-event subscription by handle. + /// The handle returned by . + /// Token to observe for cancellation. + /// A task representing the asynchronous operation. Task RemoveAlarmSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default); /// @@ -167,7 +175,7 @@ internal class StubOpcUaClient : IOpcUaClient /// public bool IsConnected { get; private set; } #pragma warning disable CS0067 - /// + /// Raised when the OPC UA session detects a keep-alive failure or the server becomes unreachable. public event Action? ConnectionLost; #pragma warning restore CS0067 @@ -230,7 +238,8 @@ internal class StubOpcUaClient : IOpcUaClient string? parentNodeId, CancellationToken cancellationToken = default) => throw new NotImplementedException(); - /// + /// Disposes this stub client and marks the connection as closed. + /// A completed . public ValueTask DisposeAsync() { IsConnected = false; diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs index 17e8ade8..ca06d0b9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs @@ -19,9 +19,14 @@ namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters; public static class MxGatewayAlarmMapper { /// Clamps the gateway severity onto the unified 0–1000 scale. + /// Raw gateway severity value to clamp. + /// The severity clamped to the range [0, 1000]. public static int NormalizeSeverity(int severity) => Math.Clamp(severity, 0, 1000); /// Maps a gateway condition-state + severity to the unified condition. + /// Gateway proto condition state to map. + /// Raw gateway severity value; normalized to 0–1000. + /// The protocol-neutral equivalent. public static AlarmConditionState MapConditionState(ProtoConditionState state, int severity) { var (active, acked) = state switch @@ -36,6 +41,8 @@ public static class MxGatewayAlarmMapper } /// Maps a gateway transition kind to the unified transition kind. + /// Gateway proto transition kind to map. + /// The protocol-neutral equivalent. public static AlarmTransitionKind MapKind(ProtoTransitionKind kind) => kind switch { ProtoTransitionKind.Raise => AlarmTransitionKind.Raise, @@ -61,6 +68,8 @@ public static class MxGatewayAlarmMapper } /// Maps a live to a transition. + /// The gateway alarm transition event proto message to map. + /// The protocol-neutral . public static NativeAlarmTransition MapTransition(OnAlarmTransitionEvent body) => new( SourceReference: body.AlarmFullReference, SourceObjectReference: body.SourceObjectReference, @@ -78,12 +87,15 @@ public static class MxGatewayAlarmMapper LimitValue: ""); /// The end-of-snapshot sentinel transition (no condition payload). + /// A with AlarmTransitionKind.SnapshotComplete. public static NativeAlarmTransition SnapshotComplete() => new( "", "", "", AlarmTransitionKind.SnapshotComplete, new AlarmConditionState(false, true, null, AlarmShelveState.Unshelved, false, 0), "", "", "", "", "", null, DateTimeOffset.UtcNow, "", ""); /// Maps one initial-snapshot entry to a Snapshot transition. + /// The active alarm snapshot proto message to map. + /// A with AlarmTransitionKind.Snapshot. public static NativeAlarmTransition MapSnapshot(ActiveAlarmSnapshot snapshot) => new( SourceReference: snapshot.AlarmFullReference, SourceObjectReference: snapshot.SourceObjectReference, diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayDataConnection.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayDataConnection.cs index 8a5f501c..a1e83886 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayDataConnection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayDataConnection.cs @@ -262,7 +262,8 @@ public class MxGatewayDataConnection : IDataConnection, IBrowsableDataConnection return new BrowseChildrenResult(nodes, truncated); } - /// + /// Cancels the event loop and disposes the underlying MxGateway client. + /// A that completes when disposal is finished. public async ValueTask DisposeAsync() { _eventLoopCts?.Cancel(); diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaAlarmMapper.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaAlarmMapper.cs index 12bfc238..8165ede0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaAlarmMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaAlarmMapper.cs @@ -13,9 +13,18 @@ namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters; public static class OpcUaAlarmMapper { /// Clamps an OPC UA severity (1–1000, sometimes out of range) to the unified 0–1000 scale. + /// The raw OPC UA severity value to clamp. + /// The severity clamped to the range [0, 1000]. public static int NormalizeSeverity(int severity) => Math.Clamp(severity, 0, 1000); /// Builds an from the orthogonal A&C sub-states. + /// Whether the alarm condition is currently active. + /// Whether the alarm has been acknowledged. + /// Whether the alarm has been confirmed; null if not supported by the server. + /// The current shelving state of the alarm. + /// Whether the alarm is suppressed. + /// The raw OPC UA severity (1–1000); clamped via . + /// The composed . public static AlarmConditionState BuildCondition( bool active, bool acked, bool? confirmed, AlarmShelveState shelve, bool suppressed, int severity) => new(Active: active, Acknowledged: acked, Confirmed: confirmed, @@ -26,6 +35,11 @@ public static class OpcUaAlarmMapper /// Acknowledgement takes precedence over an active/inactive edge when both /// change in the same event; an unchanged event is reported as a StateChange. /// + /// Acknowledged state before the event. + /// Acknowledged state after the event. + /// Active state before the event. + /// Active state after the event. + /// The that best describes the state change. public static AlarmTransitionKind DeriveKind(bool prevAcked, bool nowAcked, bool prevActive, bool nowActive) { if (!prevAcked && nowAcked) @@ -40,6 +54,8 @@ public static class OpcUaAlarmMapper } /// Maps the OPC UA ShelvingState current-state node name to the shelve enum. + /// The OPC UA ShelvingState node name, or null when unshelved. + /// The corresponding ; defaults to . public static AlarmShelveState MapShelve(string? shelvingStateName) => shelvingStateName switch { "OneShotShelved" => AlarmShelveState.OneShotShelved, diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaDataConnection.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaDataConnection.cs index 124e1c48..b8451e56 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaDataConnection.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/OpcUaDataConnection.cs @@ -339,6 +339,7 @@ public class OpcUaDataConnection : IDataConnection, IBrowsableDataConnection, IA /// /// Asynchronously disposes the OPC UA connection, releasing the client and stopping the heartbeat monitor. /// + /// A that completes when the client has been released and the heartbeat monitor stopped. public async ValueTask DisposeAsync() { StopHeartbeatMonitor(); diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/RealMxGatewayClient.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/RealMxGatewayClient.cs index e38caa0b..e2660eaa 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/RealMxGatewayClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/RealMxGatewayClient.cs @@ -301,7 +301,10 @@ public sealed class RealMxGatewayClient : IMxGatewayClient } } - /// + /// + /// Asynchronously disposes the active MxAccess session, client, and galaxy resources. + /// + /// A task that represents the asynchronous operation. public async ValueTask DisposeAsync() { if (_session is not null) await _session.DisposeAsync().ConfigureAwait(false); diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentService.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentService.cs index 1ef2c715..67958423 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentService.cs @@ -137,6 +137,7 @@ public class DeploymentService /// The database ID of the instance to deploy. /// The username initiating the deployment, recorded in the audit log. /// Cancellation token for the operation. + /// A task that resolves to a success result containing the deployment record, or a failure result with an error message. public async Task> DeployInstanceAsync( int instanceId, string user, @@ -335,6 +336,7 @@ public class DeploymentService /// The database ID of the instance to disable. /// The username initiating the operation, recorded in the audit log. /// Cancellation token for the operation. + /// A task that resolves to a success result with the site response, or a failure result with an error message. public async Task> DisableInstanceAsync( int instanceId, string user, @@ -404,6 +406,7 @@ public class DeploymentService /// The database ID of the instance to enable. /// The username initiating the operation, recorded in the audit log. /// Cancellation token for the operation. + /// A task that resolves to a success result with the site response, or a failure result with an error message. public async Task> EnableInstanceAsync( int instanceId, string user, @@ -472,6 +475,7 @@ public class DeploymentService /// The database ID of the instance to delete. /// The username initiating the deletion, recorded in the audit log. /// Cancellation token for the operation. + /// A task that resolves to a success result with the site response, or a failure result with an error message. public async Task> DeleteInstanceAsync( int instanceId, string user, @@ -568,6 +572,7 @@ public class DeploymentService /// /// The database ID of the instance to compare. /// Cancellation token for the operation. + /// A task that resolves to a success result with the comparison, or a failure result if no snapshot exists. public async Task> GetDeploymentComparisonAsync( int instanceId, CancellationToken cancellationToken = default) @@ -636,6 +641,7 @@ public class DeploymentService /// /// The unique deployment identifier to look up. /// Cancellation token for the operation. + /// A task that resolves to the matching deployment record, or null if none exists. public async Task GetDeploymentStatusAsync( string deploymentId, CancellationToken cancellationToken = default) diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentStatusNotifier.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentStatusNotifier.cs index 9ec908c3..08af178b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentStatusNotifier.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/DeploymentStatusNotifier.cs @@ -22,7 +22,7 @@ public sealed class DeploymentStatusNotifier : IDeploymentStatusNotifier _logger = logger; } - /// + /// Raised after each call to to broadcast a deployment status change to all registered subscribers. public event Action? StatusChanged; /// diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/IFlatteningPipeline.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/IFlatteningPipeline.cs index 466cc77c..98857859 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/IFlatteningPipeline.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/IFlatteningPipeline.cs @@ -15,6 +15,7 @@ public interface IFlatteningPipeline /// /// Id of the instance to flatten and validate. /// Cancellation token. + /// A task that resolves to the flattened configuration, revision hash, and validation result; or a failure result if flattening could not complete. Task> FlattenAndValidateAsync( int instanceId, CancellationToken cancellationToken = default); diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ServiceCollectionExtensions.cs index bad0d891..916af136 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/ServiceCollectionExtensions.cs @@ -21,6 +21,7 @@ public static class ServiceCollectionExtensions /// artifact-deployment timeouts are tunable via appsettings.json. /// /// The service collection to register into. + /// The instance for chaining. public static IServiceCollection AddDeploymentManager(this IServiceCollection services) { // DeploymentManager-008: ensure the options class is always resolvable. @@ -46,6 +47,7 @@ public static class ServiceCollectionExtensions /// Registers Deployment Manager Akka actor bindings. Actor creation is handled by the Host during actor system startup. /// /// The service collection to register into. + /// The instance for chaining. public static IServiceCollection AddDeploymentManagerActors(this IServiceCollection services) { // Akka actor registration is handled by Host component during actor system startup diff --git a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/StateTransitionValidator.cs b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/StateTransitionValidator.cs index bc75f043..84e91163 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/StateTransitionValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/StateTransitionValidator.cs @@ -18,21 +18,25 @@ public static class StateTransitionValidator { /// Returns true when a deploy operation is allowed from the given state. /// The current instance state. + /// if deploy is permitted; otherwise . public static bool CanDeploy(InstanceState currentState) => currentState is InstanceState.NotDeployed or InstanceState.Enabled or InstanceState.Disabled; /// Returns true when a disable operation is allowed from the given state. /// The current instance state. + /// if disable is permitted; otherwise . public static bool CanDisable(InstanceState currentState) => currentState == InstanceState.Enabled; /// Returns true when an enable operation is allowed from the given state. /// The current instance state. + /// if enable is permitted; otherwise . public static bool CanEnable(InstanceState currentState) => currentState == InstanceState.Disabled; /// Returns true when a delete operation is allowed from the given state. /// The current instance state. + /// if delete is permitted; otherwise . public static bool CanDelete(InstanceState currentState) => currentState is InstanceState.NotDeployed or InstanceState.Enabled or InstanceState.Disabled; @@ -41,6 +45,7 @@ public static class StateTransitionValidator /// /// The current instance state. /// The operation name to validate (e.g. "deploy", "disable", "enable", "delete"). + /// An error message string if the transition is invalid; null if it is permitted. public static string? ValidateTransition(InstanceState currentState, string operation) { var allowed = operation.ToLowerInvariant() switch diff --git a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/DatabaseGateway.cs b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/DatabaseGateway.cs index 5eaa6944..f2f266a9 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/DatabaseGateway.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/DatabaseGateway.cs @@ -70,6 +70,7 @@ public class DatabaseGateway : IDatabaseGateway /// tests can substitute a connection whose OpenAsync fails. /// /// The ADO.NET connection string. + /// A new for the given connection string. internal virtual DbConnection CreateConnection(string connectionString) => new SqlConnection(connectionString); @@ -145,6 +146,7 @@ public class DatabaseGateway : IDatabaseGateway /// /// The buffered store-and-forward message to deliver. /// Cancellation token for the delivery operation. + /// A task that resolves to true on success, or false if the connection no longer exists. public async Task DeliverBufferedAsync( StoreAndForwardMessage message, CancellationToken cancellationToken = default) { @@ -210,6 +212,12 @@ public class DatabaseGateway : IDatabaseGateway // precision for typical money/measurement values), and only fall through // to double for genuinely out-of-decimal-range values (very large // scientific-notation floats). + /// + /// Converts a to the most appropriate SQL parameter value, + /// preferring longdecimaldouble for numeric kinds to preserve precision. + /// + /// The JSON element to convert. + /// A boxed CLR value suitable for use as an ADO.NET parameter, or for null/undefined. internal static object JsonElementToParameterValue(JsonElement element) => element.ValueKind switch { JsonValueKind.String => (object?)element.GetString() ?? DBNull.Value, diff --git a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ErrorClassifier.cs b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ErrorClassifier.cs index ba7218b5..cb04fc18 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ErrorClassifier.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ErrorClassifier.cs @@ -17,6 +17,7 @@ public static class ErrorClassifier /// succeed and risks duplicate side effects. /// /// The HTTP status code to classify. + /// for 5xx, 408, or 429; for all other status codes. public static bool IsTransient(HttpStatusCode statusCode) { var code = (int)statusCode; @@ -27,6 +28,7 @@ public static class ErrorClassifier /// Determines whether an exception represents a transient failure. /// /// The exception to classify. + /// for connection/timeout/cancellation exceptions; otherwise. public static bool IsTransient(Exception exception) { return exception is HttpRequestException @@ -40,6 +42,7 @@ public static class ErrorClassifier /// /// Human-readable failure description. /// Optional inner exception that caused the transient failure. + /// A new wrapping the given details. public static TransientExternalSystemException AsTransient(string message, Exception? inner = null) { return new TransientExternalSystemException(message, inner); diff --git a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ServiceCollectionExtensions.cs index 5eda0a24..498383be 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ServiceCollectionExtensions.cs @@ -17,6 +17,7 @@ public static class ServiceCollectionExtensions /// Registers the External System Gateway services, HTTP client factory, and options. /// /// The service collection to configure. + /// The same for chaining. public static IServiceCollection AddExternalSystemGateway(this IServiceCollection services) { services.AddOptions() @@ -49,6 +50,7 @@ public static class ServiceCollectionExtensions /// Placeholder for External System Gateway Akka.NET actor registrations (handled in AkkaHostedService). /// /// The service collection to configure. + /// The same for chaining. public static IServiceCollection AddExternalSystemGatewayActors(this IServiceCollection services) { // WP-10: Actor registration happens in AkkaHostedService. diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/CentralHealthAggregator.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/CentralHealthAggregator.cs index 9654b7c9..998252f2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/CentralHealthAggregator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/CentralHealthAggregator.cs @@ -211,6 +211,7 @@ public class CentralHealthAggregator : BackgroundService, ICentralHealthAggregat /// full OfflineTimeout / 2. /// /// The health monitoring options to derive the interval from. + /// Half the shorter of the two configured offline timeouts. internal static TimeSpan ComputeCheckInterval(HealthMonitoringOptions options) { var shorter = options.OfflineTimeout < options.CentralOfflineTimeout diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/HealthMonitoringOptionsValidator.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/HealthMonitoringOptionsValidator.cs index 3fdf3bb1..356fb662 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/HealthMonitoringOptionsValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/HealthMonitoringOptionsValidator.cs @@ -16,11 +16,7 @@ namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring; /// public sealed class HealthMonitoringOptionsValidator : OptionsValidatorBase { - /// - /// Validates the health monitoring options, recording a failure if any interval values are non-positive. - /// - /// The accumulator to record failures on. - /// The health monitoring options to validate. + /// protected override void Validate(ValidationBuilder builder, HealthMonitoringOptions options) { builder.RequireThat(options.ReportInterval > TimeSpan.Zero, diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ICentralHealthAggregator.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ICentralHealthAggregator.cs index 45217259..81cb5104 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ICentralHealthAggregator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ICentralHealthAggregator.cs @@ -33,8 +33,10 @@ public interface ICentralHealthAggregator void MarkHeartbeat(string siteId, DateTimeOffset receivedAt); /// Returns a snapshot of all currently tracked site health states. + /// A dictionary mapping site id to its current . IReadOnlyDictionary GetAllSiteStates(); /// Returns the current health state for the specified site, or null if not tracked. /// The string identifier of the site to look up. + /// The for the site, or null if not yet seen. SiteHealthState? GetSiteState(string siteId); } diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/IClusterNodeProvider.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/IClusterNodeProvider.cs index 9da88b11..87227f8e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/IClusterNodeProvider.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/IClusterNodeProvider.cs @@ -9,6 +9,7 @@ namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring; public interface IClusterNodeProvider { /// Returns the current status of all cluster nodes for the provider's role scope. + /// A read-only list of node status records for all known cluster nodes. IReadOnlyList GetClusterNodes(); /// diff --git a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ServiceCollectionExtensions.cs index 743f794c..2bff9f09 100644 --- a/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/ServiceCollectionExtensions.cs @@ -11,6 +11,7 @@ public static class ServiceCollectionExtensions /// Call this on site nodes only. For central, call AddCentralHealthAggregation() instead. /// /// The DI service collection to register into. + /// The same instance, for call chaining. public static IServiceCollection AddSiteHealthMonitoring(this IServiceCollection services) { AddOptionsValidation(services); @@ -24,6 +25,7 @@ public static class ServiceCollectionExtensions /// Does not start the HealthReportSender — call AddSiteHealthMonitoring() on site nodes for that. /// /// The DI service collection to register into. + /// The same instance, for call chaining. public static IServiceCollection AddHealthMonitoring(this IServiceCollection services) { AddOptionsValidation(services); @@ -37,6 +39,7 @@ public static class ServiceCollectionExtensions /// for the central cluster so it appears on /monitoring/health. /// /// The DI service collection to register into. + /// The same instance, for call chaining. public static IServiceCollection AddCentralHealthAggregation(this IServiceCollection services) { AddOptionsValidation(services); diff --git a/src/ZB.MOM.WW.ScadaBridge.Host/Health/ActiveNodeGate.cs b/src/ZB.MOM.WW.ScadaBridge.Host/Health/ActiveNodeGate.cs index c5fa790d..9795b665 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Host/Health/ActiveNodeGate.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Host/Health/ActiveNodeGate.cs @@ -32,11 +32,7 @@ public sealed class ActiveNodeGate : IActiveNodeGate _akkaService = akkaService; } - /// - /// true only when this node has joined the cluster () - /// AND is the current cluster leader; false in every other state - /// (actor system not yet started, node still joining, node is a standby). - /// + /// public bool IsActiveNode { get diff --git a/src/ZB.MOM.WW.ScadaBridge.Host/LoggerConfigurationFactory.cs b/src/ZB.MOM.WW.ScadaBridge.Host/LoggerConfigurationFactory.cs index 84bd750c..7b59adb8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Host/LoggerConfigurationFactory.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Host/LoggerConfigurationFactory.cs @@ -52,6 +52,7 @@ public static class LoggerConfigurationFactory /// Site identifier added as a log enrichment property. /// Hostname added as a log enrichment property. /// Writer that receives the one-shot Host-020 override-warning when both keys are present. + /// The fully configured ready to create the Serilog logger. internal static LoggerConfiguration Build( IConfiguration configuration, string nodeRole, @@ -104,6 +105,8 @@ public static class LoggerConfigurationFactory /// Null/blank values are treated as "unset" and silently default — only /// explicit-but-invalid values trigger the warning. /// + /// Configured level string, possibly null/blank/invalid. + /// The parsed , or when the value is absent or unrecognised. internal static LogEventLevel ParseLevel(string? level) => ParseLevel(level, Console.Error); @@ -114,6 +117,7 @@ public static class LoggerConfigurationFactory /// /// Configured level string, possibly null/blank/invalid. /// Writer that receives a single warning line if the value is non-blank but unparseable. + /// The parsed , or when the value is absent or unrecognised. internal static LogEventLevel ParseLevel(string? level, TextWriter warningWriter) { if (Enum.TryParse(level, ignoreCase: true, out var parsed)) diff --git a/src/ZB.MOM.WW.ScadaBridge.Host/StartupRetry.cs b/src/ZB.MOM.WW.ScadaBridge.Host/StartupRetry.cs index fbed19b2..62ed0e44 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Host/StartupRetry.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Host/StartupRetry.cs @@ -28,6 +28,7 @@ public static class StartupRetry /// Logger for retry warnings. /// Optional predicate classifying an exception as transient; null means all exceptions are transient. /// Cancellation token that aborts the retry loop immediately. + /// A task that completes when the operation succeeds, or faults on a permanent or final-attempt failure. public static Task ExecuteWithRetryAsync( string operationName, Func operation, @@ -45,6 +46,14 @@ public static class StartupRetry /// IHostApplicationLifetime.ApplicationStopping inside the operation as well /// as inside the inter-attempt Task.Delay. /// + /// Human-readable name of the operation, used in log messages. + /// The async operation to attempt; receives the cancellation token on each try. + /// Maximum number of attempts before the exception propagates. + /// Delay before the second attempt; doubled on each subsequent retry, capped at 30 seconds. + /// Logger for retry warnings and success messages. + /// Optional predicate classifying an exception as transient; null means all exceptions are transient. + /// Token to observe for cancellation; aborts the retry loop immediately. + /// A task that completes when the operation succeeds, or faults on a permanent or final-attempt failure. public static async Task ExecuteWithRetryAsync( string operationName, Func operation, @@ -93,6 +102,7 @@ public static class StartupRetry /// permanent and must fail fast). /// /// The exception to classify. + /// true if the exception is a transient connection or timeout fault; false otherwise. public static bool IsTransientDatabaseFault(Exception ex) { // Unwrap a single layer of aggregation so a faulted Task surfaces correctly. diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/EndpointExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/EndpointExtensions.cs index d7a82ef4..c6937003 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/EndpointExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/EndpointExtensions.cs @@ -53,6 +53,7 @@ public static class EndpointExtensions /// Registers the POST /api/{methodName} inbound API endpoint with the active-node gate and body-size filter applied. /// The route builder to add the endpoint to. + /// The same instance for chaining. public static IEndpointRouteBuilder MapInboundAPI(this IEndpointRouteBuilder endpoints) { endpoints.MapPost("/api/{methodName}", HandleInboundApiRequest) diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ForbiddenApiChecker.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ForbiddenApiChecker.cs index 66f69bef..5d345b48 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ForbiddenApiChecker.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ForbiddenApiChecker.cs @@ -96,6 +96,7 @@ public static class ForbiddenApiChecker /// An empty list means the script is acceptable. /// /// The C# script source to analyse. + /// A list of trust-model violation messages; empty if the script is clean. public static IReadOnlyList FindViolations(string scriptCode) { if (string.IsNullOrWhiteSpace(scriptCode)) diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/IInstanceRouter.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/IInstanceRouter.cs index 9ddc46e4..1d08d123 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/IInstanceRouter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/IInstanceRouter.cs @@ -15,6 +15,7 @@ public interface IInstanceRouter /// Target site identifier. /// The call request to route. /// Cancellation token for the routed call. + /// A task that resolves to the call response from the target site. Task RouteToCallAsync( string siteId, RouteToCallRequest request, CancellationToken cancellationToken); @@ -22,6 +23,7 @@ public interface IInstanceRouter /// Target site identifier. /// The get-attributes request to route. /// Cancellation token for the routed call. + /// A task that resolves to the get-attributes response from the target site. Task RouteToGetAttributesAsync( string siteId, RouteToGetAttributesRequest request, CancellationToken cancellationToken); @@ -29,6 +31,7 @@ public interface IInstanceRouter /// Target site identifier. /// The set-attributes request to route. /// Cancellation token for the routed call. + /// A task that resolves to the set-attributes response from the target site. Task RouteToSetAttributesAsync( string siteId, RouteToSetAttributesRequest request, CancellationToken cancellationToken); } diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/InboundApiEndpointFilter.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/InboundApiEndpointFilter.cs index 56c8deaf..b059aa26 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/InboundApiEndpointFilter.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/InboundApiEndpointFilter.cs @@ -40,6 +40,7 @@ public sealed class InboundApiEndpointFilter : IEndpointFilter /// Applies active-node gating and request body size checks before delegating to the next filter or handler. /// The endpoint filter invocation context containing the HTTP context and arguments. /// The next filter or endpoint handler in the pipeline. + /// A value task that resolves to the filter pipeline result, or an error result if gating fails. public async ValueTask InvokeAsync( EndpointFilterInvocationContext context, EndpointFilterDelegate next) diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddleware.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddleware.cs index 3fce05b9..9d7cc1f5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddleware.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddleware.cs @@ -128,6 +128,7 @@ public sealed class AuditWriteMiddleware /// Executes the middleware: captures the request/response bodies and writes an inbound API audit event. /// /// The current HTTP context. + /// A task that represents the asynchronous operation. public async Task InvokeAsync(HttpContext ctx) { var sw = Stopwatch.StartNew(); @@ -686,6 +687,7 @@ public sealed class AuditWriteMiddleware /// audit copy hit the cap. Returns (null, false) when no bytes /// were captured, mirroring the request-body empty contract. /// + /// A tuple of the captured body string (or null if nothing was captured) and a flag indicating whether the cap was exceeded. public (string? body, bool truncated) GetCapturedBody() { var length = (int)_captured.Length; diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddlewareExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddlewareExtensions.cs index c73a6d72..db08a489 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddlewareExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/Middleware/AuditWriteMiddlewareExtensions.cs @@ -19,6 +19,7 @@ public static class AuditWriteMiddlewareExtensions /// middleware runs. /// /// The application builder to add the middleware to. + /// The same instance, for call chaining. public static IApplicationBuilder UseAuditWriteMiddleware(this IApplicationBuilder app) { ArgumentNullException.ThrowIfNull(app); diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ParameterValidator.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ParameterValidator.cs index c99bf0e5..28b3c3b5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ParameterValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ParameterValidator.cs @@ -15,6 +15,7 @@ public static class ParameterValidator /// /// The parsed JSON request body; null or undefined if no body was supplied. /// JSON-serialized list of ; null or empty means no parameters are defined. + /// A with coerced parameter values on success, or an error message on failure. public static ParameterValidationResult Validate( JsonElement? body, string? parameterDefinitions) @@ -161,6 +162,7 @@ public class ParameterValidationResult /// Creates a successful validation result with the given parameters. /// /// The validated and coerced parameter values. + /// A with set to true. public static ParameterValidationResult Valid(Dictionary parameters) => new() { IsValid = true, Parameters = parameters }; @@ -168,6 +170,7 @@ public class ParameterValidationResult /// Creates a failed validation result with the given error message. /// /// Description of the validation failure. + /// A with set to false. public static ParameterValidationResult Invalid(string message) => new() { IsValid = false, ErrorMessage = message }; } diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ReturnValueValidator.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ReturnValueValidator.cs index feac6528..7b3b438a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ReturnValueValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ReturnValueValidator.cs @@ -28,6 +28,7 @@ public static class ReturnValueValidator /// /// The JSON-serialized script return value to validate. /// JSON-serialized list of entries, or null/empty to skip validation. + /// A indicating success or describing the first validation failure. public static ReturnValidationResult Validate(string? resultJson, string? returnDefinition) { if (string.IsNullOrWhiteSpace(returnDefinition)) @@ -144,10 +145,12 @@ public sealed class ReturnValidationResult public string ErrorMessage { get; private init; } = string.Empty; /// Returns a successful validation result. + /// A with set to true. public static ReturnValidationResult Valid() => new() { IsValid = true }; /// Returns a failed validation result with the specified error message. /// Human-readable description of the validation failure. + /// A with set to false and the given error message. public static ReturnValidationResult Invalid(string message) => new() { IsValid = false, ErrorMessage = message }; } diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs index 73b7ab10..76c02a97 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs @@ -53,6 +53,7 @@ public class RouteHelper /// requires. /// /// The executing method's timeout cancellation token to inherit for routed calls. + /// A new inheriting the given deadline token. public RouteHelper WithDeadline(CancellationToken deadlineToken) => new(_instanceLocator, _instanceRouter, deadlineToken, _parentExecutionId); @@ -66,6 +67,7 @@ public class RouteHelper /// script context. /// /// The inbound request's execution id to stamp as the spawning parent on routed calls, or null for non-routed runs. + /// A new carrying the given parent execution id. public RouteHelper WithParentExecutionId(Guid? parentExecutionId) => new(_instanceLocator, _instanceRouter, _deadlineToken, parentExecutionId); @@ -73,6 +75,7 @@ public class RouteHelper /// Creates a route target for the specified instance. /// /// The unique code of the instance to route calls to. + /// A bound to the specified instance. public RouteTarget To(string instanceCode) { return new RouteTarget( @@ -125,6 +128,7 @@ public class RouteTarget /// Name of the script to call on the remote instance. /// Optional parameters passed to the script; may be a dictionary or anonymous object. /// Optional cancellation token; defaults to the method deadline when not supplied. + /// A task that resolves to the remote script's return value, or null. public async Task Call( string scriptName, object? parameters = null, @@ -158,6 +162,7 @@ public class RouteTarget /// /// Name of the attribute to read. /// Optional cancellation token; defaults to the method deadline. + /// A task that resolves to the attribute value, or null if the key is absent. public async Task GetAttribute( string attributeName, CancellationToken cancellationToken = default) @@ -171,6 +176,7 @@ public class RouteTarget /// /// Names of the attributes to read. /// Optional cancellation token; defaults to the method deadline. + /// A task that resolves to a map of attribute names to their current values. public async Task> GetAttributes( IEnumerable attributeNames, CancellationToken cancellationToken = default) @@ -205,6 +211,7 @@ public class RouteTarget /// Name of the attribute to write. /// Value to set on the attribute. /// Optional cancellation token; defaults to the method deadline. + /// A task that represents the asynchronous operation. public async Task SetAttribute( string attributeName, string value, @@ -220,6 +227,7 @@ public class RouteTarget /// /// Map of attribute names to values to write. /// Optional cancellation token; defaults to the method deadline. + /// A task that represents the asynchronous operation. public async Task SetAttributes( IReadOnlyDictionary attributeValues, CancellationToken cancellationToken = default) diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ServiceCollectionExtensions.cs index fa639bf9..13340144 100644 --- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/ServiceCollectionExtensions.cs @@ -8,6 +8,7 @@ public static class ServiceCollectionExtensions /// Registers all inbound API services (script executor, route helper, and endpoint filter). /// /// The service collection to register into. + /// The same to allow chaining. public static IServiceCollection AddInboundAPI(this IServiceCollection services) { // Auth re-arch (C5): inbound authentication is handled by the shared diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditEndpoints.cs index ed1563da..acbffcc0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditEndpoints.cs @@ -89,6 +89,7 @@ public static class AuditEndpoints /// Registers the /api/audit/query and /api/audit/export minimal-API endpoints. /// /// The endpoint route builder to register routes on. + /// The same builder, for chaining. public static IEndpointRouteBuilder MapAuditAPI(this IEndpointRouteBuilder endpoints) { endpoints.MapGet("/api/audit/query", (Delegate)HandleQuery); @@ -104,6 +105,7 @@ public static class AuditEndpoints /// Handles GET /api/audit/query: authenticates, checks the OperationalAudit permission, and returns a keyset-paged JSON result. /// /// The HTTP context for the current request. + /// A task that resolves to the HTTP result (200 JSON page, 401, or 403). internal static async Task HandleQuery(HttpContext context) { var auth = await AuthenticateAsync(context); @@ -163,6 +165,7 @@ public static class AuditEndpoints /// Handles GET /api/audit/export: authenticates, checks the AuditExport permission, and streams the matching rows as CSV or JSONL. /// /// The HTTP context for the current request. + /// A task that resolves to the HTTP result (streaming CSV/JSONL, 400, 401, 403, or 501). internal static async Task HandleExport(HttpContext context) { var auth = await AuthenticateAsync(context); @@ -401,6 +404,8 @@ public static class AuditEndpoints /// with the permitted set) returns null so the caller gets a 403 rather /// than silently empty results. /// + /// The caller-supplied audit-log query filter to scope. + /// The authenticated user whose permitted site IDs constrain the filter. /// /// The restricted filter, or null if the caller explicitly asked for /// sites entirely outside their permitted set. @@ -455,6 +460,7 @@ public static class AuditEndpoints /// builder — so do NOT "fix" the two to a single key name. /// /// The HTTP query string collection to parse filter parameters from. + /// An built from the supplied query parameters. public static AuditLogQueryFilter ParseFilter(IQueryCollection query) { var channels = AuditQueryParamParsers.ParseEnumList(query["channel"]); @@ -506,6 +512,7 @@ public static class AuditEndpoints /// keyset cursor requires the pair together). /// /// The HTTP query string collection to parse paging parameters from. + /// An built from the supplied query parameters. public static AuditLogPaging ParsePaging(IQueryCollection query) { int pageSize = DefaultPageSize; @@ -576,6 +583,7 @@ public static class AuditEndpoints /// Formats a single as an RFC 4180 CSV row matching . /// /// The audit event to format. + /// An RFC 4180 CSV row string (no trailing newline) for the supplied event. public static string FormatCsvRow(AuditExportRow evt) { var sb = new StringBuilder(256); diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditExportRow.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditExportRow.cs index 3d72fa8e..36608f4f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditExportRow.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/AuditExportRow.cs @@ -63,6 +63,8 @@ public sealed record AuditExportRow public AuditForwardState? ForwardState { get; init; } /// Decomposes a canonical into this flat export shape. + /// The audit event to decompose into the flat export row. + /// A new populated from the decomposed canonical row. public static AuditExportRow From(AuditEvent evt) { var r = AuditRowProjection.Decompose(evt); diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/DebugStreamHub.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/DebugStreamHub.cs index 754639bd..fb2ac1de 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/DebugStreamHub.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/DebugStreamHub.cs @@ -33,6 +33,7 @@ public class DebugStreamHub : Hub /// Roles held by the connected user. /// Site ids the user is scoped to; empty means system-wide. /// Site id of the instance being subscribed to. + /// if the user may subscribe to the instance; otherwise . public static bool IsInstanceAccessAllowed( IReadOnlyCollection roles, IReadOnlyCollection permittedSiteIds, @@ -134,6 +135,7 @@ public class DebugStreamHub : Hub /// Sends the initial snapshot immediately, then streams incremental changes. /// /// Database id of the instance to subscribe to. + /// A task that represents the asynchronous operation. public async Task SubscribeInstance(int instanceId) { // Stop any existing subscription for this connection @@ -222,6 +224,7 @@ public class DebugStreamHub : Hub /// /// Unsubscribes from the current debug stream. /// + /// A task that represents the asynchronous operation. public Task UnsubscribeInstance() { if (Context.Items.TryGetValue(SessionIdKey, out var sessionIdObj) && sessionIdObj is string sessionId) diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs index 811bd156..72dd1eaa 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs @@ -59,6 +59,7 @@ public class ManagementActor : ReceiveActor /// makes the contract correct ahead of any future worker actors (finding /// ManagementService-005). /// + /// A one-for-one Resume strategy with no retry limit. public static SupervisorStrategy CreateSupervisorStrategy() => new OneForOneStrategy( maxNrOfRetries: -1, @@ -85,6 +86,7 @@ public class ManagementActor : ReceiveActor /// serializer the HTTP endpoint uses — with cycle-safe settings. /// /// The command result object to serialize, or null. + /// The JSON string representation of , or "null" when null. public static string SerializeResult(object? result) => JsonSerializer.Serialize(result, ResultSerializerOptions); diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementEndpoints.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementEndpoints.cs index 5766d188..7d9d9095 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementEndpoints.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementEndpoints.cs @@ -24,6 +24,7 @@ public static class ManagementEndpoints /// zero/negative timeout would make every management call fail immediately. /// /// The management service options, or null if not configured. + /// The configured timeout, or when none is set. public static TimeSpan ResolveAskTimeout(ManagementServiceOptions? options) { if (options is { CommandTimeout: { Ticks: > 0 } configured }) @@ -33,6 +34,7 @@ public static class ManagementEndpoints /// Registers the POST /management endpoint on the given route builder. /// The route builder to add the endpoint to. + /// The same instance for chaining. public static IEndpointRouteBuilder MapManagementAPI(this IEndpointRouteBuilder endpoints) { endpoints.MapPost("/management", (Delegate)HandleRequest); @@ -166,9 +168,11 @@ public static class ManagementEndpoints { /// Creates a successful parse result wrapping the given command. /// The strongly-typed command object that was parsed. + /// A successful containing the parsed command. public static CommandParseResult Ok(object command) => new(true, command, null, null); /// Creates a failed parse result with the given error message. /// Human-readable description of the parse failure. + /// A failed with the error message and BAD_REQUEST code. public static CommandParseResult Fail(string message) => new(false, null, message, "BAD_REQUEST"); } @@ -179,6 +183,7 @@ public static class ManagementEndpoints /// case does not allocate a throwaway document (finding ManagementService-006). /// /// The raw JSON request body string. + /// A with the deserialized command on success, or an error on failure. public static CommandParseResult ParseCommand(string body) { using JsonDocument doc = ParseDocument(body, out var parseError); diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ServiceCollectionExtensions.cs index 6491b455..d32edc0b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/ServiceCollectionExtensions.cs @@ -8,6 +8,7 @@ public static class ServiceCollectionExtensions /// Registers the management actor holder and management service options. /// /// The service collection to register into. + /// The instance for chaining. public static IServiceCollection AddManagementService(this IServiceCollection services) { services.AddSingleton(); diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Delivery/DeliveryOutcome.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Delivery/DeliveryOutcome.cs index 685ca5ac..e0110a4e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Delivery/DeliveryOutcome.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/Delivery/DeliveryOutcome.cs @@ -28,16 +28,19 @@ public record DeliveryOutcome(DeliveryResult Result, string? ResolvedTargets, st { /// Creates a successful outcome carrying the resolved delivery targets. /// The concrete delivery targets used, for audit. + /// A with and the resolved targets set. public static DeliveryOutcome Success(string resolvedTargets) => new(DeliveryResult.Success, resolvedTargets, null); /// Creates a transient-failure outcome carrying an error description. /// Human-readable description of the transient failure. + /// A with and the error set. public static DeliveryOutcome Transient(string error) => new(DeliveryResult.TransientFailure, null, error); /// Creates a permanent-failure outcome carrying an error description. /// Human-readable description of the permanent failure. + /// A with and the error set. public static DeliveryOutcome Permanent(string error) => new(DeliveryResult.PermanentFailure, null, error); } diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/ServiceCollectionExtensions.cs index d3b8d0e2..009a42dc 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/ServiceCollectionExtensions.cs @@ -31,6 +31,7 @@ public static class ServiceCollectionExtensions /// the singleton actor. /// /// The DI service collection to register notification outbox services into. + /// The same instance for chaining. public static IServiceCollection AddNotificationOutbox(this IServiceCollection services) { ArgumentNullException.ThrowIfNull(services); diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/CredentialRedactor.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/CredentialRedactor.cs index eb631030..185ca223 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/CredentialRedactor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/CredentialRedactor.cs @@ -33,6 +33,16 @@ public static class CredentialRedactor /// private const int MinSecretLength = 12; + /// + /// Returns with every secret component of the supplied + /// colon-delimited credential string masked. + /// + /// The text to scrub (e.g. an exception message). Returns empty string if null. + /// + /// The credential string in use — Basic Auth user:pass or OAuth2 + /// tenantId:clientId:clientSecret. May be null; returns unmodified when null. + /// + /// The scrubbed text with secret components replaced by ***REDACTED***. public static string Scrub(string? text, string? credentials) { if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(credentials)) diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/EmailAddressValidator.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/EmailAddressValidator.cs index 51b07ffa..07dfb72b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/EmailAddressValidator.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/EmailAddressValidator.cs @@ -20,6 +20,7 @@ public static class EmailAddressValidator /// /// The sender email address to validate. /// The list of recipient addresses to validate. + /// A human-readable error string if any address is malformed; null if all addresses parse successfully. public static string? ValidateAddresses( string fromAddress, IReadOnlyList recipients) { diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/ISmtpClientWrapper.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/ISmtpClientWrapper.cs index 084a5c6d..cc0eca2c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/ISmtpClientWrapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/ISmtpClientWrapper.cs @@ -20,6 +20,7 @@ public interface ISmtpClientWrapper /// SMTP server hostname or IP address. /// SMTP server port. /// Cancellation token. + /// A task that represents the asynchronous operation. Task ConnectAsync( string host, int port, @@ -37,6 +38,7 @@ public interface ISmtpClientWrapper /// callers that do not authenticate with OAuth2. /// /// Cancellation token. + /// A task that represents the asynchronous operation. Task AuthenticateAsync( string authType, string? credentials, @@ -48,8 +50,10 @@ public interface ISmtpClientWrapper /// Email subject line. /// Plain-text email body. /// Cancellation token. + /// A task that represents the asynchronous operation. Task SendAsync(string from, IEnumerable bccRecipients, string subject, string body, CancellationToken cancellationToken = default); /// Disconnects from the SMTP server gracefully. /// Cancellation token. + /// A task that represents the asynchronous operation. Task DisconnectAsync(CancellationToken cancellationToken = default); } diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/ServiceCollectionExtensions.cs index 8cf2189e..9aa46101 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/ServiceCollectionExtensions.cs @@ -14,6 +14,7 @@ public static class ServiceCollectionExtensions /// was removed (NS-019). Notification dispatch lives in ZB.MOM.WW.ScadaBridge.NotificationOutbox. /// /// The service collection to register into. + /// The same collection, for chaining. public static IServiceCollection AddNotificationService(this IServiceCollection services) { services.AddOptions() @@ -30,6 +31,7 @@ public static class ServiceCollectionExtensions /// Registers Akka.NET actors for the notification service (placeholder for actor registration). /// /// The service collection to register into. + /// The same collection, for chaining. public static IServiceCollection AddNotificationServiceActors(this IServiceCollection services) { // Actor registration happens in AkkaHostedService. diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpErrorClassifier.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpErrorClassifier.cs index 07ba56f8..b2b9c9f5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpErrorClassifier.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpErrorClassifier.cs @@ -43,6 +43,7 @@ public static class SmtpErrorClassifier /// The token governing the send; a requested cancellation classifies as /// so the caller can re-throw it. /// + /// The describing whether the failure is transient, permanent, or unknown. public static SmtpErrorClass Classify(Exception ex, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(ex); @@ -90,6 +91,7 @@ public static class SmtpErrorClassifier /// /// The exception to classify. /// Cancellation token passed to . + /// true when returns . public static bool IsTransient(Exception ex, CancellationToken cancellationToken) => Classify(ex, cancellationToken) == SmtpErrorClass.Transient; } diff --git a/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpTlsMode.cs b/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpTlsMode.cs index 62196458..61476e44 100644 --- a/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpTlsMode.cs +++ b/src/ZB.MOM.WW.ScadaBridge.NotificationService/SmtpTlsMode.cs @@ -30,6 +30,7 @@ public static class SmtpTlsModeParser /// /// The TLS mode string to parse (None, StartTLS, or SSL); null/empty defaults to StartTLS. /// The value is not one of None/StartTLS/SSL. + /// The corresponding enum value. public static SmtpTlsMode Parse(string? tlsMode) { if (string.IsNullOrWhiteSpace(tlsMode)) diff --git a/src/ZB.MOM.WW.ScadaBridge.Security/AuthorizationPolicies.cs b/src/ZB.MOM.WW.ScadaBridge.Security/AuthorizationPolicies.cs index 4d5710ad..4e75034f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Security/AuthorizationPolicies.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Security/AuthorizationPolicies.cs @@ -121,6 +121,7 @@ public static class AuthorizationPolicies /// Registers the ScadaBridge authorization policies (Admin, Design, Deployment, OperationalAudit, AuditExport). /// /// The service collection to register into. + /// The same instance, for call chaining. public static IServiceCollection AddScadaBridgeAuthorization(this IServiceCollection services) { services.AddAuthorization(options => diff --git a/src/ZB.MOM.WW.ScadaBridge.Security/JwtTokenService.cs b/src/ZB.MOM.WW.ScadaBridge.Security/JwtTokenService.cs index 102cd4be..6d47471c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Security/JwtTokenService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Security/JwtTokenService.cs @@ -74,6 +74,7 @@ public class JwtTokenService /// Role names to embed as claims. /// Site identifiers the user may deploy to; null for system-wide access. /// Idle-timeout anchor; defaults to now when null (fresh login). + /// The signed JWT string, ready to embed in a cookie or bearer header. public string GenerateToken( string displayName, string username, diff --git a/src/ZB.MOM.WW.ScadaBridge.Security/ScadaBridgeGroupRoleMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Security/ScadaBridgeGroupRoleMapper.cs index 02a23ee0..08358fd7 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Security/ScadaBridgeGroupRoleMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Security/ScadaBridgeGroupRoleMapper.cs @@ -28,7 +28,14 @@ public sealed class ScadaBridgeGroupRoleMapper : IGroupRoleMapper _roleMapper = roleMapper ?? throw new ArgumentNullException(nameof(roleMapper)); } - /// + /// + /// Maps a list of LDAP/AD group names to ScadaBridge roles using the wrapped + /// and returns the resulting role mapping with site-scope + /// information carried in the opaque Scope field. + /// + /// The AD/LDAP group names to resolve into roles. + /// Cancellation token. + /// A task that resolves to the group-to-role mapping including permitted site identifiers. public async Task> MapAsync(IReadOnlyList groups, CancellationToken ct) { var result = await _roleMapper.MapGroupsToRolesAsync(groups, ct); diff --git a/src/ZB.MOM.WW.ScadaBridge.Security/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.Security/ServiceCollectionExtensions.cs index faa006b1..4106c1ac 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Security/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Security/ServiceCollectionExtensions.cs @@ -33,6 +33,7 @@ public static class ServiceCollectionExtensions /// IConfiguration) and component libraries must not accept IConfiguration. /// /// The service collection to register into. + /// The same instance for chaining. public static IServiceCollection AddSecurity(this IServiceCollection services) { // Task 1.2 cutover: ScadaBridge's bespoke LdapAuthService was replaced by the @@ -146,6 +147,7 @@ public static class ServiceCollectionExtensions /// Registers security-related Akka actors (placeholder for future actor registrations). /// /// The service collection to register into. + /// The same instance for chaining. public static IServiceCollection AddSecurityActors(this IServiceCollection services) { // Phase 0: placeholder for Akka actor registration diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/ServiceCollectionExtensions.cs index d786440f..0d456554 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/ServiceCollectionExtensions.cs @@ -29,6 +29,7 @@ public static class ServiceCollectionExtensions /// Props are still constructed inline in Host wiring. /// /// The service collection to register into. + /// The same collection, for chaining. public static IServiceCollection AddSiteCallAudit(this IServiceCollection services) { ArgumentNullException.ThrowIfNull(services); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs index 64361e7e..320a7227 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs @@ -156,18 +156,7 @@ public class SiteCallAuditActor : ReceiveActor Receive(HandleDiscardSiteCall); } - /// - /// SiteCallAudit-001: child supervision strategy — governs children, not this - /// actor. The actor has no children today, so this override is inert; it - /// returns a one-for-one strategy with the framework - /// (Restart on - /// most exceptions; Stop on / - /// ) and maxNrOfRetries: 0, so any - /// future child that throws is Stopped on the first failure. The actor's - /// own resilience comes from the try/catch in - /// plus the parent 's - /// supervision — not from this override. - /// + /// protected override SupervisorStrategy SupervisorStrategy() { return new OneForOneStrategy(maxNrOfRetries: 0, withinTimeRange: TimeSpan.Zero, decider: diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/EventLogPurgeService.cs b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/EventLogPurgeService.cs index 2e97845d..efdddd9a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/EventLogPurgeService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/EventLogPurgeService.cs @@ -17,6 +17,7 @@ namespace ZB.MOM.WW.ScadaBridge.SiteEventLogging; /// active" so non-clustered hosts and unit tests are unaffected — backward /// compatible with the prior "run on every host" behaviour. /// +/// true if this node is the active site member and should run the purge; false to skip. public delegate bool SiteEventLogActiveNodeCheck(); /// @@ -200,6 +201,7 @@ public class EventLogPurgeService : BackgroundService /// the raw file size from page_count) means the storage-cap loop observes /// space being reclaimed even if free pages have not yet been returned to the OS. /// + /// The logical database size in bytes (used pages × page size). internal long GetDatabaseSizeBytes() { return _eventLogger.WithConnection(connection => diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/IEventLogQueryService.cs b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/IEventLogQueryService.cs index e7d01614..b8981b91 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/IEventLogQueryService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/IEventLogQueryService.cs @@ -12,5 +12,6 @@ public interface IEventLogQueryService /// Executes a query against the local site event log and returns the matching entries. /// /// The query parameters including filters, pagination, and keyword search. + /// The query response containing the matching log entries and pagination metadata. EventLogQueryResponse ExecuteQuery(EventLogQueryRequest request); } diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ISiteEventLogger.cs b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ISiteEventLogger.cs index 7a4a5300..07fc9ea4 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ISiteEventLogger.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ISiteEventLogger.cs @@ -20,6 +20,7 @@ public interface ISiteEventLogger /// Optional free-form detail text (stack traces, compilation errors, etc.). /// Stored verbatim — JSON is conventional but not validated or enforced. /// + /// A task that completes once the event is durably persisted. Task LogEventAsync( string eventType, string severity, diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ServiceCollectionExtensions.cs index 180e267c..30810da5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/ServiceCollectionExtensions.cs @@ -11,6 +11,7 @@ public static class ServiceCollectionExtensions /// Register site event logging services (recording, purge, query). /// /// The DI service collection to register into. + /// The same for chaining. public static IServiceCollection AddSiteEventLogging(this IServiceCollection services) { // The recorder is registered as a concrete singleton and the interface is diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs index c1937fda..8ccc262e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs @@ -89,17 +89,7 @@ public class SiteEventLogger : ISiteEventLogger, IDisposable _writerLoop = Task.Run(ProcessWriteQueueAsync); } - /// - /// SiteEventLogging-018: number of event writes that have failed (SQLite - /// error, disk full, bounded-queue overflow drop, etc.) since this logger - /// was created. Available for future Health Monitoring integration — the - /// counter is correct and observable, but the central health-metric - /// pipeline does not yet poll it, so a sustained non-zero value currently - /// goes unnoticed in production beyond the per-failure log line. Wiring - /// the metric into the 30-second site-metric publish is tracked - /// separately; promoted to so the eventual - /// consumer reads it without a concrete-type downcast. - /// + /// public long FailedWriteCount => Interlocked.Read(ref _failedWriteCount); /// @@ -110,6 +100,7 @@ public class SiteEventLogger : ISiteEventLogger, IDisposable /// been disposed. /// /// The action to run against the shared connection. + /// if the action was executed; if the logger is disposed. internal bool WithConnection(Action action) { ArgumentNullException.ThrowIfNull(action); @@ -128,6 +119,7 @@ public class SiteEventLogger : ISiteEventLogger, IDisposable /// /// The return type of the function. /// The function to run against the shared connection. + /// The value returned by . internal T WithConnection(Func func) { ArgumentNullException.ThrowIfNull(func); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageInitializer.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageInitializer.cs index 3fe17662..f60637df 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageInitializer.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageInitializer.cs @@ -23,6 +23,7 @@ public class SiteStorageInitializer : IHostedService /// Initializes the SQLite schema before the actor system starts. /// /// Cancellation token for the startup operation. + /// A task that represents the asynchronous operation. public async Task StartAsync(CancellationToken cancellationToken) { await _storage.InitializeAsync(); @@ -32,5 +33,6 @@ public class SiteStorageInitializer : IHostedService /// No-op stop; schema initialization does not require cleanup. /// /// Unused cancellation token. + /// A task that represents the asynchronous operation. public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs index 2109d103..710c9ecb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Persistence/SiteStorageService.cs @@ -30,12 +30,14 @@ public class SiteStorageService /// reaching into private state via reflection (SiteRuntime-006). The caller owns /// the connection and is responsible for opening and disposing it. /// + /// A new, unopened against the site database. public SqliteConnection CreateConnection() => new(_connectionString); /// /// Creates the SQLite tables if they do not exist. /// Called once on site startup. /// + /// A task that completes when all tables have been created or verified. public async Task InitializeAsync() { await using var connection = new SqliteConnection(_connectionString); @@ -157,6 +159,7 @@ public class SiteStorageService /// /// Returns all deployed instance configurations from SQLite. /// + /// A task that resolves to the list of all deployed instance configurations. public async Task> GetAllDeployedConfigsAsync() { await using var connection = new SqliteConnection(_connectionString); @@ -193,6 +196,7 @@ public class SiteStorageService /// The unique deployment identifier. /// The configuration revision hash for staleness detection. /// Whether the instance is enabled. + /// A task that completes when the configuration has been stored or updated. public async Task StoreDeployedConfigAsync( string instanceName, string configJson, @@ -229,6 +233,7 @@ public class SiteStorageService /// Removes a deployed instance configuration and its static overrides. /// /// The unique name of the instance to remove. + /// A task that completes when the configuration and its overrides have been removed. public async Task RemoveDeployedConfigAsync(string instanceName) { await using var connection = new SqliteConnection(_connectionString); @@ -269,6 +274,7 @@ public class SiteStorageService /// /// The unique name of the instance. /// Whether the instance should be enabled. + /// A task that completes when the enabled flag has been updated. public async Task SetInstanceEnabledAsync(string instanceName, bool isEnabled) { await using var connection = new SqliteConnection(_connectionString); @@ -296,6 +302,7 @@ public class SiteStorageService /// Returns all static attribute overrides for an instance. /// /// The unique name of the instance. + /// A task that resolves to a dictionary mapping attribute names to their override values. public async Task> GetStaticOverridesAsync(string instanceName) { await using var connection = new SqliteConnection(_connectionString); @@ -324,6 +331,7 @@ public class SiteStorageService /// The unique name of the instance. /// The name of the attribute to override. /// The override value for the attribute. + /// A task that completes when the override has been saved. public async Task SetStaticOverrideAsync(string instanceName, string attributeName, string value) { await using var connection = new SqliteConnection(_connectionString); @@ -350,6 +358,7 @@ public class SiteStorageService /// Called on redeployment to reset overrides. /// /// The unique name of the instance. + /// A task that completes when all overrides for the instance have been deleted. public async Task ClearStaticOverridesAsync(string instanceName) { await using var connection = new SqliteConnection(_connectionString); @@ -369,6 +378,12 @@ public class SiteStorageService /// Inserts or updates a single mirrored native alarm condition, keyed by /// (instance, source canonical name, source reference). Newer transitions overwrite older ones. /// + /// Unique name of the instance owning the alarm. + /// Canonical name of the source binding (connection/alarm source). + /// Source-system reference key identifying the specific alarm condition. + /// Serialized JSON snapshot. + /// Timestamp of the most recent condition transition. + /// A task that completes when the alarm condition has been inserted or updated. public async Task UpsertNativeAlarmAsync( string instanceName, string sourceCanonicalName, string sourceReference, string conditionJson, DateTimeOffset lastTransitionAt) @@ -397,6 +412,10 @@ public class SiteStorageService /// /// Removes a single mirrored native alarm condition (e.g. a return-to-normal that drops out of retention). /// + /// Unique name of the instance owning the alarm. + /// Canonical name of the source binding. + /// Source-system reference key identifying the alarm condition to remove. + /// A task that completes when the alarm condition row has been deleted. public async Task DeleteNativeAlarmAsync(string instanceName, string sourceCanonicalName, string sourceReference) { await using var connection = new SqliteConnection(_connectionString); @@ -419,6 +438,9 @@ public class SiteStorageService /// Returns all mirrored native alarm conditions for an instance's source binding, /// used to rehydrate a NativeAlarmActor on (re)start. /// + /// Unique name of the instance to query. + /// Canonical name of the source binding to query. + /// A task that resolves to the list of stored native alarm condition rows for the binding. public async Task> GetNativeAlarmsAsync(string instanceName, string sourceCanonicalName) { await using var connection = new SqliteConnection(_connectionString); @@ -448,6 +470,8 @@ public class SiteStorageService /// /// Clears all mirrored native alarm conditions for an instance. Called on redeployment / stop. /// + /// Unique name of the instance whose native alarm state should be cleared. + /// A task that completes when all native alarm rows for the instance have been deleted. public async Task ClearNativeAlarmsForInstanceAsync(string instanceName) { await using var connection = new SqliteConnection(_connectionString); @@ -470,6 +494,7 @@ public class SiteStorageService /// The script code. /// JSON representation of parameter definitions, if any. /// JSON representation of the return type definition, if any. + /// A task that completes when the shared script has been stored or updated. public async Task StoreSharedScriptAsync(string name, string code, string? parameterDefs, string? returnDef) { await using var connection = new SqliteConnection(_connectionString); @@ -498,6 +523,7 @@ public class SiteStorageService /// /// Returns all stored shared scripts. /// + /// A task that resolves to the list of all stored shared scripts. public async Task> GetAllSharedScriptsAsync() { await using var connection = new SqliteConnection(_connectionString); @@ -532,6 +558,7 @@ public class SiteStorageService /// The authentication type (e.g., 'ApiKey', 'BasicAuth'). /// Authentication configuration JSON, if applicable. /// JSON representation of available method definitions, if any. + /// A task that completes when the external system definition has been stored or updated. public async Task StoreExternalSystemAsync( string name, string endpointUrl, string authType, string? authConfig, string? methodDefs) { @@ -568,6 +595,7 @@ public class SiteStorageService /// The database connection string. /// Maximum number of retry attempts. /// Delay between retry attempts. + /// A task that completes when the database connection definition has been stored or updated. public async Task StoreDatabaseConnectionAsync( string name, string connectionString, int maxRetries, TimeSpan retryDelay) { @@ -600,6 +628,7 @@ public class SiteStorageService /// /// The name of the notification list. /// List of recipient email addresses. + /// A task that completes when the notification list has been stored or updated. public async Task StoreNotificationListAsync(string name, IReadOnlyList recipientEmails) { await using var connection = new SqliteConnection(_connectionString); @@ -633,6 +662,7 @@ public class SiteStorageService /// Username for authentication, if applicable. /// Password for authentication, if applicable. /// OAuth2 configuration JSON, if applicable. + /// A task that completes when the SMTP configuration has been stored or updated. public async Task StoreSmtpConfigurationAsync( string name, string server, int port, string authMode, string fromAddress, string? username, string? password, string? oauthConfig) @@ -677,6 +707,7 @@ public class SiteStorageService /// Primary configuration as JSON. /// Backup configuration as JSON, if applicable. /// Number of retries for failover attempts. + /// A task that completes when the data connection definition has been stored or updated. public async Task StoreDataConnectionDefinitionAsync( string name, string protocol, string? configJson, string? backupConfigJson = null, int failoverRetryCount = 3) { @@ -708,6 +739,7 @@ public class SiteStorageService /// /// Returns all stored data connection definitions. /// + /// A task that resolves to the list of all stored data connection definitions. public async Task> GetAllDataConnectionDefinitionsAsync() { await using var connection = new SqliteConnection(_connectionString); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SyntheticId.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SyntheticId.cs index 93fbcfc3..df621e77 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SyntheticId.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Repositories/SyntheticId.cs @@ -21,6 +21,7 @@ internal static class SyntheticId /// given name using the FNV-1a hash over its UTF-8 bytes. /// /// The string to hash into a synthetic integer ID. + /// A deterministic positive 31-bit integer derived from the FNV-1a hash of the name. public static int From(string name) { var hash = FnvOffsetBasis; diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScopeAccessors.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScopeAccessors.cs index 5b3bc031..95d4911e 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScopeAccessors.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScopeAccessors.cs @@ -39,6 +39,7 @@ public class AttributeAccessor /// Resolves a key to its full canonical name by applying the scope prefix. /// /// The attribute key to resolve. + /// The fully qualified canonical name (e.g. "TempSensor.X" or "X" for the root scope). public string Resolve(string key) => ScopePrefix.Length == 0 ? key : ScopePrefix + "." + key; @@ -59,6 +60,7 @@ public class AttributeAccessor /// Gets an attribute value asynchronously. /// /// The attribute key. + /// A task that resolves to the attribute value, or null if not set. public Task GetAsync(string key) => _ctx.GetAttribute(Resolve(key)); /// @@ -66,6 +68,7 @@ public class AttributeAccessor /// /// The attribute key. /// The value to set. + /// A task that represents the asynchronous operation. public Task SetAsync(string key, object? value) => _ctx.SetAttribute(Resolve(key), value?.ToString() ?? string.Empty); } @@ -102,6 +105,7 @@ public class CompositionAccessor /// Resolves a script name to its full canonical name by applying the composition path. /// /// The script name to resolve. + /// The fully qualified canonical script name (e.g. "Module.MyScript" or "MyScript" at root). public string ResolveScript(string scriptName) => Path.Length == 0 ? scriptName : Path + "." + scriptName; @@ -110,6 +114,7 @@ public class CompositionAccessor /// /// The name of the script to call. /// Optional parameters to pass to the script. + /// A task that resolves to the script's return value, or null if none. public Task CallScript(string scriptName, object? parameters = null) => _ctx.CallScript(ResolveScript(scriptName), parameters); } @@ -157,6 +162,7 @@ internal static class ScopeAccessorFactory /// /// The script runtime context. /// The canonical-name path. + /// A new rooted at . public static AttributeAccessor AttributesFor(ScriptRuntimeContext ctx, string selfPath) => new(ctx, selfPath); @@ -165,6 +171,7 @@ internal static class ScopeAccessorFactory /// /// The script runtime context. /// The canonical-name path. + /// A new rooted at . public static ChildrenAccessor ChildrenFor(ScriptRuntimeContext ctx, string selfPath) => new(ctx, selfPath); @@ -173,6 +180,7 @@ internal static class ScopeAccessorFactory /// /// The script runtime context. /// The parent path, or null if no parent. + /// A for the parent, or null when is null. public static CompositionAccessor? ParentFor(ScriptRuntimeContext ctx, string? parentPath) => parentPath == null ? null : new CompositionAccessor(ctx, parentPath); } diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptCompilationService.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptCompilationService.cs index f1b65d3a..68f71779 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptCompilationService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptCompilationService.cs @@ -69,6 +69,7 @@ public class ScriptCompilationService /// Returns a list of violation messages, empty if clean. /// /// The script code to validate. + /// A list of trust-model violation messages; empty if the script is clean. public IReadOnlyList ValidateTrustModel(string code) { var tree = CSharpSyntaxTree.ParseText( @@ -243,6 +244,7 @@ public class ScriptCompilationService /// /// The name of the script. /// The script code to compile. + /// A containing the compiled script on success, or error messages on failure. public ScriptCompilationResult Compile(string scriptName, string code) => CompileCore(scriptName, code, typeof(ScriptGlobals)); @@ -255,6 +257,7 @@ public class ScriptCompilationService /// /// The name of the trigger expression. /// The trigger expression to compile. + /// A containing the compiled expression on success, or error messages on failure. public ScriptCompilationResult CompileTriggerExpression(string name, string expression) => CompileCore(name, expression, typeof(TriggerExpressionGlobals)); @@ -327,11 +330,13 @@ public class ScriptCompilationResult /// Creates a successful compilation result. /// The compiled script. + /// A with set to true and the compiled script attached. public static ScriptCompilationResult Succeeded(Script script) => new(true, script, []); /// Creates a failed compilation result. /// List of error messages. + /// A with set to false and the provided error messages. public static ScriptCompilationResult Failed(IReadOnlyList errors) => new(false, null, errors); } diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptExecutionScheduler.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptExecutionScheduler.cs index 22001219..5d8133d0 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptExecutionScheduler.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptExecutionScheduler.cs @@ -31,6 +31,7 @@ public sealed class ScriptExecutionScheduler : TaskScheduler, IDisposable /// first caller wins, subsequent calls reuse the existing instance. /// /// Site runtime options supplying the thread count for the scheduler. + /// The process-wide instance, creating it on first call. public static ScriptExecutionScheduler Shared(SiteRuntimeOptions options) { if (_shared != null) diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRuntimeContext.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRuntimeContext.cs index 94b775f5..e52672c5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRuntimeContext.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRuntimeContext.cs @@ -266,6 +266,7 @@ public class ScriptRuntimeContext /// /// Name of the attribute to set. /// String value to set for the attribute. + /// A task that represents the asynchronous operation. public async Task SetAttribute(string attributeName, string value) { var correlationId = Guid.NewGuid().ToString(); diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/SharedScriptLibrary.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/SharedScriptLibrary.cs index f65c4817..204c4209 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/SharedScriptLibrary.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/SharedScriptLibrary.cs @@ -36,6 +36,7 @@ public class SharedScriptLibrary /// /// Unique name for the shared script. /// C# source code of the shared script. + /// true if compilation succeeded and the script was registered; false if compilation failed. public bool CompileAndRegister(string name, string code) { var result = _compilationService.Compile(name, code); @@ -60,6 +61,7 @@ public class SharedScriptLibrary /// Removes a shared script from the library. /// /// Name of the shared script to remove. + /// true if the script was found and removed; false if no script with that name was registered. public bool Remove(string name) { lock (_lock) @@ -76,6 +78,7 @@ public class SharedScriptLibrary /// Runtime context providing instance state and services to the script globals. /// Optional input parameters passed to the script. /// Cancellation token for the execution. + /// A task that resolves to the script's return value, or null if the script returns nothing. public async Task ExecuteAsync( string scriptName, ScriptRuntimeContext context, @@ -106,6 +109,7 @@ public class SharedScriptLibrary /// /// Returns the names of all currently registered shared scripts. /// + /// A snapshot list of all registered script names at the time of the call. public IReadOnlyList GetRegisteredScriptNames() { lock (_lock) @@ -118,6 +122,7 @@ public class SharedScriptLibrary /// Returns whether a script with the given name is registered. /// /// Name of the shared script to look up. + /// true if a script with the given name is registered; otherwise false. public bool Contains(string name) { lock (_lock) diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/TriggerExpressionGlobals.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/TriggerExpressionGlobals.cs index 7928251d..9c17e9f8 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/TriggerExpressionGlobals.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/TriggerExpressionGlobals.cs @@ -20,6 +20,7 @@ public sealed class TriggerExpressionGlobals /// and AlarmActor. /// /// JSON string of the trigger configuration, or null. + /// The expression string, or null if the config is missing, blank, or malformed. public static string? ExtractExpression(string? triggerConfigJson) { if (string.IsNullOrEmpty(triggerConfigJson)) return null; diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/ServiceCollectionExtensions.cs index ec76383f..ca63217a 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/ServiceCollectionExtensions.cs @@ -18,6 +18,7 @@ public static class ServiceCollectionExtensions /// overload with an explicit connection string. /// /// The DI service collection to register services into. + /// The same to allow chaining. public static IServiceCollection AddSiteRuntime(this IServiceCollection services) { // SiteStorageService is registered by the Host using AddSiteRuntime(connectionString) @@ -30,6 +31,7 @@ public static class ServiceCollectionExtensions /// /// The DI service collection to register services into. /// The SQLite connection string for the site local storage database. + /// The same to allow chaining. public static IServiceCollection AddSiteRuntime(this IServiceCollection services, string siteDbConnectionString) { services.AddSingleton(sp => @@ -66,6 +68,7 @@ public static class ServiceCollectionExtensions /// Registers any additional DI services needed by the Site Runtime Akka actors. /// The DI service collection to register services into. + /// The same to allow chaining. public static IServiceCollection AddSiteRuntimeActors(this IServiceCollection services) { // Actor registration is handled by AkkaHostedService.RegisterSiteActors() diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs index 6b4be05c..8cec600b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs @@ -400,6 +400,7 @@ public class OperationTrackingStore : IOperationTrackingStore, IAsyncDisposable, /// connection, so a write currently executing a SqliteCommand completes /// before the connection is freed. /// + /// A that completes when all resources have been released. public async ValueTask DisposeAsync() { if (Interlocked.Exchange(ref _disposeState, 1) != 0) diff --git a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/NotificationForwarder.cs b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/NotificationForwarder.cs index a3b14669..0e3408cf 100644 --- a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/NotificationForwarder.cs +++ b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/NotificationForwarder.cs @@ -35,6 +35,10 @@ public sealed class NotificationForwarder private readonly TimeSpan _forwardTimeout; private readonly ILogger _logger; + /// + /// Initializes a new that forwards buffered + /// notifications to the central cluster via the site communication actor. + /// /// /// The site communication actor. It forwards a to /// central via the registered ClusterClient and replies with the @@ -69,6 +73,7 @@ public sealed class NotificationForwarder /// non-accepted ack or an Ask timeout/failure so the engine retries. /// /// The buffered store-and-forward message to deliver to central. + /// A task that resolves to true when central accepts (or the payload is corrupt and discarded); throws on a transient forward failure so the engine retries. public async Task DeliverAsync(StoreAndForwardMessage message) { // StoreAndForward-018: an unreadable payload cannot be fixed by retrying. diff --git a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ReplicationService.cs b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ReplicationService.cs index c183b6b9..2a1a2f95 100644 --- a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ReplicationService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ReplicationService.cs @@ -103,6 +103,7 @@ public class ReplicationService /// /// The replication operation to apply. /// The standby node's store-and-forward storage to update. + /// A task representing the asynchronous apply operation. public async Task ApplyReplicatedOperationAsync( ReplicationOperation operation, StoreAndForwardStorage storage) diff --git a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ServiceCollectionExtensions.cs b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ServiceCollectionExtensions.cs index 77da6516..e0cf2a46 100644 --- a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ServiceCollectionExtensions.cs +++ b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/ServiceCollectionExtensions.cs @@ -11,6 +11,7 @@ public static class ServiceCollectionExtensions /// Registers Store-and-Forward services including storage, the delivery service, and the replication service. /// /// The service collection to register into. + /// The same collection, for chaining. public static IServiceCollection AddStoreAndForward(this IServiceCollection services) { services.AddSingleton(sp => @@ -71,6 +72,7 @@ public static class ServiceCollectionExtensions /// Registers Store-and-Forward Akka actor bindings. Actor creation is handled by the Host during actor system startup. /// /// The service collection to register into. + /// The same collection, for chaining. public static IServiceCollection AddStoreAndForwardActors(this IServiceCollection services) { // Akka actor registration handled by Host component during actor system startup diff --git a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardService.cs b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardService.cs index 36cf4702..6b082579 100644 --- a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardService.cs @@ -210,6 +210,7 @@ public class StoreAndForwardService /// /// Initializes storage and starts the background retry timer. /// + /// A task representing the asynchronous start operation. public async Task StartAsync() { await _storage.InitializeAsync(); @@ -265,6 +266,7 @@ public class StoreAndForwardService /// (with a bounded so a hung /// dependency cannot block host shutdown indefinitely) before returning. /// + /// A task representing the asynchronous stop operation. public async Task StopAsync() { if (_retryTimer != null) @@ -371,6 +373,7 @@ public class StoreAndForwardService /// non-routed run and for callers (notifications, pre-Task-6 callers) that /// do not supply one. /// + /// A task that resolves to a result indicating whether the message was delivered or buffered. public async Task EnqueueAsync( StoreAndForwardCategory category, string target, @@ -469,6 +472,7 @@ public class StoreAndForwardService /// /// WP-10: Background retry sweep. Processes all pending messages that are due for retry. /// + /// A task representing the asynchronous retry sweep. internal async Task RetryPendingMessagesAsync() { // Prevent overlapping retry sweeps diff --git a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardStorage.cs b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardStorage.cs index b19cb77c..3b353502 100644 --- a/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardStorage.cs +++ b/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardStorage.cs @@ -41,6 +41,7 @@ public class StoreAndForwardStorage /// /// Creates the sf_messages table if it does not exist. /// + /// A task that represents the asynchronous operation. public async Task InitializeAsync() { EnsureDatabaseDirectoryExists(); @@ -145,6 +146,7 @@ public class StoreAndForwardStorage /// WP-9: Enqueues a new message with Pending status. /// /// The message to enqueue. + /// A task that represents the asynchronous operation. public async Task EnqueueAsync(StoreAndForwardMessage message) { await using var connection = new SqliteConnection(_connectionString); @@ -190,6 +192,7 @@ public class StoreAndForwardStorage /// /// WP-10: Gets all messages that are due for retry (Pending status, last attempt older than retry interval). /// + /// A task that resolves to the list of messages due for retry, ordered by creation time ascending. public async Task> GetMessagesForRetryAsync() { await using var connection = new SqliteConnection(_connectionString); @@ -216,6 +219,7 @@ public class StoreAndForwardStorage /// WP-10: Updates a message after a delivery attempt. /// /// The message with updated retry count, status, and last error. + /// A task that represents the asynchronous operation. public async Task UpdateMessageAsync(StoreAndForwardMessage message) { await using var connection = new SqliteConnection(_connectionString); @@ -255,6 +259,7 @@ public class StoreAndForwardStorage /// /// The message with the updated values to persist. /// The status the row must currently have for the update to proceed. + /// A task that resolves to true if the row was updated; false if its status had already changed. public async Task UpdateMessageIfStatusAsync( StoreAndForwardMessage message, StoreAndForwardMessageStatus expectedStatus) @@ -287,6 +292,7 @@ public class StoreAndForwardStorage /// WP-10: Removes a successfully delivered message. /// /// The id of the message to remove. + /// A task that represents the asynchronous operation. public async Task RemoveMessageAsync(string messageId) { await using var connection = new SqliteConnection(_connectionString); @@ -311,6 +317,7 @@ public class StoreAndForwardStorage /// Optional category filter; null returns parked messages from all categories. /// 1-based page number. /// Maximum number of messages to return per page. + /// A task that resolves to the page of parked messages and the total count of matching rows. public async Task<(List Messages, int TotalCount)> GetParkedMessagesAsync( StoreAndForwardCategory? category = null, int pageNumber = 1, @@ -366,6 +373,7 @@ public class StoreAndForwardStorage /// by accident, and a long interval would instead delay the operator's retry. /// /// The id of the parked message to move back to Pending. + /// A task that resolves to true if the message was found and reset to Pending; false if not found or not in Parked status. public async Task RetryParkedMessageAsync(string messageId) { await using var connection = new SqliteConnection(_connectionString); @@ -389,6 +397,7 @@ public class StoreAndForwardStorage /// WP-12: Permanently discards a parked message. /// /// The id of the parked message to discard. + /// A task that resolves to true if the message was found and deleted; false if not found or not in Parked status. public async Task DiscardParkedMessageAsync(string messageId) { await using var connection = new SqliteConnection(_connectionString); @@ -406,6 +415,7 @@ public class StoreAndForwardStorage /// /// WP-14: Gets buffer depth by category (count of pending messages per category). /// + /// A task that resolves to a dictionary mapping each category to its pending message count. public async Task> GetBufferDepthByCategoryAsync() { await using var connection = new SqliteConnection(_connectionString); @@ -436,6 +446,7 @@ public class StoreAndForwardStorage /// Returns the count of messages for a given origin instance. /// /// The origin instance name to count messages for. + /// A task that resolves to the number of messages whose origin instance matches . public async Task GetMessageCountByOriginInstanceAsync(string instanceName) { await using var connection = new SqliteConnection(_connectionString); @@ -455,6 +466,7 @@ public class StoreAndForwardStorage /// Gets a message by ID. /// /// The id of the message to retrieve. + /// A task that resolves to the matching message, or null if not found. public async Task GetMessageByIdAsync(string messageId) { await using var connection = new SqliteConnection(_connectionString); @@ -476,6 +488,7 @@ public class StoreAndForwardStorage /// /// Gets the count of parked messages (for health reporting). /// + /// A task that resolves to the number of messages currently in Parked status. public async Task GetParkedMessageCountAsync() { await using var conn = new SqliteConnection(_connectionString); @@ -491,6 +504,7 @@ public class StoreAndForwardStorage /// Gets total message count by status. /// /// The status to filter by. + /// A task that resolves to the count of messages with the specified status. public async Task GetMessageCountByStatusAsync(StoreAndForwardMessageStatus status) { await using var connection = new SqliteConnection(_connectionString); diff --git a/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/CycleDetector.cs b/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/CycleDetector.cs index ef38aa72..f5ce6943 100644 --- a/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/CycleDetector.cs +++ b/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/CycleDetector.cs @@ -17,6 +17,7 @@ public static class CycleDetector /// A plain ToDictionary(t => t.Id) would instead throw ArgumentException. /// /// All templates to build lookup from. + /// A dictionary keyed by template Id; on duplicate Ids the first occurrence wins. internal static Dictionary BuildLookup(IReadOnlyList