feat(email): export send attempt metadata
CI and Deploy / test (pull_request) Failing after 4m32s
CI and Deploy / deploy (pull_request) Has been skipped

Add content-free provider delivery history to encrypted and daily owner exports, exclude payload hashes, and lock in tenant-safe hard-delete cascades.
This commit is contained in:
cesnimda
2026-08-10 00:48:32 +02:00
parent 14f8d4e928
commit aff34cc645
6 changed files with 120 additions and 2 deletions
@@ -114,6 +114,15 @@ public sealed class BackgroundWorkerTenantTests
["Data:Root"] = root,
});
await fixture.SeedJobsAsync();
await using (var seedScope = fixture.Provider.CreateAsyncScope())
{
var db = seedScope.ServiceProvider.GetRequiredService<JobTrackerContext>();
var jobs = await db.JobApplications.IgnoreQueryFilters().OrderBy(job => job.OwnerUserId).ToListAsync();
db.EmailSendAttempts.AddRange(
new EmailSendAttempt { Id = Guid.NewGuid(), OwnerUserId = "user-1", JobApplicationId = jobs[0].Id, Provider = "gmail", ClientRequestId = Guid.NewGuid().ToString(), PayloadHash = new string('a', 64), Status = EmailSendStatuses.Sent, CreatedAtUtc = DateTime.UtcNow },
new EmailSendAttempt { Id = Guid.NewGuid(), OwnerUserId = "user-2", JobApplicationId = jobs[1].Id, Provider = "microsoft", ClientRequestId = Guid.NewGuid().ToString(), PayloadHash = new string('b', 64), Status = EmailSendStatuses.Failed, FailureCategory = "rejected", CreatedAtUtc = DateTime.UtcNow });
await db.SaveChangesAsync();
}
var environment = new Mock<IHostEnvironment>();
environment.SetupGet(x => x.ContentRootPath).Returns(root);
try
@@ -129,7 +138,18 @@ public sealed class BackgroundWorkerTenantTests
var files = Directory.GetFiles(Path.Combine(root, "exports"), "*.json");
Assert.Equal(2, files.Length);
Assert.DoesNotContain(files, path => path.Contains("user-1", StringComparison.Ordinal) || path.Contains("user-2", StringComparison.Ordinal));
var owners = files.Select(path => JsonDocument.Parse(System.IO.File.ReadAllText(path)).RootElement.GetProperty("OwnerUserId").GetString()).Order().ToArray();
var owners = new List<string?>();
foreach (var path in files)
{
using var document = JsonDocument.Parse(System.IO.File.ReadAllText(path));
var rootElement = document.RootElement;
var owner = rootElement.GetProperty("OwnerUserId").GetString();
owners.Add(owner);
var attempt = Assert.Single(rootElement.GetProperty("EmailSendAttempts").EnumerateArray());
Assert.Equal(owner == "user-1" ? "gmail" : "microsoft", attempt.GetProperty("Provider").GetString());
Assert.False(attempt.TryGetProperty("PayloadHash", out _));
}
owners.Sort(StringComparer.Ordinal);
Assert.Equal(new[] { "user-1", "user-2" }, owners);
Assert.Empty(Directory.GetFiles(Path.Combine(root, "exports"), "*.tmp"));
}