feat(push): add service-owned firebase channels and delivery

Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation.

Ref: IT-1074
This commit is contained in:
2026-10-24 12:31:35 +03:00
parent b30dba93e8
commit 1631786ce2
105 changed files with 3838 additions and 147 deletions
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
internal sealed class SendEmailService : ISendEmailService
{
private readonly IEmailChannelRepository _channelRepository;
private readonly INotificationServiceRepository _services;
private readonly IEmailChannelUsageRepository _usageRepository;
private readonly IEmailTemplateService _templateService;
private readonly IEmailTemplateRenderingService _templateRenderingService;
@@ -18,6 +19,7 @@ internal sealed class SendEmailService : ISendEmailService
public SendEmailService(
IEmailChannelRepository channelRepository,
INotificationServiceRepository services,
IEmailChannelUsageRepository usageRepository,
IEmailTemplateService templateService,
IEmailTemplateRenderingService templateRenderingService,
@@ -26,6 +28,7 @@ internal sealed class SendEmailService : ISendEmailService
ILogger<SendEmailService> logger)
{
_channelRepository = channelRepository;
_services = services;
_usageRepository = usageRepository;
_templateService = templateService;
_templateRenderingService = templateRenderingService;
@@ -93,7 +96,9 @@ internal sealed class SendEmailService : ISendEmailService
private async Task<EmailChannel> ResolveChannelAsync(string serviceName, CancellationToken ct)
{
var channels = await _channelRepository.GetByServiceAsync(serviceName, ct);
var service = await _services.GetByNameAsync(serviceName, ct)
?? throw new InvalidOperationException($"Service '{serviceName}' does not exist.");
var channels = await _channelRepository.GetByServiceAsync(service.Id, ct);
return channels
.Where(c => c.IsActive)