UDT-010: Infraestructura de Auditoría y Trazabilidad — Closes #6 #14

Merged
dmolinari merged 14 commits from feature/UDT-010 into main 2026-04-16 20:30:17 +00:00
7 changed files with 25 additions and 1 deletions
Showing only changes of commit c95bc7fe01 - Show all commits

View File

@@ -9,6 +9,7 @@ namespace SIGCM2.Api.Tests.Audit;
/// TransactionScope with AsyncFlowEnabled must NOT escalate to MSDTC when /// TransactionScope with AsyncFlowEnabled must NOT escalate to MSDTC when
/// multiple SqlConnections share a single connection string. If this fails, /// multiple SqlConnections share a single connection string. If this fails,
/// UDT-010 must pivot to explicit IUnitOfWork. /// UDT-010 must pivot to explicit IUnitOfWork.
[Collection("ApiIntegration")]
public sealed class TransactionScopeSpikeTests public sealed class TransactionScopeSpikeTests
{ {
private const string ConnectionString = private const string ConnectionString =

View File

@@ -10,6 +10,7 @@ namespace SIGCM2.Api.Tests.Audit;
/// REQ-AUD-1: SYSTEM_VERSIONING active on catalog entities (smoke: Usuario + Usuario_History query). /// REQ-AUD-1: SYSTEM_VERSIONING active on catalog entities (smoke: Usuario + Usuario_History query).
/// REQ-AUD-2: dbo.AuditEvent exists, accepts valid INSERT, CHECK constraints reject invalid data. /// REQ-AUD-2: dbo.AuditEvent exists, accepts valid INSERT, CHECK constraints reject invalid data.
/// REQ-SEC-1: dbo.SecurityEvent exists, CK_SecurityEvent_Result rejects invalid Result. /// REQ-SEC-1: dbo.SecurityEvent exists, CK_SecurityEvent_Result rejects invalid Result.
[Collection("ApiIntegration")]
public sealed class V010MigrationTests : IClassFixture<SIGCM2.TestSupport.TestWebAppFactory> public sealed class V010MigrationTests : IClassFixture<SIGCM2.TestSupport.TestWebAppFactory>
{ {
private const string ConnectionString = private const string ConnectionString =

View File

@@ -36,6 +36,11 @@ public class RefreshTokenRepositoryTests : IAsyncLifetime
new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Rol"),
new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "Permiso"),
new Respawn.Graph.Table("dbo", "RolPermiso"), new Respawn.Graph.Table("dbo", "RolPermiso"),
// UDT-010: *_History tables are system-versioned — engine rejects direct DELETE.
new Respawn.Graph.Table("dbo", "Usuario_History"),
new Respawn.Graph.Table("dbo", "Rol_History"),
new Respawn.Graph.Table("dbo", "Permiso_History"),
new Respawn.Graph.Table("dbo", "RolPermiso_History"),
] ]
}); });

View File

@@ -19,7 +19,9 @@ public class RolRepositoryTests : IAsyncLifetime
_connection = new SqlConnection(ConnectionString); _connection = new SqlConnection(ConnectionString);
await _connection.OpenAsync(); await _connection.OpenAsync();
// Clean Usuario first (FK), then custom Rol codes created by tests. // Clean RefreshToken first (FK to Usuario), then Usuario (FK to Rol), then custom Rol codes.
// Residual RefreshTokens from prior test suites would violate FK_RefreshToken_Usuario otherwise.
await _connection.ExecuteAsync("DELETE FROM dbo.RefreshToken;");
await _connection.ExecuteAsync("DELETE FROM dbo.Usuario;"); await _connection.ExecuteAsync("DELETE FROM dbo.Usuario;");
await _connection.ExecuteAsync("DELETE FROM dbo.Rol WHERE Codigo NOT IN ('admin','cajero','operador_ctacte','picadora','jefe_publicidad','productor','diagramacion','reportes');"); await _connection.ExecuteAsync("DELETE FROM dbo.Rol WHERE Codigo NOT IN ('admin','cajero','operador_ctacte','picadora','jefe_publicidad','productor','diagramacion','reportes');");
// Ensure canonical Rol seeds exist (idempotent — previous test classes may have wiped them via Respawn). // Ensure canonical Rol seeds exist (idempotent — previous test classes may have wiped them via Respawn).

View File

@@ -28,6 +28,11 @@ public class UsuarioRepositoryTests : IAsyncLifetime
new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Rol"),
new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "Permiso"),
new Respawn.Graph.Table("dbo", "RolPermiso"), new Respawn.Graph.Table("dbo", "RolPermiso"),
// UDT-010: *_History tables are system-versioned — engine rejects direct DELETE.
new Respawn.Graph.Table("dbo", "Usuario_History"),
new Respawn.Graph.Table("dbo", "Rol_History"),
new Respawn.Graph.Table("dbo", "Permiso_History"),
new Respawn.Graph.Table("dbo", "RolPermiso_History"),
] ]
}); });

View File

@@ -32,6 +32,11 @@ public sealed class UsuarioRepository_PermisosTests : IAsyncLifetime
new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Rol"),
new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "Permiso"),
new Respawn.Graph.Table("dbo", "RolPermiso"), new Respawn.Graph.Table("dbo", "RolPermiso"),
// UDT-010: *_History tables are system-versioned — engine rejects direct DELETE.
new Respawn.Graph.Table("dbo", "Usuario_History"),
new Respawn.Graph.Table("dbo", "Rol_History"),
new Respawn.Graph.Table("dbo", "Permiso_History"),
new Respawn.Graph.Table("dbo", "RolPermiso_History"),
] ]
}); });

View File

@@ -31,6 +31,11 @@ public sealed class V009MigrationTests : IAsyncLifetime
new Respawn.Graph.Table("dbo", "Rol"), new Respawn.Graph.Table("dbo", "Rol"),
new Respawn.Graph.Table("dbo", "Permiso"), new Respawn.Graph.Table("dbo", "Permiso"),
new Respawn.Graph.Table("dbo", "RolPermiso"), new Respawn.Graph.Table("dbo", "RolPermiso"),
// UDT-010: *_History tables are system-versioned — engine rejects direct DELETE.
new Respawn.Graph.Table("dbo", "Usuario_History"),
new Respawn.Graph.Table("dbo", "Rol_History"),
new Respawn.Graph.Table("dbo", "Permiso_History"),
new Respawn.Graph.Table("dbo", "RolPermiso_History"),
] ]
}); });