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:
@@ -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>();
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user