using Microsoft.Extensions.DependencyInjection; using StellaOps.Tools.GoldenPairs.Models; using StellaOps.Tools.GoldenPairs.Serialization; using StellaOps.Tools.GoldenPairs.Services; using System.Collections.Immutable; using System.CommandLine; using System.CommandLine.Invocation; using System.CommandLine.Parsing; using System.Text; namespace StellaOps.Tools.GoldenPairs; public static class GoldenPairsApp { public static int RunAsync(string[] args) { var repoRootOption = new Option("--repo-root") { Description = "Repository root (defaults to nearest folder containing src/StellaOps.sln)." }; var datasetRootOption = new Option("--dataset-root") { Description = "Dataset root (defaults to datasets/golden-pairs under repo root)." }; var root = new RootCommand("Golden pairs corpus tooling."); root.Add(repoRootOption); root.Add(datasetRootOption); root.Add(BuildMirrorCommand(repoRootOption, datasetRootOption)); root.Add(BuildDiffCommand(repoRootOption, datasetRootOption)); root.Add(BuildValidateCommand(repoRootOption, datasetRootOption)); var parseResult = root.Parse(args); return parseResult.Invoke(); } private static Command BuildMirrorCommand(Option repoRootOption, Option datasetRootOption) { var cveArgument = new Argument("cve") { Description = "CVE identifier to mirror." }; var command = new Command("mirror", "Fetch artifacts for a golden pair."); command.Add(cveArgument); command.SetAction(async (parseResult, cancellationToken) => { var context = ResolveContext(parseResult, repoRootOption, datasetRootOption); if (context is null) { return 2; } using var provider = context.Provider; var loader = provider.GetRequiredService(); var mirror = provider.GetRequiredService(); var layout = provider.GetRequiredService(); var cve = parseResult.GetValue(cveArgument) ?? string.Empty; var loadResult = await loader.LoadAsync(cve, cancellationToken).ConfigureAwait(false); if (!loadResult.IsValid || loadResult.Metadata is null) { return ReportLoadErrors(loadResult.Errors); } var metadata = loadResult.Metadata; Directory.CreateDirectory(layout.GetOriginalDirectory(metadata.Cve)); Directory.CreateDirectory(layout.GetPatchedDirectory(metadata.Cve)); var originalResult = await mirror.FetchAsync(metadata.Original, layout.GetOriginalDirectory(metadata.Cve), cancellationToken) .ConfigureAwait(false); if (!originalResult.Success) { Console.Error.WriteLine($"[FAIL] Original mirror failed: {originalResult.ErrorMessage}"); return 1; } var originalPath = EnsureArtifactNamed(metadata, layout.GetOriginalDirectory(metadata.Cve), originalResult.LocalPath); WriteShaFile(originalPath, originalResult.ActualSha256); var patchedResult = await mirror.FetchAsync(metadata.Patched, layout.GetPatchedDirectory(metadata.Cve), cancellationToken) .ConfigureAwait(false); if (!patchedResult.Success) { Console.Error.WriteLine($"[FAIL] Patched mirror failed: {patchedResult.ErrorMessage}"); return 1; } var patchedPath = EnsureArtifactNamed(metadata, layout.GetPatchedDirectory(metadata.Cve), patchedResult.LocalPath); WriteShaFile(patchedPath, patchedResult.ActualSha256); Console.WriteLine($"[OK] Mirrored {metadata.Cve} into {layout.GetPairDirectory(metadata.Cve)}"); return 0; }); return command; } private static Command BuildDiffCommand(Option repoRootOption, Option datasetRootOption) { var cveArgument = new Argument("cve") { Description = "CVE identifier to diff." }; var command = new Command("diff", "Run diff analysis on a golden pair."); command.Add(cveArgument); var outputOption = new Option("--output") { Description = "Output format: json or table.", DefaultValueFactory = _ => "json" }; command.Add(outputOption); command.SetAction(async (parseResult, cancellationToken) => { var context = ResolveContext(parseResult, repoRootOption, datasetRootOption); if (context is null) { return 2; } using var provider = context.Provider; var loader = provider.GetRequiredService(); var diff = provider.GetRequiredService(); var layout = provider.GetRequiredService(); var cve = parseResult.GetValue(cveArgument) ?? string.Empty; var loadResult = await loader.LoadAsync(cve, cancellationToken).ConfigureAwait(false); if (!loadResult.IsValid || loadResult.Metadata is null) { return ReportLoadErrors(loadResult.Errors); } GoldenDiffReport report; try { report = await diff.DiffAsync(loadResult.Metadata, cancellationToken: cancellationToken).ConfigureAwait(false); } catch (Exception ex) { Console.Error.WriteLine($"[FAIL] Diff failed: {ex.Message}"); return 1; } var reportJson = GoldenPairsJsonSerializer.SerializeIndented(report); var reportPath = layout.GetDiffReportPath(loadResult.Metadata.Cve); Directory.CreateDirectory(Path.GetDirectoryName(reportPath)!); await File.WriteAllTextAsync(reportPath, reportJson, cancellationToken).ConfigureAwait(false); var output = parseResult.GetValue(outputOption) ?? "json"; if (string.Equals(output, "table", StringComparison.OrdinalIgnoreCase)) { WriteTableReport(report); } else { Console.WriteLine(reportJson); } Console.WriteLine($"[OK] Diff report written to {reportPath}"); return report.MatchesExpected ? 0 : 1; }); return command; } private static Command BuildValidateCommand(Option repoRootOption, Option datasetRootOption) { var command = new Command("validate", "Validate all golden pairs in the corpus."); var failFastOption = new Option("--fail-fast") { Description = "Stop at first failure." }; command.Add(failFastOption); command.SetAction(async (parseResult, cancellationToken) => { var context = ResolveContext(parseResult, repoRootOption, datasetRootOption); if (context is null) { return 2; } using var provider = context.Provider; var loader = provider.GetRequiredService(); var diff = provider.GetRequiredService(); var layout = provider.GetRequiredService(); var failFast = parseResult.GetValue(failFastOption); var pairDirectories = Directory.EnumerateDirectories(layout.DatasetRoot, "CVE-*", SearchOption.TopDirectoryOnly) .OrderBy(path => path, StringComparer.Ordinal) .ToArray(); var failures = 0; foreach (var pairDir in pairDirectories) { var metadataPath = Path.Combine(pairDir, GoldenPairLayout.DefaultMetadataFileName); var loadResult = await loader.LoadFromPathAsync(metadataPath, cancellationToken).ConfigureAwait(false); if (!loadResult.IsValid || loadResult.Metadata is null) { failures++; Console.Error.WriteLine($"[FAIL] {Path.GetFileName(pairDir)}: metadata invalid."); if (failFast) { return 1; } continue; } try { var report = await diff.DiffAsync(loadResult.Metadata, cancellationToken: cancellationToken).ConfigureAwait(false); var reportJson = GoldenPairsJsonSerializer.SerializeIndented(report); await File.WriteAllTextAsync(layout.GetDiffReportPath(loadResult.Metadata.Cve), reportJson, cancellationToken) .ConfigureAwait(false); if (report.MatchesExpected) { Console.WriteLine($"[OK] {loadResult.Metadata.Cve} validated."); } else { failures++; Console.Error.WriteLine($"[FAIL] {loadResult.Metadata.Cve} mismatch."); if (failFast) { return 1; } } } catch (Exception ex) { failures++; Console.Error.WriteLine($"[FAIL] {loadResult.Metadata.Cve}: {ex.Message}"); if (failFast) { return 1; } } } Console.WriteLine($"Summary: {pairDirectories.Length - failures}/{pairDirectories.Length} passed."); return failures == 0 ? 0 : 1; }); return command; } private static GoldenPairsContext? ResolveContext( ParseResult parseResult, Option repoRootOption, Option datasetRootOption) { var repoRoot = parseResult.GetValue(repoRootOption)?.FullName; var datasetRoot = parseResult.GetValue(datasetRootOption)?.FullName; var resolvedRepoRoot = GoldenPairsPaths.TryResolveRepoRoot(repoRoot); if (resolvedRepoRoot is null) { Console.Error.WriteLine("[FAIL] Unable to resolve repo root. Provide --repo-root explicitly."); return null; } var resolvedDatasetRoot = GoldenPairsPaths.ResolveDatasetRoot(resolvedRepoRoot, datasetRoot); var metadataSchemaPath = GoldenPairsPaths.ResolveMetadataSchemaPath(resolvedRepoRoot); var indexSchemaPath = GoldenPairsPaths.ResolveIndexSchemaPath(resolvedRepoRoot); var provider = GoldenPairsServiceFactory.Build(resolvedDatasetRoot, metadataSchemaPath, indexSchemaPath); return new GoldenPairsContext(resolvedRepoRoot, resolvedDatasetRoot, provider); } private static int ReportLoadErrors(ImmutableArray errors) { foreach (var error in errors) { var location = string.IsNullOrWhiteSpace(error.InstanceLocation) ? string.Empty : $" ({error.InstanceLocation})"; Console.Error.WriteLine($"[FAIL] {error.Message}{location}"); } return 1; } private static string EnsureArtifactNamed(GoldenPairMetadata metadata, string destinationDirectory, string currentPath) { var expectedPath = Path.Combine(destinationDirectory, metadata.Artifact.Name); if (string.Equals(currentPath, expectedPath, StringComparison.Ordinal)) { return currentPath; } if (File.Exists(expectedPath)) { File.Delete(expectedPath); } File.Move(currentPath, expectedPath); return expectedPath; } private static void WriteShaFile(string filePath, string sha256) { var shaPath = $"{filePath}.sha256"; File.WriteAllText(shaPath, $"{sha256}\n", Encoding.ASCII); } private static void WriteTableReport(GoldenDiffReport report) { Console.WriteLine($"CVE: {report.Cve}"); Console.WriteLine($"Verdict: {report.Verdict.ToString().ToLowerInvariant()} ({report.Confidence:F2})"); Console.WriteLine($"Matches expected: {report.MatchesExpected}"); Console.WriteLine("Sections:"); foreach (var section in report.Sections) { Console.WriteLine($" {section.Name} - {section.Status.ToString().ToLowerInvariant()}"); } } private sealed record GoldenPairsContext( string RepoRoot, string DatasetRoot, ServiceProvider Provider); }