< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Command.Auditing.AuditLogWriter
Assembly: ArturRios.Heimdall.Command
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Application/ArturRios.Heimdall.Command/Auditing/AuditLogWriter.cs
Line coverage
100%
Covered lines: 22
Uncovered lines: 0
Coverable lines: 22
Total lines: 43
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage
100%
Covered methods: 2
Fully covered methods: 2
Total methods: 2
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
WriteAsync()100%66100%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Application/ArturRios.Heimdall.Command/Auditing/AuditLogWriter.cs

#LineLine coverage
 1using ArturRios.Data.Relational.Core.Interfaces;
 2using ArturRios.Heimdall.Domain.Entities;
 3using ArturRios.Heimdall.Shared.Security;
 4
 5namespace ArturRios.Heimdall.Command.Auditing;
 6
 10437public class AuditLogWriter(IAsyncRepository<AuditLog, long> repository, IActorAccessor actorAccessor)
 8    : IAuditLogWriter
 9{
 10    /// <summary>Longest failure reason stored; matches AUDIT_LOG.failure_reason's column.</summary>
 11    private const int MaxFailureReasonLength = 500;
 12
 13    public async Task WriteAsync(string action, Guid? targetId, bool succeeded, string? failureReason)
 14    {
 104315        var entry = new AuditLog
 104316        {
 104317            PublicId = Guid.NewGuid(),
 104318            ActorPersonId = actorAccessor.ActorPersonId,
 104319            ActorRole = actorAccessor.ActorRole,
 104320            Action = action,
 104321            TargetId = targetId,
 104322            Succeeded = succeeded,
 104323            // Truncated rather than allowed to fail the insert: a reason too long for the column
 104324            // would otherwise turn a recorded refusal into no record at all, which is the one
 104325            // outcome the trail must not have.
 104326            FailureReason = failureReason is { Length: > MaxFailureReasonLength }
 104327                ? failureReason[..MaxFailureReasonLength]
 104328                : failureReason,
 104329            CreatedAt = DateTime.UtcNow
 104330        };
 31
 32        // The repository reports a failed insert in its output instead of throwing. Surface it, so
 33        // the caller's catch-and-warn sees it; the message carries the action and the repository's
 34        // own error text only, never the entry's actor or other personal data.
 104335        var output = await repository.CreateAsync(entry);
 36
 104337        if (!output.Success)
 38        {
 739            throw new InvalidOperationException(
 740                $"Failed to save audit log entry for {action}: {string.Join("; ", output.Errors)}");
 41        }
 103642    }
 43}