docs: add XML doc comments across src + Sister Projects section in CLAUDE.md

Bulk CommentChecker pass: fills in <param>/<inheritdoc> tags on public
APIs across all 23 src/ projects so the doc-coverage gate is green. Also
adds a Sister Projects section to CLAUDE.md pointing at the MxAccess
Gateway and OtOpcUa sibling repos, and gitignores local credential
captures (*login*.txt) and the wonder-app-vd03 deploy/ artifacts.
This commit is contained in:
Joseph Doherty
2026-05-28 01:55:24 -04:00
parent 6731845473
commit 1eb6e972b0
381 changed files with 5788 additions and 532 deletions
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class ApiMethodCommands
{
/// <summary>
/// Builds the <c>api-method</c> CLI command group with subcommands for managing inbound API methods.
/// </summary>
/// <param name="urlOption">Global option for the management URL.</param>
/// <param name="formatOption">Global option for the output format.</param>
/// <param name="usernameOption">Global option for the authentication username.</param>
/// <param name="passwordOption">Global option for the authentication password.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("api-method") { Description = "Manage inbound API methods" };
@@ -9,12 +9,37 @@ namespace ScadaLink.CLI.Commands;
/// </summary>
public sealed class AuditConnection
{
/// <summary>
/// The management URL, or null if resolution failed.
/// </summary>
public string? Url { get; init; }
/// <summary>
/// The username for authentication, or null if resolution failed.
/// </summary>
public string? Username { get; init; }
/// <summary>
/// The password for authentication, or null if resolution failed.
/// </summary>
public string? Password { get; init; }
/// <summary>
/// Error message if resolution failed, or null.
/// </summary>
public string? Error { get; init; }
/// <summary>
/// Error code if resolution failed, or null.
/// </summary>
public string? ErrorCode { get; init; }
/// <summary>
/// Creates a failed connection with an error message and code.
/// </summary>
/// <param name="error">The error message.</param>
/// <param name="code">The error code.</param>
/// <returns>A failed AuditConnection.</returns>
public static AuditConnection Fail(string error, string code)
=> new() { Error = error, ErrorCode = code };
}
@@ -28,6 +53,14 @@ public sealed class AuditConnection
/// </summary>
public static class AuditCommandHelpers
{
/// <summary>
/// Resolves management API connection details from command line arguments, config file, or environment variables.
/// </summary>
/// <param name="result">The parsed command line arguments.</param>
/// <param name="urlOption">The URL option.</param>
/// <param name="usernameOption">The username option.</param>
/// <param name="passwordOption">The password option.</param>
/// <returns>The resolved connection details, or a failure result.</returns>
public static AuditConnection ResolveConnection(
ParseResult result,
Option<string> urlOption,
@@ -67,6 +100,12 @@ public static class AuditCommandHelpers
return new AuditConnection { Url = url, Username = username, Password = password };
}
/// <summary>
/// Resolves the output format from command line arguments, config file, or defaults to "table".
/// </summary>
/// <param name="result">The parsed command line arguments.</param>
/// <param name="formatOption">The format option.</param>
/// <returns>The resolved format string.</returns>
public static string ResolveFormat(ParseResult result, Option<string> formatOption)
=> CommandHelpers.ResolveFormat(result, formatOption, CliConfig.Load());
}
@@ -11,6 +11,13 @@ namespace ScadaLink.CLI.Commands;
/// </summary>
public static class AuditCommands
{
/// <summary>
/// Builds the <c>audit</c> command group with query, export, and verify-chain sub-commands.
/// </summary>
/// <param name="urlOption">Global <c>--url</c> option for the management API endpoint.</param>
/// <param name="formatOption">Global <c>--format</c> option for output format.</param>
/// <param name="usernameOption">Global <c>--username</c> option for authentication.</param>
/// <param name="passwordOption">Global <c>--password</c> option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("audit") { Description = "Query and export the centralized audit log" };
@@ -13,15 +13,45 @@ namespace ScadaLink.CLI.Commands;
/// </summary>
public sealed class AuditExportArgs
{
/// <summary>
/// Start timestamp for the export time window.
/// </summary>
public string Since { get; set; } = string.Empty;
/// <summary>
/// End timestamp for the export time window.
/// </summary>
public string Until { get; set; } = string.Empty;
/// <summary>
/// Export format (e.g., 'json', 'csv', 'parquet').
/// </summary>
public string Format { get; set; } = string.Empty;
/// <summary>
/// Output file path for the exported audit log.
/// </summary>
public string Output { get; set; } = string.Empty;
/// <summary>
/// Channel filter values (repeated query parameter).
/// </summary>
public string[] Channel { get; set; } = Array.Empty<string>();
/// <summary>
/// Kind filter values (repeated query parameter).
/// </summary>
public string[] Kind { get; set; } = Array.Empty<string>();
/// <summary>
/// Status filter values (repeated query parameter).
/// </summary>
public string[] Status { get; set; } = Array.Empty<string>();
/// <summary>
/// Site identifier filter values (repeated query parameter).
/// </summary>
public string[] Site { get; set; } = Array.Empty<string>();
/// <summary>
/// Optional target system filter.
/// </summary>
public string? Target { get; set; }
/// <summary>
/// Optional actor/user filter.
/// </summary>
public string? Actor { get; set; }
}
@@ -41,6 +71,8 @@ public static class AuditExportHelpers
/// server's multi-value <c>IN (…)</c> filter receives the full set — mirroring
/// <see cref="AuditQueryHelpers.BuildQueryString"/>.
/// </summary>
/// <param name="args">The export arguments containing filters and format.</param>
/// <param name="now">The current time for resolving relative time specifications.</param>
public static string BuildQueryString(AuditExportArgs args, DateTimeOffset now)
{
var parts = new List<string>();
@@ -79,6 +111,10 @@ public static class AuditExportHelpers
/// A <c>501 Not Implemented</c> (parquet not yet supported server-side) prints the
/// server message and returns a non-zero exit code.
/// </summary>
/// <param name="client">The management HTTP client for API communication.</param>
/// <param name="args">The export arguments containing filters and output file path.</param>
/// <param name="output">Text writer for command output messages.</param>
/// <param name="now">The current time for resolving relative time specifications.</param>
public static async Task<int> RunExportAsync(
ManagementHttpClient client, AuditExportArgs args, TextWriter output, DateTimeOffset now)
{
@@ -10,6 +10,8 @@ namespace ScadaLink.CLI.Commands;
public interface IAuditFormatter
{
/// <summary>Renders one page of events. Called once per fetched page.</summary>
/// <param name="events">The audit events on this page.</param>
/// <param name="output">Writer to render the formatted output to.</param>
void WritePage(IReadOnlyList<JsonElement> events, TextWriter output);
}
@@ -21,6 +23,7 @@ public sealed class JsonLinesAuditFormatter : IAuditFormatter
{
private static readonly JsonSerializerOptions Compact = new() { WriteIndented = false };
/// <inheritdoc />
public void WritePage(IReadOnlyList<JsonElement> events, TextWriter output)
{
foreach (var evt in events)
@@ -35,6 +38,11 @@ public sealed class JsonLinesAuditFormatter : IAuditFormatter
/// </summary>
public static class AuditFormatterFactory
{
/// <summary>
/// Returns an <see cref="IAuditFormatter"/> for the given format name.
/// </summary>
/// <param name="format">Format name; <c>table</c> selects the table formatter, any other value selects JSONL.</param>
/// <param name="notices">Writer for notice messages emitted during formatting.</param>
public static IAuditFormatter Create(string format, TextWriter notices)
{
if (string.Equals(format, "table", StringComparison.OrdinalIgnoreCase))
@@ -32,6 +32,8 @@ public static class AuditLogCommands
/// an alias of <c>audit-config</c> — so this only adds the migration warning.
/// Factored out of <c>Program.cs</c> so it is unit-testable without spawning a process.
/// </summary>
/// <param name="args">The raw command-line arguments passed to the CLI.</param>
/// <param name="stderr">The text writer to emit the deprecation warning to.</param>
public static void WriteDeprecationWarningIfNeeded(string[] args, TextWriter stderr)
{
if (args.Length > 0
@@ -41,6 +43,13 @@ public static class AuditLogCommands
}
}
/// <summary>
/// Builds the <c>audit-config</c> command (with the deprecated <c>audit-log</c> alias) and its subcommands.
/// </summary>
/// <param name="urlOption">Global management URL option.</param>
/// <param name="formatOption">Global output format option.</param>
/// <param name="usernameOption">Global username option.</param>
/// <param name="passwordOption">Global password option.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("audit-config") { Description = "Query the configuration-change audit log" };
@@ -15,18 +15,31 @@ namespace ScadaLink.CLI.Commands;
/// </summary>
public sealed class AuditQueryArgs
{
/// <summary>Start time spec (relative like 1h, or absolute ISO-8601).</summary>
public string? Since { get; set; }
/// <summary>End time spec (relative like 7d, or absolute ISO-8601).</summary>
public string? Until { get; set; }
/// <summary>Multi-valued channel filter.</summary>
public string[] Channel { get; set; } = Array.Empty<string>();
/// <summary>Multi-valued audit event kind filter.</summary>
public string[] Kind { get; set; } = Array.Empty<string>();
/// <summary>Multi-valued status filter.</summary>
public string[] Status { get; set; } = Array.Empty<string>();
/// <summary>Multi-valued site ID filter.</summary>
public string[] Site { get; set; } = Array.Empty<string>();
/// <summary>Target system or service filter.</summary>
public string? Target { get; set; }
/// <summary>Actor (user or system) filter.</summary>
public string? Actor { get; set; }
/// <summary>Operation correlation ID filter.</summary>
public string? CorrelationId { get; set; }
/// <summary>Script execution ID filter.</summary>
public string? ExecutionId { get; set; }
/// <summary>Parent execution ID filter.</summary>
public string? ParentExecutionId { get; set; }
/// <summary>Filter for errors only (status=Failed).</summary>
public bool ErrorsOnly { get; set; }
/// <summary>Page size for pagination.</summary>
public int PageSize { get; set; } = 100;
}
@@ -45,6 +58,8 @@ public static class AuditQueryHelpers
/// relative offset (<c>30s</c>, <c>15m</c>, <c>1h</c>, <c>7d</c>) interpreted as
/// <paramref name="now"/> minus the offset, or an absolute ISO-8601 timestamp.
/// </summary>
/// <param name="spec">The time specification string.</param>
/// <param name="now">The current time used as reference for relative specs.</param>
/// <exception cref="FormatException">The spec is neither a known relative form nor a parseable ISO-8601 timestamp.</exception>
public static DateTimeOffset ResolveTimeSpec(string spec, DateTimeOffset now)
{
@@ -84,6 +99,10 @@ public static class AuditQueryHelpers
/// server's multi-value <c>IN (…)</c> filter receives the full set. <c>--errors-only</c>
/// maps to a single <c>status=Failed</c> and overrides any explicit <c>--status</c>.
/// </summary>
/// <param name="args">The audit query arguments.</param>
/// <param name="now">The current time for resolving relative time specs.</param>
/// <param name="afterOccurredAtUtc">Optional keyset cursor timestamp.</param>
/// <param name="afterEventId">Optional keyset cursor event ID.</param>
public static string BuildQueryString(
AuditQueryArgs args, DateTimeOffset now, DateTimeOffset? afterOccurredAtUtc, string? afterEventId)
{
@@ -144,6 +163,12 @@ public static class AuditQueryHelpers
/// follows <c>nextCursor</c> until the server returns a null cursor. Returns the
/// process exit code (0 success, non-zero on HTTP/transport error).
/// </summary>
/// <param name="client">The management HTTP client.</param>
/// <param name="args">The audit query arguments.</param>
/// <param name="fetchAll">Whether to follow pagination cursors.</param>
/// <param name="formatter">The audit result formatter.</param>
/// <param name="output">The output writer for results.</param>
/// <param name="now">The current time for resolving relative time specs.</param>
public static async Task<int> RunQueryAsync(
ManagementHttpClient client,
AuditQueryArgs args,
@@ -13,6 +13,7 @@ public static class AuditVerifyChainHelpers
/// Returns true if <paramref name="month"/> is a well-formed <c>YYYY-MM</c> value
/// with a real month (01-12). A malformed month (e.g. <c>2026-13</c>) is rejected.
/// </summary>
/// <param name="month">The month string to validate in YYYY-MM format.</param>
public static bool IsValidMonth(string? month)
=> !string.IsNullOrWhiteSpace(month)
&& DateTime.TryParseExact(month, "yyyy-MM", CultureInfo.InvariantCulture,
@@ -15,6 +15,12 @@ public static class BundleCommands
{
private static readonly TimeSpan BundleCommandTimeout = TimeSpan.FromMinutes(5);
/// <summary>Builds the <c>bundle</c> command group with export, preview, and import sub-commands.</summary>
/// <param name="urlOption">Shared management URL option.</param>
/// <param name="formatOption">Shared output format option.</param>
/// <param name="usernameOption">Shared username option.</param>
/// <param name="passwordOption">Shared password option.</param>
/// <returns>The configured <see cref="Command"/> for the bundle group.</returns>
public static Command Build(
Option<string> urlOption, Option<string> formatOption,
Option<string> usernameOption, Option<string> passwordOption)
@@ -7,6 +7,16 @@ namespace ScadaLink.CLI.Commands;
internal static class CommandHelpers
{
/// <summary>
/// Resolves the management URL, credentials, and output format, then sends <paramref name="command"/>
/// to the management API and returns the process exit code.
/// </summary>
/// <param name="result">Parsed command-line result from which option values are read.</param>
/// <param name="urlOption">Option that supplies the management URL override.</param>
/// <param name="formatOption">Option that supplies the output format override.</param>
/// <param name="usernameOption">Option that supplies the username override.</param>
/// <param name="passwordOption">Option that supplies the password override.</param>
/// <param name="command">The management command object to send.</param>
internal static async Task<int> ExecuteCommandAsync(
ParseResult result,
Option<string> urlOption,
@@ -69,6 +79,9 @@ internal static class CommandHelpers
/// is used, otherwise <c>json</c>. The <c>--format</c> option must not declare a
/// <c>DefaultValueFactory</c> — that would mask whether the flag was supplied.
/// </summary>
/// <param name="result">Parsed command-line result.</param>
/// <param name="formatOption">The <c>--format</c> option definition.</param>
/// <param name="config">Loaded CLI configuration providing the default format fallback.</param>
internal static string ResolveFormat(ParseResult result, Option<string> formatOption, CliConfig config)
{
// GetResult returns non-null only when the option was actually present on the
@@ -87,6 +100,8 @@ internal static class CommandHelpers
/// Resolves a single credential: an explicit command-line value wins, otherwise the
/// environment-variable fallback (from <see cref="CliConfig"/>) is used.
/// </summary>
/// <param name="commandLineValue">Value supplied on the command line, or null if absent.</param>
/// <param name="envValue">Fallback value from the config file or environment variable.</param>
internal static string? ResolveCredential(string? commandLineValue, string? envValue)
=> string.IsNullOrWhiteSpace(commandLineValue) ? envValue : commandLineValue;
@@ -96,6 +111,7 @@ internal static class CommandHelpers
/// <c>new Uri(...)</c> in the <see cref="ManagementHttpClient"/> constructor and throw
/// an unhandled <see cref="UriFormatException"/>.
/// </summary>
/// <param name="url">URL string to validate.</param>
internal static bool IsValidManagementUrl(string? url)
{
if (string.IsNullOrWhiteSpace(url))
@@ -105,6 +121,11 @@ internal static class CommandHelpers
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps);
}
/// <summary>
/// Writes the management response to stdout and returns the appropriate process exit code.
/// </summary>
/// <param name="response">Response received from the management API.</param>
/// <param name="format">Output format (<c>json</c> or <c>table</c>).</param>
internal static int HandleResponse(ManagementResponse response, string format)
{
if (response.JsonData != null)
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class DataConnectionCommands
{
/// <summary>
/// Builds the <c>data-connection</c> command group and all its subcommands.
/// </summary>
/// <param name="urlOption">Global management URL option.</param>
/// <param name="formatOption">Global output format option.</param>
/// <param name="usernameOption">Global username option.</param>
/// <param name="passwordOption">Global password option.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("data-connection") { Description = "Manage data connections" };
@@ -4,8 +4,17 @@ using ScadaLink.Commons.Messages.Management;
namespace ScadaLink.CLI.Commands;
/// <summary>
/// CLI commands for managing database connection definitions.
/// </summary>
public static class DbConnectionCommands
{
/// <summary>Builds the <c>db-connection</c> command with list, get, create, update, and delete sub-commands.</summary>
/// <param name="urlOption">Global URL option.</param>
/// <param name="formatOption">Global output format option.</param>
/// <param name="usernameOption">Global username option.</param>
/// <param name="passwordOption">Global password option.</param>
/// <returns>The configured <c>db-connection</c> command.</returns>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("db-connection") { Description = "Manage database connections" };
@@ -10,6 +10,11 @@ namespace ScadaLink.CLI.Commands;
public static class DebugCommands
{
/// <summary>Builds the <c>debug</c> command with its subcommands using the given shared CLI options.</summary>
/// <param name="urlOption">Shared management URL option.</param>
/// <param name="formatOption">Shared output format option.</param>
/// <param name="usernameOption">Shared username option for authentication.</param>
/// <param name="passwordOption">Shared password option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("debug") { Description = "Runtime debugging" };
@@ -25,6 +25,8 @@ internal static class DebugStreamHelpers
/// (Ctrl+C during connect) is a graceful shutdown — exit 0, no error printed.
/// Anything else is a genuine connection failure — exit 1.
/// </summary>
/// <param name="ex">The exception thrown by HubConnection.StartAsync.</param>
/// <param name="cancellationRequested">True when the user requested cancellation (Ctrl+C) before the exception was thrown.</param>
internal static ConnectFailure ClassifyConnectFailure(Exception ex, bool cancellationRequested)
{
if (cancellationRequested && ex is OperationCanceledException)
@@ -40,6 +42,7 @@ internal static class DebugStreamHelpers
/// a brief grace period covers a termination that races with cancellation. If no
/// result is ever produced (pure Ctrl+C), the stream ended gracefully — exit 0.
/// </summary>
/// <param name="exitTask">The task whose result is the intended exit code, set by OnStreamTerminated or the Closed handler.</param>
internal static async Task<int> ResolveStreamExitCodeAsync(Task<int> exitTask)
{
if (exitTask.IsCompletedSuccessfully)
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class DeployCommands
{
/// <summary>
/// Builds the <c>deploy</c> command group with all sub-commands.
/// </summary>
/// <param name="urlOption">Global management URL option.</param>
/// <param name="formatOption">Global output format option.</param>
/// <param name="usernameOption">Global username option.</param>
/// <param name="passwordOption">Global password option.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("deploy") { Description = "Deployment operations" };
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class ExternalSystemCommands
{
/// <summary>
/// Builds the <c>external-system</c> CLI command group with subcommands for managing external systems.
/// </summary>
/// <param name="urlOption">Global option for the management URL.</param>
/// <param name="formatOption">Global option for the output format.</param>
/// <param name="usernameOption">Global option for the authentication username.</param>
/// <param name="passwordOption">Global option for the authentication password.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("external-system") { Description = "Manage external systems" };
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class HealthCommands
{
/// <summary>
/// Builds the <c>health</c> command group with summary, site, event-log, and parked-message sub-commands.
/// </summary>
/// <param name="urlOption">Global <c>--url</c> option for the management API endpoint.</param>
/// <param name="formatOption">Global <c>--format</c> option for output format.</param>
/// <param name="usernameOption">Global <c>--username</c> option for authentication.</param>
/// <param name="passwordOption">Global <c>--password</c> option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("health") { Description = "Health monitoring" };
@@ -6,6 +6,14 @@ namespace ScadaLink.CLI.Commands;
public static class InstanceCommands
{
/// <summary>
/// Builds the instance command and its subcommands.
/// </summary>
/// <param name="urlOption">The URL option.</param>
/// <param name="formatOption">The format option.</param>
/// <param name="usernameOption">The username option.</param>
/// <param name="passwordOption">The password option.</param>
/// <returns>The instance command with all subcommands.</returns>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("instance") { Description = "Manage instances" };
@@ -71,6 +79,10 @@ public static class InstanceCommands
/// throwing when the JSON is malformed, a pair has the wrong arity, or an element
/// has the wrong type.
/// </summary>
/// <param name="json">The JSON string to parse.</param>
/// <param name="bindings">The parsed bindings list, or null if parsing fails.</param>
/// <param name="error">The error message if parsing fails, or null on success.</param>
/// <returns>True if parsing succeeded; false otherwise.</returns>
internal static bool TryParseBindings(
string json,
out List<ConnectionBinding>? bindings,
@@ -126,6 +138,10 @@ public static class InstanceCommands
/// <c>false</c> with a descriptive <paramref name="error"/> instead of throwing
/// when the JSON is malformed or null.
/// </summary>
/// <param name="json">The JSON string to parse.</param>
/// <param name="overrides">The parsed overrides dictionary, or null if parsing fails.</param>
/// <param name="error">The error message if parsing fails, or null on success.</param>
/// <returns>True if parsing succeeded; false otherwise.</returns>
internal static bool TryParseOverrides(
string json,
out Dictionary<string, string?>? overrides,
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class NotificationCommands
{
/// <summary>
/// Builds the <c>notification</c> command group with sub-commands for managing notification lists and SMTP configuration.
/// </summary>
/// <param name="urlOption">Global <c>--url</c> option for the management API endpoint.</param>
/// <param name="formatOption">Global <c>--format</c> option for output format.</param>
/// <param name="usernameOption">Global <c>--username</c> option for authentication.</param>
/// <param name="passwordOption">Global <c>--password</c> option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("notification") { Description = "Manage notification lists" };
@@ -123,6 +130,7 @@ public static class NotificationCommands
/// invocation. The optional <c>--tls-mode</c> / <c>--credentials</c> flags map to
/// null when omitted so the server-side handler preserves the existing values.
/// </summary>
/// <param name="result">The parsed command-line result from the <c>smtp update</c> invocation.</param>
internal static UpdateSmtpConfigCommand BuildUpdateSmtpConfigCommand(ParseResult result)
{
var id = result.GetValue(SmtpIdOption);
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class SecurityCommands
{
/// <summary>
/// Builds the <c>security</c> command group with API key, role mapping, and scope rule subcommands.
/// </summary>
/// <param name="urlOption">Shared management URL option.</param>
/// <param name="formatOption">Shared output format option.</param>
/// <param name="usernameOption">Shared username option for authentication.</param>
/// <param name="passwordOption">Shared password option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("security") { Description = "Manage security settings" };
@@ -6,6 +6,12 @@ namespace ScadaLink.CLI.Commands;
public static class SharedScriptCommands
{
/// <summary>Builds the <c>shared-script</c> command group with list, get, create, update, and delete sub-commands.</summary>
/// <param name="urlOption">Shared management URL option.</param>
/// <param name="formatOption">Shared output format option.</param>
/// <param name="usernameOption">Shared username option.</param>
/// <param name="passwordOption">Shared password option.</param>
/// <returns>The configured <see cref="Command"/> for the shared-script group.</returns>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("shared-script") { Description = "Manage shared scripts" };
@@ -6,6 +6,13 @@ namespace ScadaLink.CLI.Commands;
public static class SiteCommands
{
/// <summary>
/// Builds the <c>site</c> command group and all its subcommands.
/// </summary>
/// <param name="urlOption">Global management URL option.</param>
/// <param name="formatOption">Global output format option.</param>
/// <param name="usernameOption">Global username option.</param>
/// <param name="passwordOption">Global password option.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("site") { Description = "Manage sites" };
@@ -28,6 +28,7 @@ public sealed class TableAuditFormatter : IAuditFormatter
("httpStatus", "HttpStatus", 10),
};
/// <inheritdoc />
public void WritePage(IReadOnlyList<JsonElement> events, TextWriter output)
{
// Build every cell first so column widths account for the actual data.
@@ -6,6 +6,11 @@ namespace ScadaLink.CLI.Commands;
public static class TemplateCommands
{
/// <summary>Builds the <c>template</c> command with its subcommands using the given shared CLI options.</summary>
/// <param name="urlOption">Shared management URL option.</param>
/// <param name="formatOption">Shared output format option.</param>
/// <param name="usernameOption">Shared username option for authentication.</param>
/// <param name="passwordOption">Shared password option for authentication.</param>
public static Command Build(Option<string> urlOption, Option<string> formatOption, Option<string> usernameOption, Option<string> passwordOption)
{
var command = new Command("template") { Description = "Manage templates" };