Refactor code structure for improved readability and maintainability; optimize performance in key functions.

This commit is contained in:
master
2025-12-22 19:06:31 +02:00
parent dfaa2079aa
commit 4602ccc3a3
1444 changed files with 109919 additions and 8058 deletions

View File

@@ -0,0 +1,44 @@
# StellaOps.Scanner.Triage — Agent Charter
## Mission
Provide triage workflow infrastructure for the Scanner module:
- Define and maintain Triage database schema (findings, decisions, evidence, snapshots) with EF Core migrations.
- Support evidence-first workflow with signed decisions (DSSE envelopes) and audit trails.
- Enable Smart-Diff through triage snapshots that capture finding state at points in time.
- Provide models for VEX merge results, reachability analysis, and risk/lattice evaluations.
## Expectations
- Coordinate with Scanner.WebService for REST API exposure, Policy for verdict evaluation, and Attestor for decision signing.
- Maintain deterministic serialization for reproducible triage outcomes.
- Keep database schema aligned with triage workflow requirements (lanes, verdicts, evidence types).
- Update migrations and seed data when schema changes.
## Required Reading
- `docs/modules/scanner/architecture.md`
- `docs/product-advisories/21-Dec-2025 - How Top Scanners Shape EvidenceFirst UX.md`
- `docs/product-advisories/21-Dec-2025 - Designing Explainable Triage Workflows.md`
- `docs/modules/platform/architecture-overview.md`
## Working Agreement
- 1. Update task status to `DOING`/`DONE` in both corresponding sprint file `/docs/implplan/SPRINT_*.md` and the local `TASKS.md` when you start or finish work.
- 2. Review this charter and the Required Reading documents before coding; confirm prerequisites are met.
- 3. Keep changes deterministic (stable ordering, timestamps, hashes) and align with offline/air-gap expectations.
- 4. Coordinate doc updates, tests, and cross-guild communication whenever contracts or workflows change.
- 5. Revert to `TODO` if you pause the task without shipping changes; leave notes in commit/PR descriptions for context.
## Triage Schema Overview
- **TriageFinding**: Core finding entity linking vulnerability to component, with computed lane and verdict
- **TriageDecision**: Signed human decisions (mute-reach, mute-vex, exception, ack) with DSSE envelopes
- **TriageEvidenceArtifact**: Content-addressable evidence store (VEX docs, witness paths, SBOM refs)
- **TriageSnapshot**: Point-in-time captures for Smart-Diff baseline comparison
- **TriageEffectiveVex**: Merged VEX status per finding with lattice provenance
- **TriageReachabilityResult**: Static analysis outcomes (reachable, unreachable, unknown)
- **TriageRiskResult**: Policy/lattice evaluation results
## Guardrails
- All decisions must be DSSE-signed for non-repudiation.
- Lane transitions must be deterministic and auditable.
- Evidence artifacts must be content-addressable (stored by hash).
- Snapshots must capture complete finding state for reproducible diffs.
- Preserve determinism: sort outputs, normalize timestamps (UTC ISO-8601).
- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature.

View File

@@ -0,0 +1,144 @@
using System.Collections.Immutable;
namespace StellaOps.Scanner.Triage.Models;
/// <summary>
/// Represents a complete exploit path from artifact entry point to vulnerable symbol.
/// Groups related findings that share the same attack chain.
/// </summary>
public sealed record ExploitPath
{
/// <summary>
/// Stable deterministic ID for this path: hash(artifact + package + symbol + entryPoint).
/// </summary>
public required string PathId { get; init; }
/// <summary>
/// Artifact containing the vulnerable code.
/// </summary>
public required string ArtifactDigest { get; init; }
/// <summary>
/// Package containing the vulnerability.
/// </summary>
public required PackageRef Package { get; init; }
/// <summary>
/// The vulnerable symbol (function, method, class).
/// </summary>
public required VulnerableSymbol Symbol { get; init; }
/// <summary>
/// Entry point from which this path is reachable.
/// </summary>
public required EntryPoint EntryPoint { get; init; }
/// <summary>
/// All CVEs affecting this path.
/// </summary>
public required ImmutableArray<string> CveIds { get; init; }
/// <summary>
/// Reachability status from lattice.
/// </summary>
public required ReachabilityStatus Reachability { get; init; }
/// <summary>
/// Aggregated CVSS/EPSS scores for this path.
/// </summary>
public required PathRiskScore RiskScore { get; init; }
/// <summary>
/// Evidence supporting this path.
/// </summary>
public required PathEvidence Evidence { get; init; }
/// <summary>
/// Active exceptions applying to this path.
/// </summary>
public ImmutableArray<ExceptionRef> ActiveExceptions { get; init; } = [];
/// <summary>
/// Whether this path is "quiet" (all findings suppressed by exceptions/VEX).
/// </summary>
public bool IsQuiet => ActiveExceptions.Length > 0 || Evidence.VexStatus == VexStatus.NotAffected;
/// <summary>
/// When this path was first detected.
/// </summary>
public required DateTimeOffset FirstSeenAt { get; init; }
/// <summary>
/// When this path was last updated.
/// </summary>
public required DateTimeOffset LastUpdatedAt { get; init; }
}
public sealed record PackageRef(
string Purl,
string Name,
string Version,
string? Ecosystem);
public sealed record VulnerableSymbol(
string FullyQualifiedName,
string? SourceFile,
int? LineNumber,
string? Language);
public sealed record EntryPoint(
string Name,
string Type,
string? Path);
public sealed record PathRiskScore(
decimal AggregatedCvss,
decimal MaxEpss,
int CriticalCount,
int HighCount,
int MediumCount,
int LowCount);
public sealed record PathEvidence(
ReachabilityLatticeState LatticeState,
VexStatus VexStatus,
decimal Confidence,
ImmutableArray<EvidenceItem> Items);
public sealed record EvidenceItem(
string Type,
string Source,
string Description,
decimal Weight);
public sealed record ExceptionRef(
string ExceptionId,
string Reason,
DateTimeOffset ExpiresAt);
public enum ReachabilityStatus
{
Unknown,
StaticallyReachable,
RuntimeConfirmed,
Unreachable,
Contested
}
public enum ReachabilityLatticeState
{
Unknown,
StaticallyReachable,
RuntimeObserved,
Unreachable,
Contested
}
public enum VexStatus
{
Unknown,
NotAffected,
Affected,
Fixed,
UnderInvestigation
}

View File

@@ -0,0 +1,41 @@
using StellaOps.Scanner.Triage.Models;
namespace StellaOps.Scanner.Triage.Services;
/// <summary>
/// Groups findings into exploit paths by correlating reachability data.
/// </summary>
public interface IExploitPathGroupingService
{
/// <summary>
/// Groups findings for an artifact into exploit paths.
/// </summary>
Task<IReadOnlyList<ExploitPath>> GroupFindingsAsync(
string artifactDigest,
IReadOnlyList<Finding> findings,
CancellationToken ct = default);
}
/// <summary>
/// Represents a vulnerability finding.
/// </summary>
public sealed record Finding(
string FindingId,
string PackagePurl,
string PackageName,
string PackageVersion,
IReadOnlyList<string> CveIds,
decimal CvssScore,
decimal EpssScore,
Severity Severity,
string ArtifactDigest,
DateTimeOffset FirstSeenAt);
public enum Severity
{
Critical,
High,
Medium,
Low,
Info
}

View File

@@ -1,16 +1,14 @@
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<RootNamespace>StellaOps.Scanner.Triage</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0-*" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0-*" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
</ItemGroup>
</Project>