< Summary

Information
Class: AsiBackbone.Core.HostIntegration.HostAccountabilityLifecycleEvent
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/HostIntegration/HostAccountabilityLifecycleEvent.cs
Line coverage
28%
Covered lines: 9
Uncovered lines: 23
Coverable lines: 32
Total lines: 90
Line coverage: 28.1%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ExecutionStarted(...)100%210%
FromExecutionReceipt(...)100%11100%
AddMetadata(...)0%110100%
AddOptional(...)0%620%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/HostIntegration/HostAccountabilityLifecycleEvent.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2using AsiBackbone.Core.Audit;
 3
 4namespace AsiBackbone.Core.HostIntegration;
 5
 6/// <summary>
 7/// Creates append-only audit lifecycle events that bind a governed decision to host execution evidence.
 8/// </summary>
 9public static class HostAccountabilityLifecycleEvent
 10{
 11    /// <summary>
 12    /// Creates a gateway-execution-started lifecycle event for one logical operation and attempt.
 13    /// </summary>
 14    public static AuditResidueLifecycleEvent ExecutionStarted(
 15        IAsiBackboneAuditResidue residue,
 16        string operationExecutionId,
 17        string? executionAttemptId = null,
 18        string? decisionAuditRecordId = null,
 19        string? eventId = null,
 20        DateTimeOffset? occurredUtc = null,
 21        IReadOnlyDictionary<string, string>? metadata = null)
 22    {
 023        ArgumentNullException.ThrowIfNull(residue);
 024        ArgumentException.ThrowIfNullOrWhiteSpace(operationExecutionId);
 25
 026        SortedDictionary<string, string> lifecycleMetadata = new(StringComparer.Ordinal);
 027        AddMetadata(lifecycleMetadata, metadata);
 028        lifecycleMetadata[HostAccountabilityMetadataKeys.OperationExecutionId] = operationExecutionId.Trim();
 029        AddOptional(lifecycleMetadata, HostAccountabilityMetadataKeys.ExecutionAttemptId, executionAttemptId);
 030        AddOptional(lifecycleMetadata, HostAccountabilityMetadataKeys.DecisionAuditRecordId, decisionAuditRecordId);
 31
 032        return AuditResidueLifecycleEvent.FromResidue(
 033            AuditResidueLifecycleStage.GatewayExecutionStarted,
 034            residue,
 035            eventId: eventId,
 036            occurredUtc: occurredUtc,
 037            outcome: "Started",
 038            metadata: new ReadOnlyDictionary<string, string>(lifecycleMetadata));
 39    }
 40
 41    /// <summary>
 42    /// Creates a gateway-execution-completed lifecycle event from a typed host execution receipt.
 43    /// </summary>
 44    /// <remarks>
 45    /// The existing completion stage remains stable. Committed, failed, rolled-back, and no-mutation
 46    /// distinctions are carried by the typed receipt outcome and stable metadata keys rather than by
 47    /// expanding the lifecycle-stage enum.
 48    /// </remarks>
 49    public static AuditResidueLifecycleEvent FromExecutionReceipt(
 50        IAsiBackboneAuditResidue residue,
 51        GovernedOperationExecutionReceipt receipt,
 52        string? eventId = null,
 53        IReadOnlyDictionary<string, string>? metadata = null)
 54    {
 2055        ArgumentNullException.ThrowIfNull(residue);
 2056        ArgumentNullException.ThrowIfNull(receipt);
 57
 2058        return AuditResidueLifecycleEvent.FromResidue(
 2059            AuditResidueLifecycleStage.GatewayExecutionCompleted,
 2060            residue,
 2061            eventId: eventId,
 2062            occurredUtc: receipt.CompletedUtc,
 2063            outcome: receipt.PersistenceOutcome.ToString(),
 2064            metadata: receipt.ToLifecycleMetadata(metadata));
 65    }
 66
 67    private static void AddMetadata(SortedDictionary<string, string> destination, IReadOnlyDictionary<string, string>? m
 68    {
 069        if (metadata is null)
 70        {
 071            return;
 72        }
 73
 074        foreach (KeyValuePair<string, string> item in metadata)
 75        {
 076            if (!string.IsNullOrWhiteSpace(item.Key))
 77            {
 078                destination[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 79            }
 80        }
 081    }
 82
 83    private static void AddOptional(SortedDictionary<string, string> destination, string key, string? value)
 84    {
 085        if (!string.IsNullOrWhiteSpace(value))
 86        {
 087            destination[key] = value.Trim();
 88        }
 089    }
 90}