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:
@@ -2,8 +2,10 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using StellaOps.Notifier.WebService.Constants;
|
||||
using StellaOps.Notifier.WebService.Contracts;
|
||||
using StellaOps.Notifier.WebService.Extensions;
|
||||
using StellaOps.Auth.ServerIntegration.Tenancy;
|
||||
using StellaOps.Notifier.Worker.Dispatch;
|
||||
using StellaOps.Notifier.Worker.Storage;
|
||||
using StellaOps.Notifier.Worker.Templates;
|
||||
@@ -26,7 +28,9 @@ public static class NotifyApiEndpoints
|
||||
{
|
||||
var group = app.MapGroup("/api/v2/notify")
|
||||
.WithTags("Notify")
|
||||
.WithOpenApi();
|
||||
.WithOpenApi()
|
||||
.RequireAuthorization(NotifierPolicies.NotifyViewer)
|
||||
.RequireTenant();
|
||||
|
||||
// Rules CRUD
|
||||
MapRulesEndpoints(group);
|
||||
@@ -57,7 +61,8 @@ public static class NotifyApiEndpoints
|
||||
var response = rules.Select(MapRuleToResponse).ToList();
|
||||
|
||||
return Results.Ok(response);
|
||||
});
|
||||
})
|
||||
.WithDescription("Returns all alert routing rules for the tenant. Rules define which events trigger notifications, which channels receive them, and any throttle or digest settings applied.");
|
||||
|
||||
group.MapGet("/rules/{ruleId}", async (
|
||||
HttpContext context,
|
||||
@@ -78,7 +83,8 @@ public static class NotifyApiEndpoints
|
||||
}
|
||||
|
||||
return Results.Ok(MapRuleToResponse(rule));
|
||||
});
|
||||
})
|
||||
.WithDescription("Retrieves a single alert routing rule by its identifier. Returns match criteria, actions, throttle settings, and audit metadata.");
|
||||
|
||||
group.MapPost("/rules", async (
|
||||
HttpContext context,
|
||||
@@ -108,7 +114,9 @@ public static class NotifyApiEndpoints
|
||||
}, cancellationToken);
|
||||
|
||||
return Results.Created($"/api/v2/notify/rules/{rule.RuleId}", MapRuleToResponse(rule));
|
||||
});
|
||||
})
|
||||
.WithDescription("Creates a new alert routing rule. The rule specifies event match criteria (kinds, namespaces, severities) and the notification actions to execute. An audit entry is written on creation.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapPut("/rules/{ruleId}", async (
|
||||
HttpContext context,
|
||||
@@ -145,7 +153,9 @@ public static class NotifyApiEndpoints
|
||||
}, cancellationToken);
|
||||
|
||||
return Results.Ok(MapRuleToResponse(updated));
|
||||
});
|
||||
})
|
||||
.WithDescription("Updates an existing alert routing rule. Only the provided fields are changed; match criteria, actions, throttle settings, and labels are merged. An audit entry is written on update.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapDelete("/rules/{ruleId}", async (
|
||||
HttpContext context,
|
||||
@@ -176,7 +186,9 @@ public static class NotifyApiEndpoints
|
||||
}, cancellationToken);
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
})
|
||||
.WithDescription("Permanently removes an alert routing rule. Future events will no longer be matched against this rule. An audit entry is written on deletion.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
}
|
||||
|
||||
private static void MapTemplatesEndpoints(RouteGroupBuilder group)
|
||||
@@ -214,7 +226,8 @@ public static class NotifyApiEndpoints
|
||||
var response = templates.Select(MapTemplateToResponse).ToList();
|
||||
|
||||
return Results.Ok(response);
|
||||
});
|
||||
})
|
||||
.WithDescription("Lists all notification templates for the tenant, with optional filtering by key prefix, channel type, and locale. Templates define the rendered message body used by notification rules.");
|
||||
|
||||
group.MapGet("/templates/{templateId}", async (
|
||||
HttpContext context,
|
||||
@@ -235,7 +248,8 @@ public static class NotifyApiEndpoints
|
||||
}
|
||||
|
||||
return Results.Ok(MapTemplateToResponse(template));
|
||||
});
|
||||
})
|
||||
.WithDescription("Retrieves a single notification template by its identifier. Returns the template body, channel type, locale, render mode, and audit metadata.");
|
||||
|
||||
group.MapPost("/templates", async (
|
||||
HttpContext context,
|
||||
@@ -294,7 +308,9 @@ public static class NotifyApiEndpoints
|
||||
return result.IsNew
|
||||
? Results.Created($"/api/v2/notify/templates/{request.TemplateId}", MapTemplateToResponse(created!))
|
||||
: Results.Ok(MapTemplateToResponse(created!));
|
||||
});
|
||||
})
|
||||
.WithDescription("Creates or updates a notification template. The template body supports Scriban syntax with access to event payload fields. Validation is performed before persisting; an error is returned for invalid syntax.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapDelete("/templates/{templateId}", async (
|
||||
HttpContext context,
|
||||
@@ -317,7 +333,9 @@ public static class NotifyApiEndpoints
|
||||
}
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
})
|
||||
.WithDescription("Permanently removes a notification template. Rules referencing this template will fall back to channel defaults on the next delivery. An audit entry is written on deletion.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapPost("/templates/preview", async (
|
||||
HttpContext context,
|
||||
@@ -393,7 +411,9 @@ public static class NotifyApiEndpoints
|
||||
Format = rendered.Format.ToString(),
|
||||
Warnings = warnings
|
||||
});
|
||||
});
|
||||
})
|
||||
.WithDescription("Renders a template against a sample event payload without sending any notification. Accepts either an existing templateId or an inline templateBody. Returns the rendered body, subject, and any template warnings.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapPost("/templates/validate", (
|
||||
HttpContext context,
|
||||
@@ -413,7 +433,8 @@ public static class NotifyApiEndpoints
|
||||
errors = result.Errors,
|
||||
warnings = result.Warnings
|
||||
});
|
||||
});
|
||||
})
|
||||
.WithDescription("Validates a template body for syntax correctness without persisting it. Returns isValid, a list of errors, and any non-fatal warnings.");
|
||||
}
|
||||
|
||||
private static void MapIncidentsEndpoints(RouteGroupBuilder group)
|
||||
@@ -465,7 +486,8 @@ public static class NotifyApiEndpoints
|
||||
TotalCount = incidents.Count,
|
||||
NextCursor = queryResult.ContinuationToken
|
||||
});
|
||||
});
|
||||
})
|
||||
.WithDescription("Returns a paginated list of notification incidents for the tenant, grouped by event ID. Supports filtering by status, event kind prefix, time range, and cursor-based pagination.");
|
||||
|
||||
group.MapPost("/incidents/{incidentId}/ack", async (
|
||||
HttpContext context,
|
||||
@@ -489,7 +511,9 @@ public static class NotifyApiEndpoints
|
||||
}, cancellationToken);
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
})
|
||||
.WithDescription("Acknowledges an incident, recording the actor and an optional comment in the audit log. Does not stop an active escalation; use the escalation stop endpoint for that.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
|
||||
group.MapPost("/incidents/{incidentId}/resolve", async (
|
||||
HttpContext context,
|
||||
@@ -514,7 +538,9 @@ public static class NotifyApiEndpoints
|
||||
}, cancellationToken);
|
||||
|
||||
return Results.NoContent();
|
||||
});
|
||||
})
|
||||
.WithDescription("Marks an incident as resolved, recording the actor, resolution reason, and optional comment in the audit log. Subsequent notifications for this event kind will continue to be processed normally.")
|
||||
.RequireAuthorization(NotifierPolicies.NotifyOperator);
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
Reference in New Issue
Block a user