feat(scanner): Implement Deno analyzer and associated tests
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added Deno analyzer with comprehensive metadata and evidence structure.
- Created a detailed implementation plan for Sprint 130 focusing on Deno analyzer.
- Introduced AdvisoryAiGuardrailOptions for managing guardrail configurations.
- Developed GuardrailPhraseLoader for loading blocked phrases from JSON files.
- Implemented tests for AdvisoryGuardrailOptions binding and phrase loading.
- Enhanced telemetry for Advisory AI with metrics tracking.
- Added VexObservationProjectionService for querying VEX observations.
- Created extensive tests for VexObservationProjectionService functionality.
- Introduced Ruby language analyzer with tests for simple and complex workspaces.
- Added Ruby application fixtures for testing purposes.
This commit is contained in:
master
2025-11-12 10:01:54 +02:00
parent 0e8655cbb1
commit babb81af52
75 changed files with 3346 additions and 187 deletions

View File

@@ -1,12 +1,17 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using MongoDB.Bson;
using StellaOps.Excititor.Core;
using StellaOps.Excititor.Core.Aoc;
using StellaOps.Excititor.Storage.Mongo;
using StellaOps.Excititor.WebService.Contracts;
using StellaOps.Excititor.WebService.Services;
public partial class Program
{
private const string TenantHeaderName = "X-Stella-Tenant";
@@ -127,4 +132,106 @@ public partial class Program
["primaryCode"] = exception.PrimaryErrorCode,
});
}
private static ImmutableHashSet<string> BuildStringFilterSet(StringValues values)
{
if (values.Count == 0)
{
return ImmutableHashSet<string>.Empty;
}
var builder = ImmutableHashSet.CreateBuilder<string>(StringComparer.OrdinalIgnoreCase);
foreach (var value in values)
{
if (!string.IsNullOrWhiteSpace(value))
{
builder.Add(value.Trim());
}
}
return builder.ToImmutable();
}
private static ImmutableHashSet<VexClaimStatus> BuildStatusFilter(StringValues values)
{
if (values.Count == 0)
{
return ImmutableHashSet<VexClaimStatus>.Empty;
}
var builder = ImmutableHashSet.CreateBuilder<VexClaimStatus>();
foreach (var value in values)
{
if (Enum.TryParse<VexClaimStatus>(value, ignoreCase: true, out var status))
{
builder.Add(status);
}
}
return builder.ToImmutable();
}
private static DateTimeOffset? ParseSinceTimestamp(StringValues values)
{
if (values.Count == 0)
{
return null;
}
var candidate = values[0];
return DateTimeOffset.TryParse(candidate, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var parsed)
? parsed
: null;
}
private static int ResolveLimit(StringValues values, int defaultValue, int min, int max)
{
if (values.Count == 0)
{
return defaultValue;
}
if (!int.TryParse(values[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsed))
{
return defaultValue;
}
return Math.Clamp(parsed, min, max);
}
private static VexObservationStatementResponse ToResponse(VexObservationStatementProjection projection)
{
var scope = projection.Scope;
var document = projection.Document;
var signature = projection.Signature;
return new VexObservationStatementResponse(
projection.ObservationId,
projection.ProviderId,
projection.Status.ToString().ToLowerInvariant(),
projection.Justification?.ToString().ToLowerInvariant(),
projection.Detail,
projection.FirstSeen,
projection.LastSeen,
new VexObservationScopeResponse(
scope.Key,
scope.Name,
scope.Version,
scope.Purl,
scope.Cpe,
scope.ComponentIdentifiers),
projection.Anchors,
new VexObservationDocumentResponse(
document.Digest,
document.Format.ToString().ToLowerInvariant(),
document.Revision,
document.SourceUri.ToString()),
signature is null
? null
: new VexObservationSignatureResponse(
signature.Type,
signature.KeyId,
signature.Issuer,
signature.VerifiedAt));
}
}