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

@@ -82,6 +82,7 @@ internal static class CommandFactory
root.Add(BuildMirrorCommand(services, verboseOption, cancellationToken));
root.Add(BuildAirgapCommand(services, verboseOption, cancellationToken));
root.Add(OfflineCommandGroup.BuildOfflineCommand(services, verboseOption, cancellationToken));
root.Add(VerifyCommandGroup.BuildVerifyCommand(services, verboseOption, cancellationToken));
root.Add(BuildDevPortalCommand(services, verboseOption, cancellationToken));
root.Add(BuildSymbolsCommand(services, verboseOption, cancellationToken));
root.Add(SystemCommandBuilder.BuildSystemCommand(services, verboseOption, cancellationToken));
@@ -11046,6 +11047,112 @@ internal static class CommandFactory
graph.Add(explain);
// Sprint: SPRINT_3620_0003_0001_cli_graph_verify
// stella graph verify
var verify = new Command("verify", "Verify a reachability graph DSSE attestation.");
var hashOption = new Option<string>("--hash", "-h")
{
Description = "Graph hash to verify (e.g., blake3:a1b2c3...).",
Required = true
};
var includeBundlesOption = new Option<bool>("--include-bundles")
{
Description = "Also verify edge bundles attached to the graph."
};
var specificBundleOption = new Option<string?>("--bundle")
{
Description = "Verify a specific bundle (e.g., bundle:001)."
};
var rekorProofOption = new Option<bool>("--rekor-proof")
{
Description = "Verify Rekor inclusion proof."
};
var casRootOption = new Option<string?>("--cas-root")
{
Description = "Path to offline CAS root for air-gapped verification."
};
var outputFormatOption = new Option<string>("--format")
{
Description = "Output format (text, json, markdown)."
};
outputFormatOption.SetDefaultValue("text");
verify.Add(tenantOption);
verify.Add(hashOption);
verify.Add(includeBundlesOption);
verify.Add(specificBundleOption);
verify.Add(rekorProofOption);
verify.Add(casRootOption);
verify.Add(outputFormatOption);
verify.Add(jsonOption);
verify.Add(verboseOption);
verify.SetAction((parseResult, _) =>
{
var tenant = parseResult.GetValue(tenantOption);
var hash = parseResult.GetValue(hashOption) ?? string.Empty;
var includeBundles = parseResult.GetValue(includeBundlesOption);
var specificBundle = parseResult.GetValue(specificBundleOption);
var verifyRekor = parseResult.GetValue(rekorProofOption);
var casRoot = parseResult.GetValue(casRootOption);
var format = parseResult.GetValue(outputFormatOption);
var emitJson = parseResult.GetValue(jsonOption);
var verbose = parseResult.GetValue(verboseOption);
// JSON option overrides format
if (emitJson)
{
format = "json";
}
return CommandHandlers.HandleGraphVerifyAsync(
services,
tenant,
hash,
includeBundles,
specificBundle,
verifyRekor,
casRoot,
format,
verbose,
cancellationToken);
});
graph.Add(verify);
// stella graph bundles
var bundles = new Command("bundles", "List edge bundles for a graph.");
var bundlesGraphHashOption = new Option<string>("--graph-hash", "-g")
{
Description = "Graph hash to list bundles for.",
Required = true
};
bundles.Add(tenantOption);
bundles.Add(bundlesGraphHashOption);
bundles.Add(jsonOption);
bundles.Add(verboseOption);
bundles.SetAction((parseResult, _) =>
{
var tenant = parseResult.GetValue(tenantOption);
var graphHash = parseResult.GetValue(bundlesGraphHashOption) ?? string.Empty;
var emitJson = parseResult.GetValue(jsonOption);
var verbose = parseResult.GetValue(verboseOption);
return CommandHandlers.HandleGraphBundlesAsync(
services,
tenant,
graphHash,
emitJson,
verbose,
cancellationToken);
});
graph.Add(bundles);
return graph;
}