wip: doctor/cli/docs/api to vector db consolidation; api hardening for descriptions, tenant, and scopes; migrations and conversions of all DALs to EF v10

This commit is contained in:
master
2026-02-23 15:30:50 +02:00
parent bd8fee6ed8
commit e746577380
1424 changed files with 81225 additions and 25251 deletions

View File

@@ -20,11 +20,13 @@ public static class PointInTimeQueryEndpoints
public static void MapPointInTimeQueryEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/v1/pit/advisory")
.WithTags("Point-in-Time Advisory");
.WithTags("Point-in-Time Advisory")
.RequireAuthorization("replay.token.read");
// GET /v1/pit/advisory/{cveId} - Query advisory state at a point in time
group.MapGet("/{cveId}", QueryAdvisoryAsync)
.WithName("QueryAdvisoryAtPointInTime")
.WithDescription("Returns the advisory state for a specific CVE at a given point-in-time timestamp from the specified provider. Uses the nearest captured feed snapshot to reconstruct the advisory as it appeared at that moment.")
.Produces<AdvisoryQueryResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.ProducesProblem(StatusCodes.Status400BadRequest);
@@ -32,45 +34,53 @@ public static class PointInTimeQueryEndpoints
// POST /v1/pit/advisory/cross-provider - Query advisory across multiple providers
group.MapPost("/cross-provider", QueryCrossProviderAsync)
.WithName("QueryCrossProviderAdvisory")
.WithDescription("Queries advisory state across multiple feed providers at a single point in time and returns per-provider results along with a consensus summary of severity and fix status.")
.Produces<CrossProviderQueryResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest);
// GET /v1/pit/advisory/{cveId}/timeline - Get advisory timeline
group.MapGet("/{cveId}/timeline", GetAdvisoryTimelineAsync)
.WithName("GetAdvisoryTimeline")
.WithDescription("Returns the change timeline for a specific CVE from a given provider within an optional time range. Each entry identifies the snapshot digest and the type of change observed.")
.Produces<AdvisoryTimelineResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
// POST /v1/pit/advisory/diff - Compare advisory at two points in time
group.MapPost("/diff", CompareAdvisoryAtTimesAsync)
.WithName("CompareAdvisoryAtTimes")
.WithDescription("Produces a field-level diff of a CVE advisory between two distinct points in time from the same provider, identifying severity, fix-status, and metadata changes.")
.Produces<AdvisoryDiffResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest);
var snapshotsGroup = app.MapGroup("/v1/pit/snapshots")
.WithTags("Feed Snapshots");
.WithTags("Feed Snapshots")
.RequireAuthorization("replay.token.write");
// POST /v1/pit/snapshots - Capture a feed snapshot
snapshotsGroup.MapPost("/", CaptureSnapshotAsync)
.WithName("CaptureFeedSnapshot")
.WithDescription("Captures and stores a feed snapshot for a specific provider, computing its content-addressable digest. Returns 201 Created with the digest and whether an existing snapshot was reused.")
.Produces<SnapshotCaptureResponse>(StatusCodes.Status201Created)
.ProducesProblem(StatusCodes.Status400BadRequest);
// GET /v1/pit/snapshots/{digest} - Get a snapshot by digest
snapshotsGroup.MapGet("/{digest}", GetSnapshotAsync)
.WithName("GetFeedSnapshot")
.WithDescription("Returns snapshot metadata for a specific content-addressable digest including provider ID, feed type, and capture timestamp. Returns 404 if the digest is not stored.")
.Produces<SnapshotResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
// GET /v1/pit/snapshots/{digest}/verify - Verify snapshot integrity
snapshotsGroup.MapGet("/{digest}/verify", VerifySnapshotIntegrityAsync)
.WithName("VerifySnapshotIntegrity")
.WithDescription("Verifies the integrity of a stored snapshot by recomputing its content digest and comparing it against the stored value. Returns a verification result with expected and actual digest values.")
.Produces<SnapshotVerificationResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
// POST /v1/pit/snapshots/bundle - Create a snapshot bundle
snapshotsGroup.MapPost("/bundle", CreateSnapshotBundleAsync)
.WithName("CreateSnapshotBundle")
.WithDescription("Creates a composite snapshot bundle from multiple providers at a given point in time, returning the bundle digest, completeness flag, and the list of any missing providers.")
.Produces<SnapshotBundleResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest);
}

View File

@@ -24,11 +24,13 @@ public static class VerdictReplayEndpoints
public static void MapVerdictReplayEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/v1/replay/verdict")
.WithTags("Verdict Replay");
.WithTags("Verdict Replay")
.RequireAuthorization("replay.token.read");
// POST /v1/replay/verdict - Execute verdict replay
group.MapPost("/", ExecuteReplayAsync)
.WithName("ExecuteVerdictReplay")
.WithDescription("Executes a deterministic verdict replay from an audit bundle, re-evaluating the original policy with the stored inputs. Returns whether the replayed verdict matches the original, drift items, and an optional divergence report.")
.Produces<VerdictReplayResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest)
.ProducesProblem(StatusCodes.Status404NotFound);
@@ -36,18 +38,21 @@ public static class VerdictReplayEndpoints
// POST /v1/replay/verdict/verify - Verify replay eligibility
group.MapPost("/verify", VerifyEligibilityAsync)
.WithName("VerifyReplayEligibility")
.WithDescription("Checks whether an audit bundle is eligible for deterministic replay. Returns a confidence score, eligibility flags, and the expected outcome without executing the replay.")
.Produces<ReplayEligibilityResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest);
// GET /v1/replay/verdict/{manifestId}/status - Get replay status
group.MapGet("/{manifestId}/status", GetReplayStatusAsync)
.WithName("GetReplayStatus")
.WithDescription("Returns the stored replay history for a given audit manifest ID including total replay count, success/failure counts, and the timestamp of the last replay.")
.Produces<ReplayStatusResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
// POST /v1/replay/verdict/compare - Compare two replay executions
group.MapPost("/compare", CompareReplayResultsAsync)
.WithName("CompareReplayResults")
.WithDescription("Compares two replay execution results and produces a structured divergence report identifying field-level differences with per-divergence severity ratings.")
.Produces<ReplayComparisonResponse>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status400BadRequest);
}