feat(telemetry): add telemetry client and services for tracking events

- Implemented TelemetryClient to handle event queuing and flushing to the telemetry endpoint.
- Created TtfsTelemetryService for emitting specific telemetry events related to TTFS.
- Added tests for TelemetryClient to ensure event queuing and flushing functionality.
- Introduced models for reachability drift detection, including DriftResult and DriftedSink.
- Developed DriftApiService for interacting with the drift detection API.
- Updated FirstSignalCardComponent to emit telemetry events on signal appearance.
- Enhanced localization support for first signal component with i18n strings.
This commit is contained in:
master
2025-12-18 16:19:16 +02:00
parent 00d2c99af9
commit 811f35cba7
114 changed files with 13702 additions and 268 deletions

View File

@@ -0,0 +1,86 @@
using System.CommandLine;
using StellaOps.Cli.Extensions;
namespace StellaOps.Cli.Commands;
internal static class VerifyCommandGroup
{
internal static Command BuildVerifyCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var verify = new Command("verify", "Verification commands (offline-first).");
verify.Add(BuildVerifyOfflineCommand(services, verboseOption, cancellationToken));
return verify;
}
private static Command BuildVerifyOfflineCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var evidenceDirOption = new Option<string>("--evidence-dir")
{
Description = "Path to offline evidence directory (contains keys/, policy/, sboms/, attestations/, tlog/).",
Required = true
};
var artifactOption = new Option<string>("--artifact")
{
Description = "Artifact digest to verify (sha256:<hex>).",
Required = true
};
var policyOption = new Option<string>("--policy")
{
Description = "Policy file path (YAML or JSON). If relative, resolves under evidence-dir.",
Required = true
};
var outputDirOption = new Option<string?>("--output-dir")
{
Description = "Directory to write deterministic reconciliation outputs."
};
var outputOption = new Option<string?>("--output", new[] { "-o" })
{
Description = "Output format: table (default), json."
}.SetDefaultValue("table").FromAmong("table", "json");
var command = new Command("offline", "Verify offline evidence for a specific artifact.")
{
evidenceDirOption,
artifactOption,
policyOption,
outputDirOption,
outputOption,
verboseOption
};
command.SetAction(parseResult =>
{
var evidenceDir = parseResult.GetValue(evidenceDirOption) ?? string.Empty;
var artifact = parseResult.GetValue(artifactOption) ?? string.Empty;
var policy = parseResult.GetValue(policyOption) ?? string.Empty;
var outputDir = parseResult.GetValue(outputDirOption);
var outputFormat = parseResult.GetValue(outputOption) ?? "table";
var verbose = parseResult.GetValue(verboseOption);
return CommandHandlers.HandleVerifyOfflineAsync(
services,
evidenceDir,
artifact,
policy,
outputDir,
outputFormat,
verbose,
cancellationToken);
});
return command;
}
}