< Summary

Information
Class: AsiBackbone.Core.Signing.SigningRequest
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/SigningRequest.cs
Line coverage
100%
Covered lines: 37
Uncovered lines: 0
Coverable lines: 37
Total lines: 104
Line coverage: 100%
Branch coverage
81%
Covered branches: 13
Total branches: 16
Branch coverage: 81.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
get_SigningHash()100%11100%
get_HashAlgorithm()100%11100%
get_Purpose()100%11100%
get_KeyId()100%11100%
get_KeyVersion()100%11100%
get_Metadata()100%11100%
get_HasMetadata()100%11100%
NormalizeOptional(...)100%22100%
NormalizeMetadata(...)78.57%1414100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/SigningRequest.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Signing;
 4
 5/// <summary>
 6/// Represents a provider-neutral request to sign a precomputed artifact hash.
 7/// </summary>
 8/// <remarks>
 9/// The request is intentionally hash-oriented so production providers can use key-based signing APIs without exposing r
 10/// </remarks>
 11public sealed class SigningRequest
 12{
 513    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 514        new ReadOnlyDictionary<string, string>(
 515            new Dictionary<string, string>(StringComparer.Ordinal));
 16
 17    /// <summary>
 18    /// Initializes a new instance of the <see cref="SigningRequest" /> class.
 19    /// </summary>
 1820    public SigningRequest(
 1821        string signingHash,
 1822        string? hashAlgorithm = null,
 1823        string? purpose = null,
 1824        string? keyId = null,
 1825        string? keyVersion = null,
 1826        IReadOnlyDictionary<string, string>? metadata = null)
 27    {
 1828        ArgumentException.ThrowIfNullOrWhiteSpace(signingHash);
 29
 1830        SigningHash = signingHash.Trim();
 1831        HashAlgorithm = NormalizeOptional(hashAlgorithm);
 1832        Purpose = NormalizeOptional(purpose);
 1833        KeyId = NormalizeOptional(keyId);
 1834        KeyVersion = NormalizeOptional(keyVersion);
 1835        Metadata = NormalizeMetadata(metadata);
 1836    }
 37
 38    /// <summary>
 39    /// Gets the precomputed artifact hash to sign.
 40    /// </summary>
 2941    public string SigningHash { get; }
 42
 43    /// <summary>
 44    /// Gets the hash algorithm or descriptor associated with <see cref="SigningHash" />, when supplied.
 45    /// </summary>
 3646    public string? HashAlgorithm { get; }
 47
 48    /// <summary>
 49    /// Gets the host-defined signing purpose, when supplied.
 50    /// </summary>
 3251    public string? Purpose { get; }
 52
 53    /// <summary>
 54    /// Gets the requested signing key identifier, when supplied.
 55    /// </summary>
 3256    public string? KeyId { get; }
 57
 58    /// <summary>
 59    /// Gets the requested signing key version, when supplied.
 60    /// </summary>
 3461    public string? KeyVersion { get; }
 62
 63    /// <summary>
 64    /// Gets additional provider-neutral request metadata.
 65    /// </summary>
 2466    public IReadOnlyDictionary<string, string> Metadata { get; }
 67
 68    /// <summary>
 69    /// Gets a value indicating whether metadata is present.
 70    /// </summary>
 171    public bool HasMetadata => Metadata.Count > 0;
 72
 73    private static string? NormalizeOptional(string? value)
 74    {
 7275        return string.IsNullOrWhiteSpace(value)
 7276            ? null
 7277            : value.Trim();
 78    }
 79
 80    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 81        IReadOnlyDictionary<string, string>? metadata)
 82    {
 1883        if (metadata is null || metadata.Count == 0)
 84        {
 1285            return EmptyMetadata;
 86        }
 87
 688        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 89
 5090        foreach (KeyValuePair<string, string> item in metadata)
 91        {
 1992            if (string.IsNullOrWhiteSpace(item.Key))
 93            {
 94                continue;
 95            }
 96
 1897            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 98        }
 99
 6100        return normalizedMetadata.Count == 0
 6101            ? EmptyMetadata
 6102            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 103    }
 104}