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

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Findings.Ledger.WebService.Contracts;
using StellaOps.Findings.Ledger.WebService.Services;
@@ -17,13 +18,15 @@ public static class WebhookEndpoints
public static void MapWebhookEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/api/v1/scoring/webhooks")
.WithTags("Webhooks");
.WithTags("Webhooks")
.RequireTenant();
// POST /api/v1/scoring/webhooks - Register webhook
// Rate limit: 10/min (via API Gateway)
group.MapPost("/", RegisterWebhook)
.WithName("RegisterScoringWebhook")
.WithDescription("Register a webhook for score change notifications")
.WithSummary("Register a webhook for score change notifications")
.WithDescription("Registers an HTTPS callback URL to receive score change notifications. Supports optional HMAC-SHA256 signing via a shared secret, finding pattern filters, minimum score change threshold, and bucket transition triggers. The webhook is activated immediately upon registration.")
.Produces<WebhookResponse>(StatusCodes.Status201Created)
.ProducesValidationProblem()
.RequireAuthorization(ScoringAdminPolicy);
@@ -32,7 +35,8 @@ public static class WebhookEndpoints
// Rate limit: 10/min (via API Gateway)
group.MapGet("/", ListWebhooks)
.WithName("ListScoringWebhooks")
.WithDescription("List all registered webhooks")
.WithSummary("List all registered webhooks")
.WithDescription("Returns all currently registered score change webhooks with their configuration, including URL, filter patterns, minimum score change threshold, and creation timestamp. Secrets are not returned in responses.")
.Produces<WebhookListResponse>(StatusCodes.Status200OK)
.RequireAuthorization(ScoringAdminPolicy);
@@ -40,7 +44,8 @@ public static class WebhookEndpoints
// Rate limit: 10/min (via API Gateway)
group.MapGet("/{id:guid}", GetWebhook)
.WithName("GetScoringWebhook")
.WithDescription("Get a specific webhook by ID")
.WithSummary("Get a specific webhook by ID")
.WithDescription("Returns the configuration of a specific webhook by its UUID. Inactive webhooks (soft-deleted) return 404. Secrets are not included in the response body.")
.Produces<WebhookResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.RequireAuthorization(ScoringAdminPolicy);
@@ -49,7 +54,8 @@ public static class WebhookEndpoints
// Rate limit: 10/min (via API Gateway)
group.MapPut("/{id:guid}", UpdateWebhook)
.WithName("UpdateScoringWebhook")
.WithDescription("Update a webhook configuration")
.WithSummary("Update a webhook configuration")
.WithDescription("Replaces the full configuration of an existing webhook. All fields in the request body are applied as-is; partial updates are not supported. To update a secret, supply the new secret value; omitting the secret field retains the existing secret.")
.Produces<WebhookResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.ProducesValidationProblem()
@@ -59,7 +65,8 @@ public static class WebhookEndpoints
// Rate limit: 10/min (via API Gateway)
group.MapDelete("/{id:guid}", DeleteWebhook)
.WithName("DeleteScoringWebhook")
.WithDescription("Delete a webhook")
.WithSummary("Delete a webhook")
.WithDescription("Permanently removes a webhook registration by its UUID. No further score change notifications will be delivered to the associated URL after deletion. Returns 204 on success, 404 if the webhook does not exist.")
.Produces(StatusCodes.Status204NoContent)
.Produces(StatusCodes.Status404NotFound)
.RequireAuthorization(ScoringAdminPolicy);
@@ -67,7 +74,8 @@ public static class WebhookEndpoints
private static Results<Created<WebhookResponse>, ValidationProblem> RegisterWebhook(
[FromBody] RegisterWebhookRequest request,
[FromServices] IWebhookStore store)
[FromServices] IWebhookStore store,
[FromServices] IStellaOpsTenantAccessor tenantAccessor)
{
// Validate URL
if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri) ||
@@ -86,7 +94,8 @@ public static class WebhookEndpoints
}
private static Ok<WebhookListResponse> ListWebhooks(
[FromServices] IWebhookStore store)
[FromServices] IWebhookStore store,
[FromServices] IStellaOpsTenantAccessor tenantAccessor)
{
var webhooks = store.List();
var response = new WebhookListResponse
@@ -100,7 +109,8 @@ public static class WebhookEndpoints
private static Results<Ok<WebhookResponse>, NotFound> GetWebhook(
Guid id,
[FromServices] IWebhookStore store)
[FromServices] IWebhookStore store,
[FromServices] IStellaOpsTenantAccessor tenantAccessor)
{
var webhook = store.Get(id);
if (webhook is null || !webhook.IsActive)
@@ -114,7 +124,8 @@ public static class WebhookEndpoints
private static Results<Ok<WebhookResponse>, NotFound, ValidationProblem> UpdateWebhook(
Guid id,
[FromBody] RegisterWebhookRequest request,
[FromServices] IWebhookStore store)
[FromServices] IWebhookStore store,
[FromServices] IStellaOpsTenantAccessor tenantAccessor)
{
// Validate URL
if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri) ||
@@ -137,7 +148,8 @@ public static class WebhookEndpoints
private static Results<NoContent, NotFound> DeleteWebhook(
Guid id,
[FromServices] IWebhookStore store)
[FromServices] IWebhookStore store,
[FromServices] IStellaOpsTenantAccessor tenantAccessor)
{
if (!store.Delete(id))
{