feat(infra): AuditLogger + SecurityEventLogger impl (UDT-010 B6)
Composes the audit emission layer per design #D-8:
SIGCM2.Infrastructure/Audit/AuditLogger.cs (IAuditLogger):
- Enriches from IAuditContext (ActorUserId/ActorRoleId/Ip/UserAgent/CorrelationId).
- Sanitizes metadata via JsonSanitizer + AuditOptions.SanitizedKeys.
- Persists via IAuditEventRepository.InsertAsync.
- Fail-closed: throws AuditContextMissingException when ActorUserId is null.
- Translates Guid.Empty correlation id to null (DB column is nullable; Empty
indicates 'no middleware ran').
- Uses System.DateTime.UtcNow for occurredAt.
SIGCM2.Infrastructure/Audit/SecurityEventLogger.cs (ISecurityEventLogger):
- NOT fail-closed: null ActorUserId is valid (login failures, anonymous
permission.denied events).
- Ip/UserAgent pulled from IAuditContext; metadata sanitized the same way.
- Persists via ISecurityEventRepository.
DI: AddScoped for both loggers in AddInfrastructure.
Tests (Strict TDD, mocks for IAuditContext/IAuditEventRepository/
ISecurityEventRepository):
- AuditLoggerTests (6): happy path with full context, fail-closed null actor,
metadata sanitization, null metadata pass-through, repo-throws-bubbles-up
(critical for TransactionScope rollback), custom SanitizedKeys from options.
- SecurityEventLoggerTests (4): login.success with context, login.failure
with null actor + attemptedUsername, metadata sanitization,
permission.denied with both actor and attemptedUsername null.
Two initial failures were fixed by replacing 'null' literal arguments in
NSubstitute Received(...) assertions with Arg.Is<T?>(x => x == null) —
NSubstitute does not always match null literals when mixed with Arg.Any<T>().
Suite: 378/378 Application.Tests + 141/141 Api.Tests = 519/519 passing.
Refs: sdd/udt-010-auditoria-trazabilidad/{spec#REQ-AUD-4 #REQ-SEC-2/3, design#D-8, tasks#B6}
This commit is contained in:
@@ -74,6 +74,8 @@ public static class DependencyInjection
|
||||
services.AddScoped<IAuditContext, SIGCM2.Infrastructure.Audit.AuditContext>();
|
||||
services.AddScoped<IAuditEventRepository, SIGCM2.Infrastructure.Audit.AuditEventRepository>();
|
||||
services.AddScoped<ISecurityEventRepository, SIGCM2.Infrastructure.Audit.SecurityEventRepository>();
|
||||
services.AddScoped<IAuditLogger, SIGCM2.Infrastructure.Audit.AuditLogger>();
|
||||
services.AddScoped<ISecurityEventLogger, SIGCM2.Infrastructure.Audit.SecurityEventLogger>();
|
||||
|
||||
// Dispatcher
|
||||
services.AddScoped<IDispatcher, Dispatcher>();
|
||||
|
||||
Reference in New Issue
Block a user