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
@@ -13,10 +13,16 @@ public sealed class DevelopmentDataSeederTests
private readonly IEmailTemplateRepository _templates = Substitute.For<IEmailTemplateRepository>();
private readonly INotificationServiceRepository _services = Substitute.For<INotificationServiceRepository>();
public DevelopmentDataSeederTests()
{
_services.SaveAsync(Arg.Any<NotificationServiceInfo>(), true, Arg.Any<CancellationToken>())
.Returns(call => { call.Arg<NotificationServiceInfo>().Id = Guid.NewGuid(); return Task.CompletedTask; });
}
[Fact]
public async Task SeedAsync_WhenConfigurationIsMissing_CreatesMailpitChannelAndTestTemplate()
{
_channels.GetByServiceAsync("TestService", Arg.Any<CancellationToken>())
_channels.GetByServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
.Returns(Array.Empty<EmailChannel>());
_templates.GetAsync("TestService", "TestEmail", "en", Arg.Any<CancellationToken>())
.Returns((EmailTemplate?)null);
@@ -39,10 +45,10 @@ public sealed class DevelopmentDataSeederTests
[Fact]
public async Task SeedAsync_WhenConfigurationExists_DoesNotDuplicateOrOverwriteIt()
{
_channels.GetByServiceAsync("TestService", Arg.Any<CancellationToken>())
_channels.GetByServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
.Returns([new EmailChannel
{
ServiceName = "TestService",
ServiceId = Guid.NewGuid(),
EmailChannelType = EmailChannelType.Smtp,
Settings = new SmtpChannelSettings()
}]);
@@ -75,7 +81,7 @@ public sealed class DevelopmentDataSeederTests
private static bool IsMailpitChannel(EmailChannel channel)
{
return channel.ServiceName == "TestService" &&
return channel.ServiceId != Guid.Empty &&
channel.IsActive &&
channel.Settings is SmtpChannelSettings smtp &&
smtp.Host == "mailpit" &&