up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Symbols Server CI / symbols-smoke (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-24 20:57:49 +02:00
parent 46c8c47d06
commit 7c39058386
92 changed files with 3549 additions and 157 deletions

View File

@@ -1,28 +1,42 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using StellaOps.Notifier.WebService.Contracts;
using StellaOps.Notifier.WebService.Setup;
using StellaOps.Notify.Storage.Mongo;
using StellaOps.Notify.Storage.Mongo.Documents;
using StellaOps.Notify.Storage.Mongo.Repositories;
using StellaOps.Notify.Models;
using StellaOps.Notify.Queue;
var builder = WebApplication.CreateBuilder(args);
var isTesting = builder.Environment.IsEnvironment("Testing");
builder.Configuration
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables(prefix: "NOTIFIER_");
var mongoSection = builder.Configuration.GetSection("notifier:storage:mongo");
builder.Services.AddNotifyMongoStorage(mongoSection);
// OpenAPI cache resolved inline for simplicity in tests
builder.Services.AddSingleton<TimeProvider>(TimeProvider.System);
if (!isTesting)
{
var mongoSection = builder.Configuration.GetSection("notifier:storage:mongo");
builder.Services.AddNotifyMongoStorage(mongoSection);
builder.Services.AddHostedService<MongoInitializationHostedService>();
builder.Services.AddHostedService<PackApprovalTemplateSeeder>();
}
// Fallback no-op event queue for environments that do not configure a real backend.
builder.Services.TryAddSingleton<INotifyEventQueue, NullNotifyEventQueue>();
builder.Services.AddHealthChecks();
builder.Services.AddHostedService<MongoInitializationHostedService>();
var app = builder.Build();
@@ -48,6 +62,7 @@ app.MapPost("/api/v1/notify/pack-approvals", async (
INotifyLockRepository locks,
INotifyPackApprovalRepository packApprovals,
INotifyAuditRepository audit,
INotifyEventQueue? eventQueue,
TimeProvider timeProvider) =>
{
var tenantId = context.Request.Headers["X-StellaOps-Tenant"].ToString();
@@ -112,6 +127,38 @@ app.MapPost("/api/v1/notify/pack-approvals", async (
};
await audit.AppendAsync(auditEntry, context.RequestAborted).ConfigureAwait(false);
if (eventQueue is not null)
{
var payload = JsonSerializer.SerializeToNode(new
{
request.PackId,
request.Kind,
request.Decision,
request.Policy,
request.ResumeToken,
request.Summary,
request.Labels
}) ?? new JsonObject();
var notifyEvent = NotifyEvent.Create(
eventId: request.EventId != Guid.Empty ? request.EventId : Guid.NewGuid(),
kind: request.Kind ?? "pack.approval",
tenant: tenantId,
ts: request.IssuedAt != default ? request.IssuedAt : timeProvider.GetUtcNow(),
payload: payload,
actor: request.Actor,
version: "1");
await eventQueue.PublishAsync(
new NotifyQueueEventMessage(
notifyEvent,
stream: "notify:events",
idempotencyKey: lockKey,
partitionKey: tenantId,
traceId: context.TraceIdentifier),
context.RequestAborted).ConfigureAwait(false);
}
}
catch
{
@@ -177,7 +224,23 @@ app.MapPost("/api/v1/notify/pack-approvals/{packId}/ack", async (
return Results.NoContent();
});
app.MapGet("/.well-known/openapi", () => Results.Content("# notifier openapi stub\nopenapi: 3.1.0\npaths: {}", "application/yaml"));
app.MapGet("/.well-known/openapi", (HttpContext context) =>
{
context.Response.Headers["X-OpenAPI-Scope"] = "notify";
context.Response.Headers.ETag = "\"notifier-oas-stub\"";
const string stub = """
# notifier openapi stub
openapi: 3.1.0
info:
title: StellaOps Notifier
paths:
/api/v1/notify/quiet-hours: {}
/api/v1/notify/incidents: {}
""";
return Results.Text(stub, "application/yaml", Encoding.UTF8);
});
static object Error(string code, string message, HttpContext context) => new
{