< Summary

Information
Class: AsiBackbone.Core.Integrity.AuditIntegrityVerificationResult
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Integrity/AuditIntegrityVerificationResult.cs
Line coverage
90%
Covered lines: 68
Uncovered lines: 7
Coverable lines: 75
Total lines: 163
Line coverage: 90.6%
Branch coverage
83%
Covered branches: 20
Total branches: 24
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
.ctor(...)50%2295.65%
get_IsValid()100%11100%
get_Category()100%11100%
get_Status()100%210%
get_FailureCode()100%11100%
get_FailureMessage()100%210%
get_ChainId()100%11100%
get_Sequence()100%210%
get_RecordId()100%210%
get_SafeMetadata()100%11100%
Valid(...)100%11100%
Failed(...)85%2020100%
NormalizeOptional(...)100%22100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Integrity/AuditIntegrityVerificationResult.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Integrity;
 4
 5/// <summary>
 6/// Represents the outcome of provider-neutral audit integrity verification.
 7/// </summary>
 8public sealed class AuditIntegrityVerificationResult
 9{
 010    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 011        new ReadOnlyDictionary<string, string>(new Dictionary<string, string>(StringComparer.Ordinal));
 12
 3213    private AuditIntegrityVerificationResult(
 3214        bool isValid,
 3215        AuditIntegrityVerificationCategory category,
 3216        string status,
 3217        string? failureCode,
 3218        string? failureMessage,
 3219        string? chainId,
 3220        long? sequence,
 3221        string? recordId,
 3222        IReadOnlyDictionary<string, string> safeMetadata)
 23    {
 3224        ArgumentException.ThrowIfNullOrWhiteSpace(status);
 25
 3226        if (!Enum.IsDefined(category))
 27        {
 028            throw new ArgumentOutOfRangeException(nameof(category), category, "Verification category must be defined.");
 29        }
 30
 3231        IsValid = isValid;
 3232        Category = category;
 3233        Status = status.Trim();
 3234        FailureCode = NormalizeOptional(failureCode);
 3235        FailureMessage = NormalizeOptional(failureMessage);
 3236        ChainId = NormalizeOptional(chainId);
 3237        Sequence = sequence;
 3238        RecordId = NormalizeOptional(recordId);
 3239        SafeMetadata = safeMetadata;
 3240    }
 41
 42    /// <summary>
 43    /// Gets a value indicating whether the integrity chain verified successfully.
 44    /// </summary>
 3245    public bool IsValid { get; }
 46
 47    /// <summary>
 48    /// Gets the provider-neutral verification category.
 49    /// </summary>
 3050    public AuditIntegrityVerificationCategory Category { get; }
 51
 52    /// <summary>
 53    /// Gets a provider-neutral status string.
 54    /// </summary>
 055    public string Status { get; }
 56
 57    /// <summary>
 58    /// Gets the failure code when verification did not succeed.
 59    /// </summary>
 2860    public string? FailureCode { get; }
 61
 62    /// <summary>
 63    /// Gets the failure message when verification did not succeed.
 64    /// </summary>
 065    public string? FailureMessage { get; }
 66
 67    /// <summary>
 68    /// Gets the chain identifier associated with the result, when known.
 69    /// </summary>
 270    public string? ChainId { get; }
 71
 72    /// <summary>
 73    /// Gets the sequence associated with the result, when known.
 74    /// </summary>
 075    public long? Sequence { get; }
 76
 77    /// <summary>
 78    /// Gets the record identifier associated with the result, when known.
 79    /// </summary>
 080    public string? RecordId { get; }
 81
 82    /// <summary>
 83    /// Gets safe-to-log verification metadata.
 84    /// </summary>
 2085    public IReadOnlyDictionary<string, string> SafeMetadata { get; }
 86
 87    /// <summary>
 88    /// Creates a valid verification result.
 89    /// </summary>
 90    public static AuditIntegrityVerificationResult Valid(string chainId, long linkCount, string tipHash)
 91    {
 492        Dictionary<string, string> metadata = new(StringComparer.Ordinal)
 493        {
 494            ["chain_id"] = chainId,
 495            ["link_count"] = linkCount.ToString(System.Globalization.CultureInfo.InvariantCulture),
 496            ["tip_hash"] = tipHash
 497        };
 98
 499        return new AuditIntegrityVerificationResult(
 4100            true,
 4101            AuditIntegrityVerificationCategory.Valid,
 4102            "Valid",
 4103            null,
 4104            null,
 4105            chainId,
 4106            linkCount,
 4107            null,
 4108            new ReadOnlyDictionary<string, string>(metadata));
 109    }
 110
 111    /// <summary>
 112    /// Creates a failed verification result.
 113    /// </summary>
 114    public static AuditIntegrityVerificationResult Failed(
 115        AuditIntegrityVerificationCategory category,
 116        string failureCode,
 117        string? failureMessage = null,
 118        AuditIntegrityLink? link = null,
 119        IReadOnlyDictionary<string, string>? metadata = null)
 120    {
 28121        ArgumentException.ThrowIfNullOrWhiteSpace(failureCode);
 122
 28123        Dictionary<string, string> safeMetadata = new(StringComparer.Ordinal)
 28124        {
 28125            ["category"] = category.ToString(),
 28126            ["failure_code"] = failureCode.Trim()
 28127        };
 128
 28129        if (link is not null)
 130        {
 26131            safeMetadata["chain_id"] = link.ChainId;
 26132            safeMetadata["record_id"] = link.RecordId;
 26133            safeMetadata["sequence"] = link.Sequence.ToString(System.Globalization.CultureInfo.InvariantCulture);
 134        }
 135
 28136        if (metadata is not null)
 137        {
 72138            foreach (KeyValuePair<string, string> item in metadata)
 139            {
 24140                if (!string.IsNullOrWhiteSpace(item.Key))
 141                {
 24142                    safeMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 143                }
 144            }
 145        }
 146
 28147        return new AuditIntegrityVerificationResult(
 28148            false,
 28149            category,
 28150            "Failed",
 28151            failureCode,
 28152            failureMessage,
 28153            link?.ChainId,
 28154            link?.Sequence,
 28155            link?.RecordId,
 28156            safeMetadata.Count == 0 ? EmptyMetadata : new ReadOnlyDictionary<string, string>(safeMetadata));
 157    }
 158
 159    private static string? NormalizeOptional(string? value)
 160    {
 128161        return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
 162    }
 163}