feat: Add initial implementation of Vulnerability Resolver Jobs
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Created project for StellaOps.Scanner.Analyzers.Native.Tests with necessary dependencies.
- Documented roles and guidelines in AGENTS.md for Scheduler module.
- Implemented IResolverJobService interface and InMemoryResolverJobService for handling resolver jobs.
- Added ResolverBacklogNotifier and ResolverBacklogService for monitoring job metrics.
- Developed API endpoints for managing resolver jobs and retrieving metrics.
- Defined models for resolver job requests and responses.
- Integrated dependency injection for resolver job services.
- Implemented ImpactIndexSnapshot for persisting impact index data.
- Introduced SignalsScoringOptions for configurable scoring weights in reachability scoring.
- Added unit tests for ReachabilityScoringService and RuntimeFactsIngestionService.
- Created dotnet-filter.sh script to handle command-line arguments for dotnet.
- Established nuget-prime project for managing package downloads.
This commit is contained in:
master
2025-11-18 07:52:15 +02:00
parent e69b57d467
commit 8355e2ff75
299 changed files with 13293 additions and 2444 deletions

View File

@@ -1,6 +0,0 @@
namespace StellaOps.Orchestrator.Core;
public class Class1
{
}

View File

@@ -0,0 +1,102 @@
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.Orchestrator.Core;
public sealed record EventEnvelope(
[property: JsonPropertyName("schemaVersion")] string SchemaVersion,
[property: JsonPropertyName("eventId")] string EventId,
[property: JsonPropertyName("eventType")] string EventType,
[property: JsonPropertyName("occurredAt")] DateTimeOffset OccurredAt,
[property: JsonPropertyName("idempotencyKey")] string IdempotencyKey,
[property: JsonPropertyName("correlationId")] string? CorrelationId,
[property: JsonPropertyName("tenantId")] string TenantId,
[property: JsonPropertyName("projectId")] string? ProjectId,
[property: JsonPropertyName("actor")] EventActor Actor,
[property: JsonPropertyName("job")] EventJob Job,
[property: JsonPropertyName("metrics")] EventMetrics? Metrics,
[property: JsonPropertyName("notifier")] EventNotifier? Notifier)
{
public static EventEnvelope Create(
string eventType,
string tenantId,
EventJob job,
EventActor actor,
string schemaVersion = "orch.event.v1",
string? correlationId = null,
string? projectId = null,
EventMetrics? metrics = null,
EventNotifier? notifier = null,
DateTimeOffset? occurredAt = null,
string? eventId = null,
string? idempotencyKey = null)
{
ArgumentException.ThrowIfNullOrWhiteSpace(eventType);
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
ArgumentNullException.ThrowIfNull(job);
ArgumentNullException.ThrowIfNull(actor);
var occurred = occurredAt ?? DateTimeOffset.UtcNow;
var evtId = string.IsNullOrWhiteSpace(eventId) ? Guid.NewGuid().ToString() : eventId!;
var key = string.IsNullOrWhiteSpace(idempotencyKey)
? ComputeIdempotencyKey(eventType, job.Id, job.Attempt)
: idempotencyKey!;
return new EventEnvelope(
schemaVersion,
evtId,
eventType,
occurred,
key,
string.IsNullOrWhiteSpace(correlationId) ? null : correlationId,
tenantId,
string.IsNullOrWhiteSpace(projectId) ? null : projectId,
actor,
job,
metrics,
notifier);
}
public static string ComputeIdempotencyKey(string eventType, string jobId, int attempt)
{
ArgumentException.ThrowIfNullOrWhiteSpace(eventType);
ArgumentException.ThrowIfNullOrWhiteSpace(jobId);
return $"orch-{eventType}-{jobId}-{attempt}".ToLowerInvariant();
}
}
public sealed record EventActor(
[property: JsonPropertyName("subject")] string Subject,
[property: JsonPropertyName("scopes")] ImmutableArray<string> Scopes);
public sealed record EventJob(
[property: JsonPropertyName("id")] string Id,
[property: JsonPropertyName("type")] string Type,
[property: JsonPropertyName("runId")] string? RunId,
[property: JsonPropertyName("attempt")] int Attempt,
[property: JsonPropertyName("leaseId")] string? LeaseId,
[property: JsonPropertyName("taskRunnerId")] string? TaskRunnerId,
[property: JsonPropertyName("status")] string Status,
[property: JsonPropertyName("reason")] string? Reason,
[property: JsonPropertyName("payloadDigest")] string? PayloadDigest,
[property: JsonPropertyName("artifacts")] ImmutableArray<EventArtifact> Artifacts,
[property: JsonPropertyName("provenance")] ImmutableDictionary<string, string>? Provenance);
public sealed record EventArtifact(
[property: JsonPropertyName("uri")] string Uri,
[property: JsonPropertyName("digest")] string Digest,
[property: JsonPropertyName("mime")] string? Mime);
public sealed record EventMetrics(
[property: JsonPropertyName("durationSeconds")] double? DurationSeconds,
[property: JsonPropertyName("logStreamLagSeconds")] double? LogStreamLagSeconds,
[property: JsonPropertyName("backoffSeconds")] double? BackoffSeconds);
public sealed record EventNotifier(
[property: JsonPropertyName("channel")] string Channel,
[property: JsonPropertyName("delivery")] string Delivery,
[property: JsonPropertyName("replay")] EventReplayInfo? Replay);
public sealed record EventReplayInfo(
[property: JsonPropertyName("ordinal")] int Ordinal,
[property: JsonPropertyName("total")] int Total);

View File

@@ -0,0 +1,55 @@
using System.Collections.Immutable;
using System.Text.Json;
using StellaOps.Orchestrator.Core;
namespace StellaOps.Orchestrator.Tests;
public class EventEnvelopeTests
{
[Fact]
public void ComputeIdempotencyKey_IsDeterministicAndLowercase()
{
var key = EventEnvelope.ComputeIdempotencyKey("Job.Completed", "job_abc", 3);
Assert.Equal("orch-job.completed-job_abc-3", key);
}
[Fact]
public void Create_PopulatesDefaultsAndSerializes()
{
var job = new EventJob(
Id: "job_123",
Type: "pack-run",
RunId: "run_123",
Attempt: 2,
LeaseId: "lease_1",
TaskRunnerId: "tr_9",
Status: "completed",
Reason: null,
PayloadDigest: "sha256:deadbeef",
Artifacts: ImmutableArray.Create(new EventArtifact("s3://bucket/obj", "sha256:beef", "application/json")),
Provenance: ImmutableDictionary<string, string>.Empty);
var actor = new EventActor("worker-sdk-go", ImmutableArray.Create("orch:quota"));
var envelope = EventEnvelope.Create(
eventType: "job.completed",
tenantId: "tenant-alpha",
job: job,
actor: actor,
projectId: "proj-1",
correlationId: "corr-123");
Assert.False(string.IsNullOrWhiteSpace(envelope.EventId));
Assert.Equal("orch-job.completed-job_123-2", envelope.IdempotencyKey);
Assert.Equal("orch.event.v1", envelope.SchemaVersion);
Assert.Equal("tenant-alpha", envelope.TenantId);
Assert.Equal("proj-1", envelope.ProjectId);
var json = JsonSerializer.Serialize(envelope);
var roundtrip = JsonSerializer.Deserialize<EventEnvelope>(json);
Assert.NotNull(roundtrip);
Assert.Equal(envelope.IdempotencyKey, roundtrip!.IdempotencyKey);
Assert.Equal(envelope.Job.Id, roundtrip.Job.Id);
Assert.Equal(envelope.Actor.Subject, roundtrip.Actor.Subject);
}
}

View File

@@ -1,10 +0,0 @@
namespace StellaOps.Orchestrator.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}

View File

@@ -1,41 +1,19 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRouting(options => options.LowercaseUrls = true);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.MapGet("/healthz", () => Results.Json(new { status = "ok" }));
app.MapGet("/readyz", () => Results.Json(new { status = "ready" }));
app.Run();
public partial class Program;