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

@@ -32,10 +32,21 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
public async Task<LedgerWriteResult> AppendAsync(LedgerEventDraft draft, CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
using var activity = LedgerTelemetry.StartLedgerAppend(draft);
using var scope = _logger.BeginScope(new Dictionary<string, object?>
{
["tenant"] = draft.TenantId,
["chainId"] = draft.ChainId,
["sequence"] = draft.SequenceNumber,
["eventId"] = draft.EventId,
["eventType"] = draft.EventType,
["policyVersion"] = draft.PolicyVersion
});
var validationErrors = ValidateDraft(draft);
if (validationErrors.Count > 0)
{
LedgerTelemetry.MarkError(activity, "validation_failed");
return LedgerWriteResult.ValidationFailed([.. validationErrors]);
}
@@ -45,6 +56,7 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
var canonicalJson = LedgerCanonicalJsonSerializer.Serialize(draft.CanonicalEnvelope);
if (!string.Equals(existing.CanonicalJson, canonicalJson, StringComparison.Ordinal))
{
LedgerTelemetry.MarkError(activity, "event_id_conflict");
return LedgerWriteResult.Conflict(
"event_id_conflict",
$"Event '{draft.EventId}' already exists with a different payload.");
@@ -58,6 +70,7 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
var expectedSequence = chainHead is null ? 1 : chainHead.SequenceNumber + 1;
if (draft.SequenceNumber != expectedSequence)
{
LedgerTelemetry.MarkError(activity, "sequence_mismatch");
return LedgerWriteResult.Conflict(
"sequence_mismatch",
$"Sequence number '{draft.SequenceNumber}' does not match expected '{expectedSequence}'.");
@@ -66,6 +79,7 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
var previousHash = chainHead?.EventHash ?? LedgerEventConstants.EmptyHash;
if (draft.ProvidedPreviousHash is not null && !string.Equals(draft.ProvidedPreviousHash, previousHash, StringComparison.OrdinalIgnoreCase))
{
LedgerTelemetry.MarkError(activity, "previous_hash_mismatch");
return LedgerWriteResult.Conflict(
"previous_hash_mismatch",
$"Provided previous hash '{draft.ProvidedPreviousHash}' does not match chain head hash '{previousHash}'.");
@@ -93,7 +107,8 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
hashResult.EventHash,
previousHash,
hashResult.MerkleLeafHash,
hashResult.CanonicalJson);
hashResult.CanonicalJson,
draft.EvidenceBundleReference);
try
{
@@ -102,10 +117,29 @@ public sealed class LedgerEventWriteService : ILedgerEventWriteService
stopwatch.Stop();
LedgerMetrics.RecordWriteSuccess(stopwatch.Elapsed, draft.TenantId, draft.EventType, DetermineSource(draft));
LedgerTelemetry.MarkAppendOutcome(activity, record, stopwatch.Elapsed);
_logger.LogInformation(
"Ledger append committed for tenant {Tenant} chain {ChainId} seq {Sequence} event {EventId} ({EventType}) hash {Hash} prev {PrevHash}.",
record.TenantId,
record.ChainId,
record.SequenceNumber,
record.EventId,
record.EventType,
record.EventHash,
record.PreviousHash);
LedgerTimeline.EmitLedgerAppended(_logger, record, evidenceBundleRef: null);
}
catch (Exception ex) when (IsDuplicateKeyException(ex))
{
_logger.LogWarning(ex, "Ledger append detected concurrent duplicate for {EventId}", draft.EventId);
LedgerTelemetry.MarkError(activity, "duplicate_event");
_logger.LogWarning(
ex,
"Ledger append detected concurrent duplicate for tenant {Tenant} chain {ChainId} seq {Sequence} event {EventId}.",
draft.TenantId,
draft.ChainId,
draft.SequenceNumber,
draft.EventId);
var persisted = await _repository.GetByEventIdAsync(draft.TenantId, draft.EventId, cancellationToken).ConfigureAwait(false);
if (persisted is null)
{