< 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: 91
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;
 3using AsiBackbone.Core.Signing;
 4
 5namespace AsiBackbone.Core.HostIntegration;
 6
 7/// <summary>
 8/// Creates append-only audit lifecycle events that bind a governed decision to host execution evidence.
 9/// </summary>
 10public static class HostAccountabilityLifecycleEvent
 11{
 12    /// <summary>
 13    /// Creates a gateway-execution-started lifecycle event for one logical operation and attempt.
 14    /// </summary>
 15    public static DecisionReceiptLifecycleEvent ExecutionStarted(
 16        IDecisionReceipt residue,
 17        string operationExecutionId,
 18        string? executionAttemptId = null,
 19        string? decisionAuditRecordId = null,
 20        string? eventId = null,
 21        DateTimeOffset? occurredUtc = null,
 22        IReadOnlyDictionary<string, string>? metadata = null)
 23    {
 024        ArgumentNullException.ThrowIfNull(residue);
 025        ArgumentException.ThrowIfNullOrWhiteSpace(operationExecutionId);
 26
 027        SortedDictionary<string, string> lifecycleMetadata = new(StringComparer.Ordinal);
 028        AddMetadata(lifecycleMetadata, metadata);
 029        lifecycleMetadata[HostAccountabilityMetadataKeys.OperationExecutionId] = operationExecutionId.Trim();
 030        AddOptional(lifecycleMetadata, HostAccountabilityMetadataKeys.ExecutionAttemptId, executionAttemptId);
 031        AddOptional(lifecycleMetadata, HostAccountabilityMetadataKeys.DecisionAuditRecordId, decisionAuditRecordId);
 32
 033        return DecisionReceiptLifecycleEvent.FromDecisionReceipt(
 034            DecisionReceiptLifecycleStage.GatewayExecutionStarted,
 035            residue,
 036            eventId: eventId,
 037            occurredUtc: occurredUtc,
 038            outcome: "Started",
 039            metadata: new ReadOnlyDictionary<string, string>(lifecycleMetadata));
 40    }
 41
 42    /// <summary>
 43    /// Creates a gateway-execution-completed lifecycle event from a typed host execution receipt.
 44    /// </summary>
 45    /// <remarks>
 46    /// The existing completion stage remains stable. Committed, failed, rolled-back, and no-mutation
 47    /// distinctions are carried by the typed receipt outcome and stable metadata keys rather than by
 48    /// expanding the lifecycle-stage enum.
 49    /// </remarks>
 50    public static DecisionReceiptLifecycleEvent FromExecutionReceipt(
 51        IDecisionReceipt residue,
 52        GovernedOperationExecutionReceipt receipt,
 53        string? eventId = null,
 54        IReadOnlyDictionary<string, string>? metadata = null)
 55    {
 1956        ArgumentNullException.ThrowIfNull(residue);
 1957        ArgumentNullException.ThrowIfNull(receipt);
 58
 1959        return DecisionReceiptLifecycleEvent.FromDecisionReceipt(
 1960            DecisionReceiptLifecycleStage.GatewayExecutionCompleted,
 1961            residue,
 1962            eventId: eventId,
 1963            occurredUtc: receipt.CompletedUtc,
 1964            outcome: CanonicalEnumWireNames.ForPersistenceOutcome(receipt.PersistenceOutcome),
 1965            metadata: receipt.ToLifecycleMetadata(metadata));
 66    }
 67
 68    private static void AddMetadata(SortedDictionary<string, string> destination, IReadOnlyDictionary<string, string>? m
 69    {
 070        if (metadata is null)
 71        {
 072            return;
 73        }
 74
 075        foreach (KeyValuePair<string, string> item in metadata)
 76        {
 077            if (!string.IsNullOrWhiteSpace(item.Key))
 78            {
 079                destination[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 80            }
 81        }
 082    }
 83
 84    private static void AddOptional(SortedDictionary<string, string> destination, string key, string? value)
 85    {
 086        if (!string.IsNullOrWhiteSpace(value))
 87        {
 088            destination[key] = value.Trim();
 89        }
 090    }
 91}