< Summary

Information
Class: AsiBackbone.Core.Signing.CanonicalPayloadOptions
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Signing/CanonicalPayloadOptions.cs
Line coverage
100%
Covered lines: 36
Uncovered lines: 0
Coverable lines: 36
Total lines: 103
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
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_Default()100%11100%
get_CanonicalizationVersion()100%11100%
get_HashAlgorithm()100%11100%
get_MetadataKeyAllowList()100%11100%
Create(...)100%44100%
AllowsMetadataKey(...)100%22100%
NormalizeMetadataKeyAllowList(...)100%44100%

File(s)

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

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Signing;
 4
 5/// <summary>
 6/// Configures canonical payload construction and hashing behavior.
 7/// </summary>
 8/// <remarks>
 9/// Metadata is excluded from canonical payloads unless an explicit allow-list is supplied. This prevents host-specific 
 10/// </remarks>
 11public sealed class CanonicalPayloadOptions
 12{
 13    /// <summary>
 14    /// Gets the default canonicalization version for deterministic AsiBackbone JSON signing payloads.
 15    /// </summary>
 16    public const string DefaultCanonicalizationVersion = "asibackbone.canonical-json.v1";
 17
 18    /// <summary>
 19    /// Gets the default hash algorithm used by the provider-neutral payload hasher.
 20    /// </summary>
 21    public const string DefaultHashAlgorithm = "SHA-256";
 22
 223    private static readonly IReadOnlyCollection<string> EmptyMetadataKeyAllowList =
 224        new ReadOnlyCollection<string>(Array.Empty<string>());
 25
 1626    private CanonicalPayloadOptions(
 1627        string canonicalizationVersion,
 1628        string hashAlgorithm,
 1629        IReadOnlyCollection<string> metadataKeyAllowList)
 30    {
 1631        ArgumentException.ThrowIfNullOrWhiteSpace(canonicalizationVersion);
 1632        ArgumentException.ThrowIfNullOrWhiteSpace(hashAlgorithm);
 33
 1634        CanonicalizationVersion = canonicalizationVersion.Trim();
 1635        HashAlgorithm = hashAlgorithm.Trim();
 1636        MetadataKeyAllowList = metadataKeyAllowList;
 1637    }
 38
 39    /// <summary>
 40    /// Gets default canonical payload options.
 41    /// </summary>
 1342    public static CanonicalPayloadOptions Default { get; } = Create();
 43
 44    /// <summary>
 45    /// Gets the canonicalization version stamped onto payloads.
 46    /// </summary>
 3147    public string CanonicalizationVersion { get; }
 48
 49    /// <summary>
 50    /// Gets the hash algorithm descriptor used by <see cref="CanonicalPayloadHasher" />.
 51    /// </summary>
 252    public string HashAlgorithm { get; }
 53
 54    /// <summary>
 55    /// Gets the metadata keys that may be included in canonical payloads.
 56    /// </summary>
 4557    public IReadOnlyCollection<string> MetadataKeyAllowList { get; }
 58
 59    /// <summary>
 60    /// Creates canonical payload options.
 61    /// </summary>
 62    public static CanonicalPayloadOptions Create(
 63        IEnumerable<string>? metadataKeyAllowList = null,
 64        string? canonicalizationVersion = null,
 65        string? hashAlgorithm = null)
 66    {
 1667        return new CanonicalPayloadOptions(
 1668            string.IsNullOrWhiteSpace(canonicalizationVersion)
 1669                ? DefaultCanonicalizationVersion
 1670                : canonicalizationVersion,
 1671            string.IsNullOrWhiteSpace(hashAlgorithm)
 1672                ? DefaultHashAlgorithm
 1673                : hashAlgorithm,
 1674            NormalizeMetadataKeyAllowList(metadataKeyAllowList));
 75    }
 76
 77    /// <summary>
 78    /// Determines whether the supplied metadata key may be included in a canonical payload.
 79    /// </summary>
 80    public bool AllowsMetadataKey(string key)
 81    {
 4482        return !string.IsNullOrWhiteSpace(key)
 4483            && MetadataKeyAllowList.Contains(key.Trim(), StringComparer.Ordinal);
 84    }
 85
 86    private static IReadOnlyCollection<string> NormalizeMetadataKeyAllowList(IEnumerable<string>? metadataKeyAllowList)
 87    {
 1688        if (metadataKeyAllowList is null)
 89        {
 290            return EmptyMetadataKeyAllowList;
 91        }
 92
 1493        string[] normalizedKeys = [.. metadataKeyAllowList
 1994            .Where(key => !string.IsNullOrWhiteSpace(key))
 1695            .Select(key => key.Trim())
 1496            .Distinct(StringComparer.Ordinal)
 1897            .OrderBy(key => key, StringComparer.Ordinal)];
 98
 1499        return normalizedKeys.Length == 0
 14100            ? EmptyMetadataKeyAllowList
 14101            : new ReadOnlyCollection<string>(normalizedKeys);
 102    }
 103}