up
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-26 20:23:28 +02:00
parent 4831c7fcb0
commit d63af51f84
139 changed files with 8010 additions and 2795 deletions

View File

@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Policy.Engine.Domain;
using StellaOps.Policy.Engine.Services;
namespace StellaOps.Policy.Engine.Endpoints;
public static class EvidenceSummaryEndpoint
{
public static IEndpointRouteBuilder MapEvidenceSummaries(this IEndpointRouteBuilder routes)
{
routes.MapPost("/evidence/summary", HandleAsync)
.WithName("PolicyEngine.EvidenceSummary");
return routes;
}
private static IResult HandleAsync(
[FromBody] EvidenceSummaryRequest request,
EvidenceSummaryService service)
{
try
{
var response = service.Summarize(request);
return Results.Ok(response);
}
catch (ArgumentException ex)
{
return Results.Problem(ex.Message, statusCode: StatusCodes.Status400BadRequest);
}
}
}

View File

@@ -31,6 +31,19 @@ internal static class PolicyPackEndpoints
.Produces<PolicyRevisionDto>(StatusCodes.Status201Created)
.Produces<ProblemHttpResult>(StatusCodes.Status400BadRequest);
group.MapPost("/{packId}/revisions/{version:int}/bundle", CreateBundle)
.WithName("CreatePolicyBundle")
.WithSummary("Compile and sign a policy revision bundle for distribution.")
.Produces<PolicyBundleResponse>(StatusCodes.Status201Created)
.Produces<ProblemHttpResult>(StatusCodes.Status400BadRequest);
group.MapPost("/{packId}/revisions/{version:int}/evaluate", EvaluateRevision)
.WithName("EvaluatePolicyRevision")
.WithSummary("Evaluate a policy revision deterministically with in-memory caching.")
.Produces<PolicyEvaluationResponse>(StatusCodes.Status200OK)
.Produces<ProblemHttpResult>(StatusCodes.Status400BadRequest)
.Produces<ProblemHttpResult>(StatusCodes.Status404NotFound);
group.MapPost("/{packId}/revisions/{version:int}:activate", ActivateRevision)
.WithName("ActivatePolicyRevision")
.WithSummary("Activate an approved policy revision, enforcing two-person approval when required.")
@@ -217,6 +230,98 @@ internal static class PolicyPackEndpoints
};
}
private static async Task<IResult> CreateBundle(
HttpContext context,
[FromRoute] string packId,
[FromRoute] int version,
[FromBody] PolicyBundleRequest request,
PolicyBundleService bundleService,
CancellationToken cancellationToken)
{
var scopeResult = ScopeAuthorization.RequireScope(context, StellaOpsScopes.PolicyEdit);
if (scopeResult is not null)
{
return scopeResult;
}
if (request is null)
{
return Results.BadRequest(new ProblemDetails
{
Title = "Invalid request",
Detail = "Request body is required.",
Status = StatusCodes.Status400BadRequest
});
}
var response = await bundleService.CompileAndStoreAsync(packId, version, request, cancellationToken).ConfigureAwait(false);
if (!response.Success)
{
return Results.BadRequest(response);
}
return Results.Created($"/api/policy/packs/{packId}/revisions/{version}/bundle", response);
}
private static async Task<IResult> EvaluateRevision(
HttpContext context,
[FromRoute] string packId,
[FromRoute] int version,
[FromBody] PolicyEvaluationRequest request,
PolicyRuntimeEvaluator evaluator,
CancellationToken cancellationToken)
{
var scopeResult = ScopeAuthorization.RequireScope(context, StellaOpsScopes.PolicyRead);
if (scopeResult is not null)
{
return scopeResult;
}
if (request is null)
{
return Results.BadRequest(new ProblemDetails
{
Title = "Invalid request",
Detail = "Request body is required.",
Status = StatusCodes.Status400BadRequest
});
}
if (!string.Equals(request.PackId, packId, StringComparison.OrdinalIgnoreCase) || request.Version != version)
{
return Results.BadRequest(new ProblemDetails
{
Title = "Path/body mismatch",
Detail = "packId/version in body must match route parameters.",
Status = StatusCodes.Status400BadRequest
});
}
try
{
var response = await evaluator.EvaluateAsync(request, cancellationToken).ConfigureAwait(false);
return Results.Ok(response);
}
catch (InvalidOperationException)
{
return Results.NotFound(new ProblemDetails
{
Title = "Bundle not found",
Detail = "Policy bundle must be created before evaluation.",
Status = StatusCodes.Status404NotFound
});
}
catch (ArgumentException ex)
{
return Results.BadRequest(new ProblemDetails
{
Title = "Invalid request",
Detail = ex.Message,
Status = StatusCodes.Status400BadRequest
});
}
}
private static string? ResolveActorId(HttpContext context)
{
var user = context.User;