refactor(notify): merge Notifier WebService into Notify WebService

- Delete dead Notify Worker (NoOp handler)
- Move 51 source files (endpoints, contracts, services, compat stores)
- Transform namespaces from Notifier.WebService to Notify.WebService
- Update DI registrations, WebSocket support, v2 endpoint mapping
- Comment out notifier-web in compose, update gateway routes
- Update architecture docs, port registry, rollout matrix
- Notifier Worker stays as separate delivery engine container

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-04-08 13:17:13 +03:00
parent b3198a66c7
commit 9eec100204
75 changed files with 11218 additions and 1039 deletions

View File

@@ -21,6 +21,8 @@ using StellaOps.Notify.Persistence.Extensions;
using StellaOps.Notify.Persistence.Postgres;
using StellaOps.Notify.Persistence.Postgres.Models;
using StellaOps.Notify.Persistence.Postgres.Repositories;
// Alias to disambiguate from StellaOps.Notifier.Worker.Storage.INotifyAuditRepository
using INotifyAuditRepository = StellaOps.Notify.Persistence.Postgres.Repositories.INotifyAuditRepository;
using StellaOps.Notify.WebService.Contracts;
using StellaOps.Notify.WebService.Diagnostics;
using StellaOps.Notify.WebService.Extensions;
@@ -32,6 +34,27 @@ using StellaOps.Notify.WebService.Security;
using StellaOps.Notify.WebService.Services;
using StellaOps.Plugin.DependencyInjection;
using StellaOps.Router.AspNet;
// Notifier Worker shared types (correlation, simulation, security, escalation, etc.)
using StellaOps.Cryptography;
using StellaOps.Auth.Abstractions;
using StellaOps.Notify.Queue;
using StellaOps.Notify.WebService.Constants;
using StellaOps.Notify.WebService.Endpoints;
using StellaOps.Notify.WebService.Setup;
using StellaOps.Notify.WebService.Storage.Compat;
using StellaOps.Notifier.Worker.Channels;
using StellaOps.Notifier.Worker.Security;
using StellaOps.Notifier.Worker.StormBreaker;
using StellaOps.Notifier.Worker.DeadLetter;
using StellaOps.Notifier.Worker.Retention;
using StellaOps.Notifier.Worker.Observability;
using StellaOps.Notifier.Worker.Escalation;
using StellaOps.Notifier.Worker.Tenancy;
using StellaOps.Notifier.Worker.Templates;
using StellaOps.Notifier.Worker.Correlation;
using StellaOps.Notifier.Worker.Simulation;
using StellaOps.Notifier.Worker.Storage;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Immutable;
using System.Diagnostics;
@@ -102,6 +125,104 @@ builder.Services.AddSingleton<INotifyPluginRegistry, NotifyPluginRegistry>();
builder.Services.AddSingleton<INotifyChannelTestService, NotifyChannelTestService>();
builder.Services.AddSingleton<INotifyChannelHealthService, NotifyChannelHealthService>();
// =========================================================================
// Notifier v2 DI registrations (merged from Notifier WebService)
// =========================================================================
builder.Services.AddSingleton<ICryptoHmac, DefaultCryptoHmac>();
// Core correlation engine registrations required by incident and escalation flows.
builder.Services.AddCorrelationServices(builder.Configuration);
// Rule evaluation + simulation services power /api/v2/simulate* endpoints.
builder.Services.AddSingleton<StellaOps.Notify.Engine.INotifyRuleEvaluator, StellaOps.Notifier.Worker.Processing.DefaultNotifyRuleEvaluator>();
SimulationServiceExtensions.AddSimulationServices(builder.Services, builder.Configuration);
// Fallback no-op event queue for environments that do not configure a real backend.
builder.Services.TryAddSingleton<INotifyEventQueue, NullNotifyEventQueue>();
// In-memory storage for Notifier v2 endpoints (fully qualified to avoid ambiguity with Notify.Persistence types)
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyChannelRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyRuleRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyTemplateRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyDeliveryRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyAuditRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyLockRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<IInAppInboxStore, InMemoryInboxStore>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyInboxRepository, InMemoryInboxStore>();
builder.Services.AddSingleton<StellaOps.Notifier.Worker.Storage.INotifyLocalizationRepository, InMemoryNotifyRepositories>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyPackApprovalRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryPackApprovalRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyThrottleConfigRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryThrottleConfigRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyOperatorOverrideRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryOperatorOverrideRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyQuietHoursRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryQuietHoursRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyMaintenanceWindowRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryMaintenanceWindowRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyEscalationPolicyRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryEscalationPolicyRepository>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Storage.Compat.INotifyOnCallScheduleRepository, StellaOps.Notify.WebService.Storage.Compat.InMemoryOnCallScheduleRepository>();
// Correlation suppression services
builder.Services.Configure<SuppressionAuditOptions>(builder.Configuration.GetSection(SuppressionAuditOptions.SectionName));
builder.Services.Configure<OperatorOverrideOptions>(builder.Configuration.GetSection(OperatorOverrideOptions.SectionName));
builder.Services.AddSingleton<ISuppressionAuditLogger, InMemorySuppressionAuditLogger>();
builder.Services.AddSingleton<IThrottleConfigurationService, InMemoryThrottleConfigurationService>();
builder.Services.AddSingleton<IQuietHoursCalendarService, InMemoryQuietHoursCalendarService>();
builder.Services.AddSingleton<IOperatorOverrideService, InMemoryOperatorOverrideService>();
// Template service with enhanced renderer (worker contracts)
builder.Services.AddTemplateServices(options =>
{
var provenanceUrl = builder.Configuration["notifier:provenance:baseUrl"];
if (!string.IsNullOrWhiteSpace(provenanceUrl))
{
options.ProvenanceBaseUrl = provenanceUrl;
}
});
// Localization resolver with fallback chain
builder.Services.AddSingleton<StellaOps.Notify.Models.ILocalizationResolver, StellaOps.Notify.WebService.Services.DefaultLocalizationResolver>();
// Security services (ack tokens, webhook, HTML sanitizer, tenant isolation)
builder.Services.Configure<AckTokenOptions>(builder.Configuration.GetSection("notifier:security:ackToken"));
builder.Services.AddSingleton<IAckTokenService, HmacAckTokenService>();
builder.Services.Configure<WebhookSecurityOptions>(builder.Configuration.GetSection("notifier:security:webhook"));
builder.Services.AddSingleton<IWebhookSecurityService, InMemoryWebhookSecurityService>();
builder.Services.AddSingleton<IHtmlSanitizer, DefaultHtmlSanitizer>();
builder.Services.Configure<TenantIsolationOptions>(builder.Configuration.GetSection("notifier:security:tenantIsolation"));
builder.Services.AddSingleton<ITenantIsolationValidator, InMemoryTenantIsolationValidator>();
// Observability, dead-letter, and retention services
builder.Services.AddSingleton<INotifyMetrics, DefaultNotifyMetrics>();
builder.Services.AddSingleton<IDeadLetterService, InMemoryDeadLetterService>();
builder.Services.AddSingleton<IRetentionPolicyService, DefaultRetentionPolicyService>();
// Escalation and on-call services
builder.Services.AddEscalationServices(builder.Configuration);
// Storm breaker services
builder.Services.AddStormBreakerServices(builder.Configuration);
// Additional security services (signing, webhook validation)
builder.Services.AddNotifierSecurityServices(builder.Configuration);
// Tenancy services (context accessor, RLS enforcement, channel resolution, notification enrichment)
builder.Services.AddNotifierTenancy(builder.Configuration);
// Notifier WebService template/renderer services
builder.Services.AddSingleton<StellaOps.Notify.WebService.Services.INotifyTemplateService, StellaOps.Notify.WebService.Services.NotifyTemplateService>();
builder.Services.AddSingleton<StellaOps.Notify.WebService.Services.INotifyTemplateRenderer, StellaOps.Notify.WebService.Services.AdvancedTemplateRenderer>();
// Notifier authorization policies
builder.Services.AddAuthorization(options =>
{
options.AddStellaOpsScopePolicy(NotifierPolicies.NotifyViewer, StellaOpsScopes.NotifyViewer);
options.AddStellaOpsScopePolicy(NotifierPolicies.NotifyOperator, StellaOpsScopes.NotifyOperator);
options.AddStellaOpsScopePolicy(NotifierPolicies.NotifyAdmin, StellaOpsScopes.NotifyAdmin);
options.AddStellaOpsScopePolicy(NotifierPolicies.NotifyEscalate, StellaOpsScopes.NotifyEscalate);
});
builder.Services.AddHealthChecks();
// =========================================================================
ConfigureAuthentication(builder, bootstrapOptions, builder.Configuration);
ConfigureRateLimiting(builder, bootstrapOptions);
@@ -129,8 +250,38 @@ var resolvedOptions = app.Services.GetRequiredService<IOptions<NotifyWebServiceO
await InitialiseAsync(app.Services, readyStatus, app.Logger, resolvedOptions);
ConfigureRequestPipeline(app, bootstrapOptions, routerEnabled);
// Enable WebSocket support for live incident feed (merged from Notifier)
app.UseWebSockets(new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromSeconds(30)
});
// Tenant context middleware (from Notifier merge)
app.UseTenantContext();
ConfigureEndpoints(app);
// =========================================================================
// Notifier v2 endpoint mappings (merged from Notifier WebService)
// =========================================================================
app.MapNotifyApiV2();
app.MapRuleEndpoints();
app.MapTemplateEndpoints();
app.MapIncidentEndpoints();
app.MapIncidentLiveFeed();
app.MapSimulationEndpoints();
app.MapQuietHoursEndpoints();
app.MapThrottleEndpoints();
app.MapOperatorOverrideEndpoints();
app.MapEscalationEndpoints();
app.MapStormBreakerEndpoints();
app.MapLocalizationEndpoints();
app.MapFallbackEndpoints();
app.MapSecurityEndpoints();
app.MapObservabilityEndpoints();
// =========================================================================
// Refresh Router endpoint cache
app.TryRefreshStellaRouterEndpoints(routerEnabled);