Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.

This commit is contained in:
StellaOps Bot
2025-12-26 21:54:17 +02:00
parent 335ff7da16
commit c2b9cd8d1f
3717 changed files with 264714 additions and 48202 deletions

View File

@@ -62,18 +62,14 @@ public sealed class VexCliCommandModule : ICliCommandModule
StellaOpsCliOptions options,
CancellationToken cancellationToken)
{
var cmd = new Command("auto-downgrade", "Auto-downgrade VEX based on runtime observations.");
var imageOption = new Option<string>("--image")
var imageOption = new Option<string?>("--image")
{
Description = "Container image digest or reference to check",
IsRequired = false
Description = "Container image digest or reference to check"
};
var checkOption = new Option<string>("--check")
var checkOption = new Option<string?>("--check")
{
Description = "Image to check for hot vulnerable symbols",
IsRequired = false
Description = "Image to check for hot vulnerable symbols"
};
var dryRunOption = new Option<bool>("--dry-run")
@@ -84,20 +80,20 @@ public sealed class VexCliCommandModule : ICliCommandModule
var minObservationsOption = new Option<int>("--min-observations")
{
Description = "Minimum observation count threshold",
DefaultValueFactory = _ => 10
};
minObservationsOption.SetDefaultValue(10);
var minCpuOption = new Option<double>("--min-cpu")
{
Description = "Minimum CPU percentage threshold",
DefaultValueFactory = _ => 1.0
};
minCpuOption.SetDefaultValue(1.0);
var minConfidenceOption = new Option<double>("--min-confidence")
{
Description = "Minimum confidence threshold (0.0-1.0)",
DefaultValueFactory = _ => 0.7
};
minConfidenceOption.SetDefaultValue(0.7);
var outputOption = new Option<string?>("--output")
{
@@ -106,39 +102,40 @@ public sealed class VexCliCommandModule : ICliCommandModule
var formatOption = new Option<OutputFormat>("--format")
{
Description = "Output format"
Description = "Output format",
DefaultValueFactory = _ => OutputFormat.Table
};
formatOption.SetDefaultValue(OutputFormat.Table);
cmd.AddOption(imageOption);
cmd.AddOption(checkOption);
cmd.AddOption(dryRunOption);
cmd.AddOption(minObservationsOption);
cmd.AddOption(minCpuOption);
cmd.AddOption(minConfidenceOption);
cmd.AddOption(outputOption);
cmd.AddOption(formatOption);
cmd.AddOption(verboseOption);
cmd.SetHandler(async (context) =>
var cmd = new Command("auto-downgrade", "Auto-downgrade VEX based on runtime observations.")
{
var image = context.ParseResult.GetValueForOption(imageOption);
var check = context.ParseResult.GetValueForOption(checkOption);
var dryRun = context.ParseResult.GetValueForOption(dryRunOption);
var minObs = context.ParseResult.GetValueForOption(minObservationsOption);
var minCpu = context.ParseResult.GetValueForOption(minCpuOption);
var minConf = context.ParseResult.GetValueForOption(minConfidenceOption);
var output = context.ParseResult.GetValueForOption(outputOption);
var format = context.ParseResult.GetValueForOption(formatOption);
var verbose = context.ParseResult.GetValueForOption(verboseOption);
imageOption,
checkOption,
dryRunOption,
minObservationsOption,
minCpuOption,
minConfidenceOption,
outputOption,
formatOption
};
cmd.SetAction(async (parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption);
var check = parseResult.GetValue(checkOption);
var dryRun = parseResult.GetValue(dryRunOption);
var minObs = parseResult.GetValue(minObservationsOption);
var minCpu = parseResult.GetValue(minCpuOption);
var minConf = parseResult.GetValue(minConfidenceOption);
var output = parseResult.GetValue(outputOption);
var format = parseResult.GetValue(formatOption);
var verbose = parseResult.GetValue(verboseOption);
// Use --check if --image not provided
var targetImage = image ?? check;
if (string.IsNullOrWhiteSpace(targetImage))
{
AnsiConsole.MarkupLine("[red]Error:[/] Either --image or --check must be specified.");
context.ExitCode = 1;
return;
return 1;
}
var logger = services.GetService<ILogger<VexCliCommandModule>>();
@@ -155,9 +152,9 @@ public sealed class VexCliCommandModule : ICliCommandModule
format,
verbose,
options,
cancellationToken);
ct);
context.ExitCode = 0;
return 0;
});
return cmd;
@@ -322,8 +319,6 @@ public sealed class VexCliCommandModule : ICliCommandModule
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var cmd = new Command("check", "Check VEX status for an image or CVE.");
var imageOption = new Option<string?>("--image")
{
Description = "Container image to check"
@@ -334,25 +329,26 @@ public sealed class VexCliCommandModule : ICliCommandModule
Description = "CVE identifier to check"
};
cmd.AddOption(imageOption);
cmd.AddOption(cveOption);
cmd.AddOption(verboseOption);
cmd.SetHandler(async (context) =>
var cmd = new Command("check", "Check VEX status for an image or CVE.")
{
var image = context.ParseResult.GetValueForOption(imageOption);
var cve = context.ParseResult.GetValueForOption(cveOption);
var verbose = context.ParseResult.GetValueForOption(verboseOption);
imageOption,
cveOption
};
cmd.SetAction((parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption);
var cve = parseResult.GetValue(cveOption);
var verbose = parseResult.GetValue(verboseOption);
if (string.IsNullOrWhiteSpace(image) && string.IsNullOrWhiteSpace(cve))
{
AnsiConsole.MarkupLine("[red]Error:[/] Either --image or --cve must be specified.");
context.ExitCode = 1;
return;
return Task.FromResult(1);
}
AnsiConsole.MarkupLine("[grey]VEX check not yet implemented[/]");
context.ExitCode = 0;
return Task.FromResult(0);
});
return cmd;
@@ -363,8 +359,6 @@ public sealed class VexCliCommandModule : ICliCommandModule
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var cmd = new Command("list", "List VEX statements.");
var productOption = new Option<string?>("--product")
{
Description = "Filter by product identifier"
@@ -377,23 +371,25 @@ public sealed class VexCliCommandModule : ICliCommandModule
var limitOption = new Option<int>("--limit")
{
Description = "Maximum number of results"
Description = "Maximum number of results",
DefaultValueFactory = _ => 100
};
limitOption.SetDefaultValue(100);
cmd.AddOption(productOption);
cmd.AddOption(statusOption);
cmd.AddOption(limitOption);
cmd.AddOption(verboseOption);
cmd.SetHandler(async (context) =>
var cmd = new Command("list", "List VEX statements.")
{
var product = context.ParseResult.GetValueForOption(productOption);
var status = context.ParseResult.GetValueForOption(statusOption);
var limit = context.ParseResult.GetValueForOption(limitOption);
productOption,
statusOption,
limitOption
};
cmd.SetAction((parseResult, ct) =>
{
var product = parseResult.GetValue(productOption);
var status = parseResult.GetValue(statusOption);
var limit = parseResult.GetValue(limitOption);
AnsiConsole.MarkupLine("[grey]VEX list not yet implemented[/]");
context.ExitCode = 0;
return Task.FromResult(0);
});
return cmd;
@@ -405,25 +401,23 @@ public sealed class VexCliCommandModule : ICliCommandModule
StellaOpsCliOptions options,
CancellationToken cancellationToken)
{
var cmd = new Command("not-reachable", "Generate VEX with not_reachable_at_runtime justification.");
var imageOption = new Option<string>("--image")
{
Description = "Container image to analyze",
IsRequired = true
Required = true
};
var windowOption = new Option<int>("--window")
{
Description = "Observation window in hours"
Description = "Observation window in hours",
DefaultValueFactory = _ => 24
};
windowOption.SetDefaultValue(24);
var minConfidenceOption = new Option<double>("--min-confidence")
{
Description = "Minimum confidence threshold"
Description = "Minimum confidence threshold",
DefaultValueFactory = _ => 0.6
};
minConfidenceOption.SetDefaultValue(0.6);
var outputOption = new Option<string?>("--output")
{
@@ -435,27 +429,28 @@ public sealed class VexCliCommandModule : ICliCommandModule
Description = "Dry run - analyze but don't generate VEX"
};
cmd.AddOption(imageOption);
cmd.AddOption(windowOption);
cmd.AddOption(minConfidenceOption);
cmd.AddOption(outputOption);
cmd.AddOption(dryRunOption);
cmd.AddOption(verboseOption);
cmd.SetHandler(async (context) =>
var cmd = new Command("not-reachable", "Generate VEX with not_reachable_at_runtime justification.")
{
var image = context.ParseResult.GetValueForOption(imageOption);
var window = context.ParseResult.GetValueForOption(windowOption);
var minConf = context.ParseResult.GetValueForOption(minConfidenceOption);
var output = context.ParseResult.GetValueForOption(outputOption);
var dryRun = context.ParseResult.GetValueForOption(dryRunOption);
var verbose = context.ParseResult.GetValueForOption(verboseOption);
imageOption,
windowOption,
minConfidenceOption,
outputOption,
dryRunOption
};
cmd.SetAction(async (parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption);
var window = parseResult.GetValue(windowOption);
var minConf = parseResult.GetValue(minConfidenceOption);
var output = parseResult.GetValue(outputOption);
var dryRun = parseResult.GetValue(dryRunOption);
var verbose = parseResult.GetValue(verboseOption);
if (string.IsNullOrWhiteSpace(image))
{
AnsiConsole.MarkupLine("[red]Error:[/] --image is required.");
context.ExitCode = 1;
return;
return 1;
}
await RunNotReachableAnalysisAsync(
@@ -467,9 +462,9 @@ public sealed class VexCliCommandModule : ICliCommandModule
dryRun,
verbose,
options,
cancellationToken);
ct);
context.ExitCode = 0;
return 0;
});
return cmd;
@@ -584,9 +579,8 @@ public sealed class VexCliCommandModule : ICliCommandModule
var httpClient = services.GetService<IHttpClientFactory>()?.CreateClient("autovex")
?? new HttpClient();
var baseUrl = options.ExcititorApiBaseUrl
?? Environment.GetEnvironmentVariable("STELLAOPS_EXCITITOR_URL")
?? "http://localhost:5080";
var baseUrl = Environment.GetEnvironmentVariable("STELLAOPS_EXCITITOR_URL")
?? (string.IsNullOrEmpty(options.BackendUrl) ? "http://localhost:5080" : options.BackendUrl);
return new AutoVexHttpClient(httpClient, baseUrl);
}