Add Authority Advisory AI and API Lifecycle Configuration

- Introduced AuthorityAdvisoryAiOptions and related classes for managing advisory AI configurations, including remote inference options and tenant-specific settings.
- Added AuthorityApiLifecycleOptions to control API lifecycle settings, including legacy OAuth endpoint configurations.
- Implemented validation and normalization methods for both advisory AI and API lifecycle options to ensure proper configuration.
- Created AuthorityNotificationsOptions and its related classes for managing notification settings, including ack tokens, webhooks, and escalation options.
- Developed IssuerDirectoryClient and related models for interacting with the issuer directory service, including caching mechanisms and HTTP client configurations.
- Added support for dependency injection through ServiceCollectionExtensions for the Issuer Directory Client.
- Updated project file to include necessary package references for the new Issuer Directory Client library.
This commit is contained in:
master
2025-11-02 13:40:38 +02:00
parent 66cb6c4b8a
commit f98cea3bcf
516 changed files with 68157 additions and 24754 deletions

View File

@@ -0,0 +1,15 @@
using BenchmarkDotNet.Running;
if (args.Any(arg => string.Equals(arg, "--dump-heuristics", StringComparison.OrdinalIgnoreCase)))
{
RustBenchmarkUtility.DumpHeuristicsFixture();
return;
}
if (args.Any(arg => string.Equals(arg, "--dump-fallback", StringComparison.OrdinalIgnoreCase)))
{
RustBenchmarkUtility.DumpFallbackFixture();
return;
}
BenchmarkRunner.Run<RustLanguageAnalyzerBenchmark>();

View File

@@ -0,0 +1,109 @@
using System.Text.Json;
using StellaOps.Scanner.Analyzers.Lang;
internal static class RustBenchmarkShared
{
public static string ResolveRepoRoot()
{
var fromEnv = Environment.GetEnvironmentVariable("STELLAOPS_REPO_ROOT");
if (!string.IsNullOrWhiteSpace(fromEnv) && Directory.Exists(fromEnv))
{
return Path.GetFullPath(fromEnv);
}
var directory = Path.GetFullPath(AppContext.BaseDirectory);
while (!string.IsNullOrEmpty(directory))
{
if (Directory.Exists(Path.Combine(directory, ".git")))
{
return directory;
}
var parent = Directory.GetParent(directory)?.FullName;
if (string.IsNullOrEmpty(parent) || string.Equals(parent, directory, StringComparison.Ordinal))
{
break;
}
directory = parent;
}
directory = Path.GetFullPath(AppContext.BaseDirectory);
while (!string.IsNullOrEmpty(directory))
{
if (File.Exists(Path.Combine(directory, "Directory.Build.props")) && Directory.Exists(Path.Combine(directory, "docs")))
{
return directory;
}
var parent = Directory.GetParent(directory)?.FullName;
if (string.IsNullOrEmpty(parent) || string.Equals(parent, directory, StringComparison.Ordinal))
{
break;
}
directory = parent;
}
throw new InvalidOperationException("Unable to locate StellaOps repository root. Set STELLAOPS_REPO_ROOT.");
}
public static string ResolveFixture(string repoRoot, params string[] segments)
{
var path = Path.Combine(new[] { repoRoot }.Concat(segments).ToArray());
if (!Directory.Exists(path))
{
throw new DirectoryNotFoundException($"Fixture path '{path}' not found.");
}
return path;
}
public static LanguageAnalyzerContext CreateContext(string rootPath, LanguageUsageHints usageHints)
=> new(rootPath, TimeProvider.System, usageHints);
public static HashSet<string> ExtractHeuristicComponents(LanguageAnalyzerResult result)
{
var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var component in result.Components)
{
if (component.Metadata.TryGetValue("provenance", out var provenance) &&
string.Equals(provenance, "heuristic", StringComparison.OrdinalIgnoreCase))
{
names.Add(component.Name);
}
}
return names;
}
public static HashSet<string> LoadCompetitorBaseline(string baselinePath)
{
var names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (!File.Exists(baselinePath))
{
return names;
}
using var document = JsonDocument.Parse(File.ReadAllText(baselinePath));
if (document.RootElement.TryGetProperty("detectedCrates", out var detectedCrates) &&
detectedCrates.ValueKind == JsonValueKind.Array)
{
foreach (var entry in detectedCrates.EnumerateArray())
{
if (entry.ValueKind == JsonValueKind.Object &&
entry.TryGetProperty("name", out var nameProperty) &&
nameProperty.ValueKind == JsonValueKind.String)
{
var name = nameProperty.GetString();
if (!string.IsNullOrWhiteSpace(name))
{
names.Add(name);
}
}
}
}
return names;
}
}

View File

@@ -0,0 +1,56 @@
using StellaOps.Scanner.Analyzers.Lang;
using StellaOps.Scanner.Analyzers.Lang.Rust;
internal static class RustBenchmarkUtility
{
public static void DumpHeuristicsFixture()
{
var repoRoot = RustBenchmarkShared.ResolveRepoRoot();
var fixture = RustBenchmarkShared.ResolveFixture(repoRoot, "src", "Scanner", "__Tests", "StellaOps.Scanner.Analyzers.Lang.Tests", "Fixtures", "lang", "rust", "heuristics");
var usageHints = new LanguageUsageHints(new[]
{
Path.Combine(fixture, "usr/local/bin/heuristic_app")
});
var analyzers = new ILanguageAnalyzer[]
{
new RustLanguageAnalyzer()
};
var engine = new LanguageAnalyzerEngine(analyzers);
var context = RustBenchmarkShared.CreateContext(fixture, usageHints);
var result = engine.AnalyzeAsync(context, CancellationToken.None).GetAwaiter().GetResult();
Console.WriteLine(result.ToJson(indent: true));
var heuristics = RustBenchmarkShared.ExtractHeuristicComponents(result);
var competitor = RustBenchmarkShared.LoadCompetitorBaseline(Path.Combine(fixture, "competitor-baseline.json"));
if (competitor.Count > 0)
{
var improvement = (double)heuristics.Count / competitor.Count;
Console.WriteLine();
Console.WriteLine($"Heuristic coverage: {heuristics.Count} components vs competitor {competitor.Count} ({improvement:P2}).");
}
}
public static void DumpFallbackFixture()
{
var repoRoot = RustBenchmarkShared.ResolveRepoRoot();
var fixture = RustBenchmarkShared.ResolveFixture(repoRoot, "src", "Scanner", "__Tests", "StellaOps.Scanner.Analyzers.Lang.Tests", "Fixtures", "lang", "rust", "fallback");
var usageHints = new LanguageUsageHints(new[]
{
Path.Combine(fixture, "usr/local/bin/opaque_bin")
});
var analyzers = new ILanguageAnalyzer[]
{
new RustLanguageAnalyzer()
};
var engine = new LanguageAnalyzerEngine(analyzers);
var context = RustBenchmarkShared.CreateContext(fixture, usageHints);
var result = engine.AnalyzeAsync(context, CancellationToken.None).GetAwaiter().GetResult();
Console.WriteLine(result.ToJson(indent: true));
}
}

View File

@@ -0,0 +1,79 @@
using System.Linq;
using BenchmarkDotNet.Attributes;
using StellaOps.Scanner.Analyzers.Lang;
using StellaOps.Scanner.Analyzers.Lang.Rust;
[MemoryDiagnoser]
public class RustLanguageAnalyzerBenchmark
{
private ILanguageAnalyzer[] _analyzers = Array.Empty<ILanguageAnalyzer>();
private LanguageAnalyzerEngine _engine = default!;
private string _heuristicsFixture = string.Empty;
private string _fallbackFixture = string.Empty;
private LanguageUsageHints _heuristicUsageHints = LanguageUsageHints.Empty;
private LanguageUsageHints _fallbackUsageHints = LanguageUsageHints.Empty;
private HashSet<string> _competitorBaseline = new(StringComparer.OrdinalIgnoreCase);
public double HeuristicImprovement { get; private set; }
public int HeuristicComponentCount { get; private set; }
[GlobalSetup]
public void Setup()
{
_analyzers = new ILanguageAnalyzer[]
{
new RustLanguageAnalyzer()
};
_engine = new LanguageAnalyzerEngine(_analyzers);
var repoRoot = RustBenchmarkShared.ResolveRepoRoot();
_heuristicsFixture = RustBenchmarkShared.ResolveFixture(repoRoot, "src", "Scanner", "__Tests", "StellaOps.Scanner.Analyzers.Lang.Tests", "Fixtures", "lang", "rust", "heuristics");
_fallbackFixture = RustBenchmarkShared.ResolveFixture(repoRoot, "src", "Scanner", "__Tests", "StellaOps.Scanner.Analyzers.Lang.Tests", "Fixtures", "lang", "rust", "fallback");
_heuristicUsageHints = new LanguageUsageHints(new[]
{
Path.Combine(_heuristicsFixture, "usr/local/bin/heuristic_app")
});
_fallbackUsageHints = new LanguageUsageHints(new[]
{
Path.Combine(_fallbackFixture, "usr/local/bin/opaque_bin")
});
var baselinePath = Path.Combine(_heuristicsFixture, "competitor-baseline.json");
_competitorBaseline = RustBenchmarkShared.LoadCompetitorBaseline(baselinePath);
HeuristicImprovement = CalculateHeuristicImprovement();
Console.WriteLine($"[Rust Analyzer] Heuristic coverage improvement vs competitor: {HeuristicImprovement:P2} ({HeuristicComponentCount} vs {_competitorBaseline.Count}).");
}
[Benchmark(Description = "Heuristics fixture")]
public async Task AnalyzeHeuristicsFixtureAsync()
{
var context = RustBenchmarkShared.CreateContext(_heuristicsFixture, _heuristicUsageHints);
await _engine.AnalyzeAsync(context, CancellationToken.None).ConfigureAwait(false);
}
[Benchmark(Description = "Fallback fixture")]
public async Task AnalyzeFallbackFixtureAsync()
{
var context = RustBenchmarkShared.CreateContext(_fallbackFixture, _fallbackUsageHints);
await _engine.AnalyzeAsync(context, CancellationToken.None).ConfigureAwait(false);
}
private double CalculateHeuristicImprovement()
{
var context = RustBenchmarkShared.CreateContext(_heuristicsFixture, _heuristicUsageHints);
var result = _engine.AnalyzeAsync(context, CancellationToken.None).GetAwaiter().GetResult();
var heuristics = RustBenchmarkShared.ExtractHeuristicComponents(result);
HeuristicComponentCount = heuristics.Count;
if (_competitorBaseline.Count == 0)
{
return double.PositiveInfinity;
}
return (double)HeuristicComponentCount / _competitorBaseline.Count;
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Analyzers.Lang.Rust\StellaOps.Scanner.Analyzers.Lang.Rust.csproj" />
<ProjectReference Include="..\..\__Libraries\StellaOps.Scanner.Core\StellaOps.Scanner.Core.csproj" />
</ItemGroup>
</Project>