Restructure solution layout by module
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StellaOps.Policy;
|
||||
using StellaOps.Policy.Engine.Services;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Endpoints;
|
||||
|
||||
internal static class PolicyCompilationEndpoints
|
||||
{
|
||||
private const string CompileRoute = "/api/policy/policies/{policyId}/versions/{version}:compile";
|
||||
|
||||
public static IEndpointRouteBuilder MapPolicyCompilation(this IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
endpoints.MapPost(CompileRoute, CompilePolicy)
|
||||
.WithName("CompilePolicy")
|
||||
.WithSummary("Compile and lint a policy DSL document.")
|
||||
.WithDescription("Compiles a stella-dsl@1 policy document and returns deterministic digest and statistics.")
|
||||
.Produces<PolicyCompileResponse>(StatusCodes.Status200OK)
|
||||
.Produces<ProblemHttpResult>(StatusCodes.Status400BadRequest)
|
||||
.RequireAuthorization(); // scopes enforced by policy middleware.
|
||||
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
private static IResult CompilePolicy(
|
||||
[FromRoute] string policyId,
|
||||
[FromRoute] int version,
|
||||
[FromBody] PolicyCompileRequest request,
|
||||
PolicyCompilationService compilationService)
|
||||
{
|
||||
if (request is null)
|
||||
{
|
||||
return Results.BadRequest(BuildProblem("ERR_POL_001", "Request body missing.", policyId, version));
|
||||
}
|
||||
|
||||
var result = compilationService.Compile(request);
|
||||
if (!result.Success)
|
||||
{
|
||||
return Results.BadRequest(BuildProblem("ERR_POL_001", "Policy compilation failed.", policyId, version, result.Diagnostics));
|
||||
}
|
||||
|
||||
var response = new PolicyCompileResponse(
|
||||
result.Digest!,
|
||||
result.Statistics ?? new PolicyCompilationStatistics(0, ImmutableDictionary<string, int>.Empty),
|
||||
ConvertDiagnostics(result.Diagnostics));
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
private static PolicyProblemDetails BuildProblem(string code, string message, string policyId, int version, ImmutableArray<PolicyIssue>? diagnostics = null)
|
||||
{
|
||||
var problem = new PolicyProblemDetails
|
||||
{
|
||||
Code = code,
|
||||
Title = "Policy compilation error",
|
||||
Detail = message,
|
||||
PolicyId = policyId,
|
||||
PolicyVersion = version
|
||||
};
|
||||
|
||||
if (diagnostics is { Length: > 0 } diag)
|
||||
{
|
||||
problem.Diagnostics = diag;
|
||||
}
|
||||
|
||||
return problem;
|
||||
}
|
||||
|
||||
private static ImmutableArray<PolicyDiagnosticDto> ConvertDiagnostics(ImmutableArray<PolicyIssue> issues)
|
||||
{
|
||||
if (issues.IsDefaultOrEmpty)
|
||||
{
|
||||
return ImmutableArray<PolicyDiagnosticDto>.Empty;
|
||||
}
|
||||
|
||||
var builder = ImmutableArray.CreateBuilder<PolicyDiagnosticDto>(issues.Length);
|
||||
foreach (var issue in issues)
|
||||
{
|
||||
if (issue.Severity != PolicyIssueSeverity.Warning)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Add(new PolicyDiagnosticDto(issue.Code, issue.Message, issue.Path));
|
||||
}
|
||||
|
||||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
private sealed class PolicyProblemDetails : ProblemDetails
|
||||
{
|
||||
public string Code { get; set; } = "ERR_POL_001";
|
||||
|
||||
public string? PolicyId { get; set; }
|
||||
|
||||
public int PolicyVersion { get; set; }
|
||||
|
||||
public ImmutableArray<PolicyIssue> Diagnostics { get; set; } = ImmutableArray<PolicyIssue>.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record PolicyCompileResponse(
|
||||
string Digest,
|
||||
PolicyCompilationStatistics Statistics,
|
||||
ImmutableArray<PolicyDiagnosticDto> Warnings);
|
||||
|
||||
internal sealed record PolicyDiagnosticDto(string Code, string Message, string Path);
|
||||
Reference in New Issue
Block a user