Gaps fill up, fixes, ui restructuring

This commit is contained in:
master
2026-02-19 22:10:54 +02:00
parent b5829dce5c
commit 04cacdca8a
331 changed files with 42859 additions and 2174 deletions

View File

@@ -0,0 +1,200 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using StellaOps.Scanner.WebService.Security;
namespace StellaOps.Scanner.WebService.Endpoints;
internal static class SecurityAdapterEndpoints
{
private static readonly DateTimeOffset SnapshotAt = DateTimeOffset.Parse("2026-02-19T03:15:00Z");
public static void MapSecurityAdapterEndpoints(this RouteGroupBuilder apiGroup)
{
ArgumentNullException.ThrowIfNull(apiGroup);
var security = apiGroup.MapGroup("/security")
.WithTags("Security");
security.MapGet("/findings", (
[FromQuery] string? severity,
[FromQuery] string? reachability,
[FromQuery] string? environment) =>
{
var items = BuildFindings()
.Where(item => string.IsNullOrWhiteSpace(severity) || string.Equals(item.Severity, severity, StringComparison.OrdinalIgnoreCase))
.Where(item => string.IsNullOrWhiteSpace(reachability) || string.Equals(item.Reachability, reachability, StringComparison.OrdinalIgnoreCase))
.Where(item => string.IsNullOrWhiteSpace(environment) || string.Equals(item.Environment, environment, StringComparison.OrdinalIgnoreCase))
.OrderBy(item => item.FindingId, StringComparer.Ordinal)
.ToList();
return Results.Ok(new SecurityFindingsResponseDto(
SnapshotAt,
BuildConfidence(),
items,
items.Count));
})
.WithName("SecurityFindingsAdapter")
.WithSummary("Decision-first findings view with reachability context.")
.RequireAuthorization(ScannerPolicies.ScansRead);
security.MapGet("/vulnerabilities", (
[FromQuery] string? cve) =>
{
var items = BuildVulnerabilities()
.Where(item => string.IsNullOrWhiteSpace(cve) || item.Cve.Contains(cve, StringComparison.OrdinalIgnoreCase))
.OrderBy(item => item.Cve, StringComparer.Ordinal)
.ToList();
return Results.Ok(new SecurityVulnerabilitiesResponseDto(
SnapshotAt,
items,
items.Count));
})
.WithName("SecurityVulnerabilitiesAdapter")
.WithSummary("Vulnerability catalog projection with environment impact counts.")
.RequireAuthorization(ScannerPolicies.ScansRead);
security.MapGet("/vex", (
[FromQuery] string? status) =>
{
var items = BuildVexStatements()
.Where(item => string.IsNullOrWhiteSpace(status) || string.Equals(item.Status, status, StringComparison.OrdinalIgnoreCase))
.OrderBy(item => item.StatementId, StringComparer.Ordinal)
.ToList();
return Results.Ok(new SecurityVexResponseDto(
SnapshotAt,
items,
items.Count));
})
.WithName("SecurityVexAdapter")
.WithSummary("VEX statement projection linked to findings and trust state.")
.RequireAuthorization(ScannerPolicies.ScansRead);
security.MapGet("/reachability", () =>
{
var items = BuildReachability()
.OrderBy(item => item.Environment, StringComparer.Ordinal)
.ToList();
return Results.Ok(new SecurityReachabilityResponseDto(
SnapshotAt,
BuildConfidence(),
items));
})
.WithName("SecurityReachabilityAdapter")
.WithSummary("Reachability summary projection by environment.")
.RequireAuthorization(ScannerPolicies.ScansRead);
}
private static SecurityDataConfidenceDto BuildConfidence()
{
return new SecurityDataConfidenceDto(
Status: "warning",
Summary: "NVD freshness lag and runtime ingest delay reduce confidence.",
NvdStalenessHours: 3,
PendingRescans: 12,
RuntimeDlqDepth: 1230);
}
private static IReadOnlyList<SecurityFindingRowDto> BuildFindings()
{
return
[
new SecurityFindingRowDto("finding-0001", "CVE-2026-1234", "us-prod", "user-service", "critical", "reachable", "0/1/0", "stale"),
new SecurityFindingRowDto("finding-0002", "CVE-2026-2222", "us-uat", "billing-worker", "critical", "reachable", "0/1/0", "stale"),
new SecurityFindingRowDto("finding-0003", "CVE-2026-9001", "us-prod", "api-gateway", "high", "not_reachable", "1/1/1", "fresh"),
];
}
private static IReadOnlyList<SecurityVulnerabilityRowDto> BuildVulnerabilities()
{
return
[
new SecurityVulnerabilityRowDto("CVE-2026-1234", "critical", AffectedEnvironments: 1, ReachableEnvironments: 1, VexStatus: "under_investigation"),
new SecurityVulnerabilityRowDto("CVE-2026-2222", "critical", AffectedEnvironments: 1, ReachableEnvironments: 1, VexStatus: "none"),
new SecurityVulnerabilityRowDto("CVE-2026-9001", "high", AffectedEnvironments: 2, ReachableEnvironments: 0, VexStatus: "not_affected"),
];
}
private static IReadOnlyList<SecurityVexStatementRowDto> BuildVexStatements()
{
return
[
new SecurityVexStatementRowDto("vex-0001", "CVE-2026-9001", "not_affected", "vendor-a", "trusted", "2026-02-19T01:10:00Z"),
new SecurityVexStatementRowDto("vex-0002", "CVE-2026-1234", "under_investigation", "internal-sec", "trusted", "2026-02-19T00:22:00Z"),
new SecurityVexStatementRowDto("vex-0003", "CVE-2026-2222", "affected", "vendor-b", "unverified", "2026-02-18T19:02:00Z"),
];
}
private static IReadOnlyList<SecurityReachabilityRowDto> BuildReachability()
{
return
[
new SecurityReachabilityRowDto("apac-prod", CriticalReachable: 0, HighReachable: 0, RuntimeCoveragePercent: 86),
new SecurityReachabilityRowDto("eu-prod", CriticalReachable: 0, HighReachable: 1, RuntimeCoveragePercent: 89),
new SecurityReachabilityRowDto("us-prod", CriticalReachable: 2, HighReachable: 1, RuntimeCoveragePercent: 41),
new SecurityReachabilityRowDto("us-uat", CriticalReachable: 1, HighReachable: 2, RuntimeCoveragePercent: 62),
];
}
}
public sealed record SecurityFindingsResponseDto(
DateTimeOffset GeneratedAt,
SecurityDataConfidenceDto DataConfidence,
IReadOnlyList<SecurityFindingRowDto> Items,
int Total);
public sealed record SecurityFindingRowDto(
string FindingId,
string Cve,
string Environment,
string Component,
string Severity,
string Reachability,
string HybridEvidence,
string SbomFreshness);
public sealed record SecurityVulnerabilitiesResponseDto(
DateTimeOffset GeneratedAt,
IReadOnlyList<SecurityVulnerabilityRowDto> Items,
int Total);
public sealed record SecurityVulnerabilityRowDto(
string Cve,
string Severity,
int AffectedEnvironments,
int ReachableEnvironments,
string VexStatus);
public sealed record SecurityVexResponseDto(
DateTimeOffset GeneratedAt,
IReadOnlyList<SecurityVexStatementRowDto> Items,
int Total);
public sealed record SecurityVexStatementRowDto(
string StatementId,
string Cve,
string Status,
string Issuer,
string TrustStatus,
string SignedAt);
public sealed record SecurityReachabilityResponseDto(
DateTimeOffset GeneratedAt,
SecurityDataConfidenceDto DataConfidence,
IReadOnlyList<SecurityReachabilityRowDto> Items);
public sealed record SecurityReachabilityRowDto(
string Environment,
int CriticalReachable,
int HighReachable,
int RuntimeCoveragePercent);
public sealed record SecurityDataConfidenceDto(
string Status,
string Summary,
int NvdStalenessHours,
int PendingRescans,
int RuntimeDlqDepth);

View File

@@ -636,6 +636,7 @@ apiGroup.MapTriageInboxEndpoints();
apiGroup.MapBatchTriageEndpoints();
apiGroup.MapProofBundleEndpoints();
apiGroup.MapSecretDetectionSettingsEndpoints(); // Sprint: SPRINT_20260104_006_BE
apiGroup.MapSecurityAdapterEndpoints(); // Pack v2 security adapter routes
if (resolvedOptions.Features.EnablePolicyPreview)
{