save dev progress
This commit is contained in:
@@ -411,6 +411,40 @@ public sealed record BucketThresholdsDto
|
||||
public required int InvestigateMin { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response for listing policy versions.
|
||||
/// Sprint: SPRINT_8200_0012_0004 - Task API-8200-029
|
||||
/// </summary>
|
||||
public sealed record PolicyVersionListResponse
|
||||
{
|
||||
/// <summary>List of available policy versions.</summary>
|
||||
public required IReadOnlyList<PolicyVersionSummary> Versions { get; init; }
|
||||
|
||||
/// <summary>Currently active version.</summary>
|
||||
public required string ActiveVersion { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of a policy version.
|
||||
/// </summary>
|
||||
public sealed record PolicyVersionSummary
|
||||
{
|
||||
/// <summary>Version identifier.</summary>
|
||||
public required string Version { get; init; }
|
||||
|
||||
/// <summary>Content digest.</summary>
|
||||
public required string Digest { get; init; }
|
||||
|
||||
/// <summary>Environment/profile (production, staging, etc.).</summary>
|
||||
public required string Environment { get; init; }
|
||||
|
||||
/// <summary>When this version was created.</summary>
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
|
||||
/// <summary>Whether this is the currently active version.</summary>
|
||||
public required bool IsActive { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Webhook registration response.
|
||||
/// </summary>
|
||||
|
||||
@@ -85,6 +85,15 @@ public static class ScoringEndpoints
|
||||
.RequireAuthorization(ScoringReadPolicy)
|
||||
.Produces<ScoringPolicyResponse>(200)
|
||||
.Produces(404);
|
||||
|
||||
// GET /api/v1/scoring/policy/versions - List all policy versions
|
||||
// Rate limit: 100/min (via API Gateway)
|
||||
// Task: API-8200-029
|
||||
scoringGroup.MapGet("/policy/versions", ListPolicyVersions)
|
||||
.WithName("ListScoringPolicyVersions")
|
||||
.WithDescription("List all available scoring policy versions")
|
||||
.RequireAuthorization(ScoringReadPolicy)
|
||||
.Produces<PolicyVersionListResponse>(200);
|
||||
}
|
||||
|
||||
private static async Task<Results<Ok<EvidenceWeightedScoreResponse>, NotFound<ScoringErrorResponse>, BadRequest<ScoringErrorResponse>>> CalculateScore(
|
||||
@@ -218,4 +227,12 @@ public static class ScoringEndpoints
|
||||
|
||||
return TypedResults.Ok(policy);
|
||||
}
|
||||
|
||||
private static async Task<Ok<PolicyVersionListResponse>> ListPolicyVersions(
|
||||
IFindingScoringService service,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var versions = await service.ListPolicyVersionsAsync(ct);
|
||||
return TypedResults.Ok(versions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2004,3 +2004,11 @@ static Guid? ParseGuid(string value)
|
||||
{
|
||||
return Guid.TryParse(value, out var result) ? result : null;
|
||||
}
|
||||
|
||||
namespace StellaOps.Findings.Ledger.WebService
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker class for WebApplicationFactory integration tests.
|
||||
/// </summary>
|
||||
public partial class Program { }
|
||||
}
|
||||
|
||||
@@ -59,6 +59,12 @@ public interface IFindingScoringService
|
||||
/// Get specific policy version.
|
||||
/// </summary>
|
||||
Task<ScoringPolicyResponse?> GetPolicyVersionAsync(string version, CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// List all available policy versions.
|
||||
/// Task: API-8200-029
|
||||
/// </summary>
|
||||
Task<PolicyVersionListResponse> ListPolicyVersionsAsync(CancellationToken ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -326,6 +332,32 @@ public sealed class FindingScoringService : IFindingScoringService
|
||||
return MapPolicyToResponse(policy);
|
||||
}
|
||||
|
||||
public async Task<PolicyVersionListResponse> ListPolicyVersionsAsync(CancellationToken ct)
|
||||
{
|
||||
// Get known policy versions/environments
|
||||
var environments = new[] { "production", "staging", "development" };
|
||||
var versions = new List<PolicyVersionSummary>();
|
||||
|
||||
foreach (var env in environments)
|
||||
{
|
||||
var policy = await _policyProvider.GetDefaultPolicyAsync(env, ct);
|
||||
versions.Add(new PolicyVersionSummary
|
||||
{
|
||||
Version = policy.Version,
|
||||
Digest = policy.ComputeDigest(),
|
||||
Environment = env,
|
||||
CreatedAt = policy.CreatedAt,
|
||||
IsActive = env == _environment
|
||||
});
|
||||
}
|
||||
|
||||
return new PolicyVersionListResponse
|
||||
{
|
||||
Versions = versions,
|
||||
ActiveVersion = versions.FirstOrDefault(v => v.IsActive)?.Version ?? versions[0].Version
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetCacheKey(string findingId) => $"ews:score:{findingId}";
|
||||
|
||||
private static EvidenceWeightedScoreResponse MapToResponse(
|
||||
|
||||
Reference in New Issue
Block a user