< 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
 423    private static readonly IReadOnlyCollection<string> EmptyMetadataKeyAllowList =
 424        new ReadOnlyCollection<string>(Array.Empty<string>());
 25
 3426    private CanonicalPayloadOptions(
 3427        string canonicalizationVersion,
 3428        string hashAlgorithm,
 3429        IReadOnlyCollection<string> metadataKeyAllowList)
 30    {
 3431        ArgumentException.ThrowIfNullOrWhiteSpace(canonicalizationVersion);
 3432        ArgumentException.ThrowIfNullOrWhiteSpace(hashAlgorithm);
 33
 3434        CanonicalizationVersion = canonicalizationVersion.Trim();
 3435        HashAlgorithm = hashAlgorithm.Trim();
 3436        MetadataKeyAllowList = metadataKeyAllowList;
 3437    }
 38
 39    /// <summary>
 40    /// Gets default canonical payload options.
 41    /// </summary>
 4642    public static CanonicalPayloadOptions Default { get; } = Create();
 43
 44    /// <summary>
 45    /// Gets the canonicalization version stamped onto payloads.
 46    /// </summary>
 8647    public string CanonicalizationVersion { get; }
 48
 49    /// <summary>
 50    /// Gets the hash algorithm descriptor used by <see cref="CanonicalPayloadHasher" />.
 51    /// </summary>
 452    public string HashAlgorithm { get; }
 53
 54    /// <summary>
 55    /// Gets the metadata keys that may be included in canonical payloads.
 56    /// </summary>
 9857    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    {
 3467        return new CanonicalPayloadOptions(
 3468            string.IsNullOrWhiteSpace(canonicalizationVersion)
 3469                ? DefaultCanonicalizationVersion
 3470                : canonicalizationVersion,
 3471            string.IsNullOrWhiteSpace(hashAlgorithm)
 3472                ? DefaultHashAlgorithm
 3473                : hashAlgorithm,
 3474            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    {
 9682        return !string.IsNullOrWhiteSpace(key)
 9683            && MetadataKeyAllowList.Contains(key.Trim(), StringComparer.Ordinal);
 84    }
 85
 86    private static IReadOnlyCollection<string> NormalizeMetadataKeyAllowList(IEnumerable<string>? metadataKeyAllowList)
 87    {
 3488        if (metadataKeyAllowList is null)
 89        {
 490            return EmptyMetadataKeyAllowList;
 91        }
 92
 3093        string[] normalizedKeys = [.. metadataKeyAllowList
 4094            .Where(key => !string.IsNullOrWhiteSpace(key))
 3495            .Select(key => key.Trim())
 3096            .Distinct(StringComparer.Ordinal)
 3897            .OrderBy(key => key, StringComparer.Ordinal)];
 98
 3099        return normalizedKeys.Length == 0
 30100            ? EmptyMetadataKeyAllowList
 30101            : new ReadOnlyCollection<string>(normalizedKeys);
 102    }
 103}