using Microsoft.Extensions.DependencyInjection; using Tiku.Application.Security; using Tiku.Domain.Tenancy; using Tiku.Infrastructure.Persistence; using Tiku.IntegrationTests.Api; namespace Tiku.IntegrationTests; public sealed class SystemScopeAuditTests { [Fact] public async Task Descriptor_is_required_and_success_is_audited() { await using var factory = new ApiTestFactory(); using var outer = factory.CreateSystemScope("Resolve execution scope"); var executionScope = outer.ServiceProvider.GetRequiredService(); await Assert.ThrowsAsync(() => executionScope.ExecuteAsync( new SystemScopeRequest(null, SystemScopeCallerType.Worker, "worker", "", "job-1"), (_, _) => Task.CompletedTask)); await Assert.ThrowsAsync(() => executionScope.ExecuteAsync( new SystemScopeRequest(null, SystemScopeCallerType.Worker, "worker", "missing target", "job-2"), (_, _) => Task.CompletedTask)); var correlationId = Guid.NewGuid().ToString("N"); var tenantId = Guid.NewGuid(); await factory.SeedAsync(new Tenant { Id = tenantId, Slug = tenantId.ToString("N"), Name = "System Scope Tenant" }); await executionScope.ExecuteAsync( new SystemScopeRequest(tenantId, SystemScopeCallerType.Worker, "background-worker", "test audit", correlationId), (_, _) => Task.CompletedTask); using var verification = factory.CreateSystemScope("Verify execution scope audit"); var dbContext = verification.ServiceProvider.GetRequiredService(); Assert.Contains(dbContext.AuditLogs, item => item.Action == "system_scope.entered" && item.TargetId == correlationId); Assert.Contains(dbContext.AuditLogs, item => item.Action == "system_scope.completed" && item.TargetId == correlationId); } [Fact] public async Task Failed_system_scope_rolls_back_business_write_and_persists_failure_audit() { await using var factory = new ApiTestFactory(); using var outer = factory.CreateSystemScope("Resolve execution scope"); var executionScope = outer.ServiceProvider.GetRequiredService(); var correlationId = Guid.NewGuid().ToString("N"); var tenantId = Guid.NewGuid(); await factory.SeedAsync(new Tenant { Id = tenantId, Slug = tenantId.ToString("N"), Name = "Existing Tenant" }); await Assert.ThrowsAsync(() => executionScope.ExecuteAsync( new SystemScopeRequest( tenantId, SystemScopeCallerType.Worker, "background-worker", "verify transactional rollback", correlationId), async (provider, cancellationToken) => { var dbContext = provider.GetRequiredService(); dbContext.TenantBrandings.Add(new TenantBranding { TenantId = tenantId, BrandName = "Must Roll Back" }); await dbContext.SaveChangesAsync(cancellationToken); throw new InvalidOperationException("expected failure"); })); using var verification = factory.CreateSystemScope("Verify failed execution scope audit"); var verificationDb = verification.ServiceProvider.GetRequiredService(); Assert.DoesNotContain(verificationDb.TenantBrandings, item => item.TenantId == tenantId); Assert.Contains(verificationDb.AuditLogs, item => item.Action == "system_scope.entered" && item.TargetId == correlationId); Assert.Contains(verificationDb.AuditLogs, item => item.Action == "system_scope.failed" && item.TargetId == correlationId); Assert.DoesNotContain(verificationDb.AuditLogs, item => item.Action == "system_scope.completed" && item.TargetId == correlationId); } }