< Summary

Information
Class: AsiBackbone.Core.Emissions.GovernanceEmissionEnvelope
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Emissions/GovernanceEmissionEnvelope.cs
Line coverage
100%
Covered lines: 181
Uncovered lines: 0
Coverable lines: 181
Total lines: 402
Line coverage: 100%
Branch coverage
88%
Covered branches: 39
Total branches: 44
Branch coverage: 88.6%
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%88100%
get_EnvelopeId()100%11100%
get_SchemaVersion()100%11100%
get_EventType()100%11100%
get_EventId()100%11100%
get_OccurredUtc()100%11100%
get_CreatedUtc()100%11100%
get_CorrelationId()100%11100%
get_AuditResidueId()100%11100%
get_LifecycleStage()100%11100%
get_LifecycleStageSequence()100%11100%
get_PolicyVersion()100%11100%
get_PolicyHash()100%11100%
get_TraceId()100%11100%
get_SpanId()100%11100%
get_ParentSpanId()100%11100%
get_OperationName()100%11100%
get_Outcome()100%11100%
get_ActorId()100%11100%
get_EmitterStatus()100%11100%
get_EmitterProvider()100%11100%
get_OutboxSequence()100%11100%
get_GatewayExecutionId()100%11100%
get_DecisionStage()100%11100%
get_Payload()100%11100%
get_Metadata()100%11100%
get_HasCorrelation()100%44100%
get_HasMetadata()100%11100%
Create(...)83.33%66100%
FromResidue(...)50%22100%
FromLifecycleEvent(...)50%22100%
NormalizeIdentifier(...)100%22100%
NormalizeOptional(...)100%22100%
NormalizeNonNegative(...)100%22100%
NormalizeMetadata(...)87.5%1616100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Emissions/GovernanceEmissionEnvelope.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2using AsiBackbone.Core.Audit;
 3using AsiBackbone.Core.Serialization;
 4
 5namespace AsiBackbone.Core.Emissions;
 6
 7/// <summary>
 8/// Represents a provider-neutral governance emission envelope that can be handed to outbox storage or downstream provid
 9/// </summary>
 10/// <remarks>
 11/// The envelope carries minimized governance context and safe diagnostics. It does not contain provider SDK payloads, c
 12/// </remarks>
 13public sealed class GovernanceEmissionEnvelope
 14{
 715    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 716        new ReadOnlyDictionary<string, string>(
 717            new Dictionary<string, string>(StringComparer.Ordinal));
 18
 143719    private GovernanceEmissionEnvelope(
 143720        string envelopeId,
 143721        string schemaVersion,
 143722        GovernanceEmissionEventType eventType,
 143723        string? eventId,
 143724        DateTimeOffset occurredUtc,
 143725        DateTimeOffset createdUtc,
 143726        string? correlationId,
 143727        string? auditResidueId,
 143728        AuditResidueLifecycleStage? lifecycleStage,
 143729        string? policyVersion,
 143730        string? policyHash,
 143731        string? traceId,
 143732        string? spanId,
 143733        string? parentSpanId,
 143734        string? operationName,
 143735        string? outcome,
 143736        string? actorId,
 143737        string? emitterStatus,
 143738        string? emitterProvider,
 143739        long? outboxSequence,
 143740        string? gatewayExecutionId,
 143741        string? decisionStage,
 143742        GovernanceEmissionPayload? payload,
 143743        IReadOnlyDictionary<string, string> metadata)
 44    {
 143745        ArgumentException.ThrowIfNullOrWhiteSpace(envelopeId);
 46
 143747        if (!Enum.IsDefined(eventType))
 48        {
 249            throw new ArgumentOutOfRangeException(nameof(eventType), eventType, "Governance emission event type must be 
 50        }
 51
 143552        if (lifecycleStage.HasValue && !Enum.IsDefined(lifecycleStage.Value))
 53        {
 254            throw new ArgumentOutOfRangeException(nameof(lifecycleStage), lifecycleStage, "Lifecycle stage must be defin
 55        }
 56
 143357        EnvelopeId = envelopeId.Trim();
 143358        SchemaVersion = AsiBackboneSchemaVersions.Normalize(schemaVersion);
 143359        EventType = eventType;
 143360        EventId = NormalizeOptional(eventId);
 143361        OccurredUtc = occurredUtc.ToUniversalTime();
 143362        CreatedUtc = createdUtc.ToUniversalTime();
 143363        CorrelationId = NormalizeOptional(correlationId);
 143364        AuditResidueId = NormalizeOptional(auditResidueId);
 143365        LifecycleStage = lifecycleStage;
 143366        LifecycleStageSequence = lifecycleStage.HasValue ? (int)lifecycleStage.Value : null;
 143367        PolicyVersion = NormalizeOptional(policyVersion);
 143368        PolicyHash = NormalizeOptional(policyHash);
 143369        TraceId = NormalizeOptional(traceId);
 143370        SpanId = NormalizeOptional(spanId);
 143371        ParentSpanId = NormalizeOptional(parentSpanId);
 143372        OperationName = NormalizeOptional(operationName);
 143373        Outcome = NormalizeOptional(outcome);
 143374        ActorId = NormalizeOptional(actorId);
 143375        EmitterStatus = NormalizeOptional(emitterStatus);
 143376        EmitterProvider = NormalizeOptional(emitterProvider);
 143377        OutboxSequence = NormalizeNonNegative(outboxSequence, nameof(outboxSequence));
 143178        GatewayExecutionId = NormalizeOptional(gatewayExecutionId);
 143179        DecisionStage = NormalizeOptional(decisionStage);
 143180        Payload = payload;
 143181        Metadata = metadata;
 143182    }
 83
 84    /// <summary>
 85    /// Gets the stable envelope identifier.
 86    /// </summary>
 104787    public string EnvelopeId { get; }
 88
 89    /// <summary>
 90    /// Gets the schema version for this provider-neutral envelope shape.
 91    /// </summary>
 102292    public string SchemaVersion { get; }
 93
 94    /// <summary>
 95    /// Gets the provider-neutral event category.
 96    /// </summary>
 101697    public GovernanceEmissionEventType EventType { get; }
 98
 99    /// <summary>
 100    /// Gets the source governance event identifier, when available.
 101    /// </summary>
 1000102    public string? EventId { get; }
 103
 104    /// <summary>
 105    /// Gets the UTC timestamp when the source governance event occurred.
 106    /// </summary>
 978107    public DateTimeOffset OccurredUtc { get; }
 108
 109    /// <summary>
 110    /// Gets the UTC timestamp when this emission envelope was created.
 111    /// </summary>
 976112    public DateTimeOffset CreatedUtc { get; }
 113
 114    /// <summary>
 115    /// Gets the correlation identifier that links the emission to the host workflow, when available.
 116    /// </summary>
 1051117    public string? CorrelationId { get; }
 118
 119    /// <summary>
 120    /// Gets the audit residue identifier linked to this emission, when available.
 121    /// </summary>
 1011122    public string? AuditResidueId { get; }
 123
 124    /// <summary>
 125    /// Gets the audit residue lifecycle stage linked to this emission, when available.
 126    /// </summary>
 1018127    public AuditResidueLifecycleStage? LifecycleStage { get; }
 128
 129    /// <summary>
 130    /// Gets the stable lifecycle stage sequence value, when a lifecycle stage is supplied.
 131    /// </summary>
 982132    public int? LifecycleStageSequence { get; }
 133
 134    /// <summary>
 135    /// Gets the policy version associated with the source governance event, when available.
 136    /// </summary>
 986137    public string? PolicyVersion { get; }
 138
 139    /// <summary>
 140    /// Gets the policy hash associated with the source governance event, when available.
 141    /// </summary>
 986142    public string? PolicyHash { get; }
 143
 144    /// <summary>
 145    /// Gets the trace identifier associated with the source governance event, when available.
 146    /// </summary>
 1000147    public string? TraceId { get; }
 148
 149    /// <summary>
 150    /// Gets the span identifier associated with the source governance event, when available.
 151    /// </summary>
 984152    public string? SpanId { get; }
 153
 154    /// <summary>
 155    /// Gets the parent span identifier associated with the source governance event, when available.
 156    /// </summary>
 984157    public string? ParentSpanId { get; }
 158
 159    /// <summary>
 160    /// Gets the operation name associated with the source governance event, when available.
 161    /// </summary>
 988162    public string? OperationName { get; }
 163
 164    /// <summary>
 165    /// Gets the outcome associated with the source governance event, when available.
 166    /// </summary>
 984167    public string? Outcome { get; }
 168
 169    /// <summary>
 170    /// Gets the actor identifier associated with the source governance event, when available.
 171    /// </summary>
 978172    public string? ActorId { get; }
 173
 174    /// <summary>
 175    /// Gets the provider-neutral emitter status, when available.
 176    /// </summary>
 1010177    public string? EmitterStatus { get; }
 178
 179    /// <summary>
 180    /// Gets the provider-neutral emitter provider name, when available.
 181    /// </summary>
 989182    public string? EmitterProvider { get; }
 183
 184    /// <summary>
 185    /// Gets the outbox sequence associated with the emission, when available.
 186    /// </summary>
 980187    public long? OutboxSequence { get; }
 188
 189    /// <summary>
 190    /// Gets the gateway execution identifier associated with the emission, when available.
 191    /// </summary>
 984192    public string? GatewayExecutionId { get; }
 193
 194    /// <summary>
 195    /// Gets the provider-neutral decision stage associated with the emission, when available.
 196    /// </summary>
 984197    public string? DecisionStage { get; }
 198
 199    /// <summary>
 200    /// Gets the minimized provider-neutral payload descriptor, when available.
 201    /// </summary>
 1024202    public GovernanceEmissionPayload? Payload { get; }
 203
 204    /// <summary>
 205    /// Gets minimized provider-neutral metadata.
 206    /// </summary>
 1032207    public IReadOnlyDictionary<string, string> Metadata { get; }
 208
 209    /// <summary>
 210    /// Gets a value indicating whether correlation metadata is available.
 211    /// </summary>
 16212    public bool HasCorrelation => CorrelationId is not null || TraceId is not null || AuditResidueId is not null;
 213
 214    /// <summary>
 215    /// Gets a value indicating whether envelope metadata is present.
 216    /// </summary>
 10217    public bool HasMetadata => Metadata.Count > 0;
 218
 219    /// <summary>
 220    /// Creates a provider-neutral governance emission envelope.
 221    /// </summary>
 222    public static GovernanceEmissionEnvelope Create(
 223        GovernanceEmissionEventType eventType,
 224        string? eventId = null,
 225        DateTimeOffset? occurredUtc = null,
 226        string? envelopeId = null,
 227        DateTimeOffset? createdUtc = null,
 228        string? schemaVersion = null,
 229        string? correlationId = null,
 230        string? auditResidueId = null,
 231        AuditResidueLifecycleStage? lifecycleStage = null,
 232        string? policyVersion = null,
 233        string? policyHash = null,
 234        string? traceId = null,
 235        string? spanId = null,
 236        string? parentSpanId = null,
 237        string? operationName = null,
 238        string? outcome = null,
 239        string? actorId = null,
 240        string? emitterStatus = null,
 241        string? emitterProvider = null,
 242        long? outboxSequence = null,
 243        string? gatewayExecutionId = null,
 244        string? decisionStage = null,
 245        GovernanceEmissionPayload? payload = null,
 246        IReadOnlyDictionary<string, string>? metadata = null)
 247    {
 1427248        return new GovernanceEmissionEnvelope(
 1427249            NormalizeIdentifier(envelopeId),
 1427250            schemaVersion ?? AsiBackboneSchemaVersions.StableArtifactsV1,
 1427251            eventType,
 1427252            eventId,
 1427253            occurredUtc ?? DateTimeOffset.UtcNow,
 1427254            createdUtc ?? DateTimeOffset.UtcNow,
 1427255            correlationId,
 1427256            auditResidueId,
 1427257            lifecycleStage,
 1427258            policyVersion,
 1427259            policyHash,
 1427260            traceId,
 1427261            spanId,
 1427262            parentSpanId,
 1427263            operationName,
 1427264            outcome,
 1427265            actorId,
 1427266            emitterStatus,
 1427267            emitterProvider,
 1427268            outboxSequence,
 1427269            gatewayExecutionId,
 1427270            decisionStage,
 1427271            payload,
 1427272            NormalizeMetadata(metadata));
 273    }
 274
 275    /// <summary>
 276    /// Creates a provider-neutral governance emission envelope from audit residue.
 277    /// </summary>
 278    public static GovernanceEmissionEnvelope FromResidue(
 279        IAsiBackboneAuditResidue residue,
 280        GovernanceEmissionEventType eventType = GovernanceEmissionEventType.AuditResidue,
 281        string? envelopeId = null,
 282        DateTimeOffset? createdUtc = null,
 283        GovernanceEmissionPayload? payload = null,
 284        IReadOnlyDictionary<string, string>? metadata = null)
 285    {
 4286        ArgumentNullException.ThrowIfNull(residue);
 287
 4288        return new GovernanceEmissionEnvelope(
 4289            NormalizeIdentifier(envelopeId),
 4290            residue.SchemaVersion,
 4291            eventType,
 4292            residue.EventId,
 4293            residue.OccurredUtc,
 4294            createdUtc ?? DateTimeOffset.UtcNow,
 4295            residue.CorrelationId,
 4296            residue.AuditResidueId,
 4297            null,
 4298            residue.PolicyVersion,
 4299            residue.PolicyHash,
 4300            residue.TraceId,
 4301            residue.SpanId,
 4302            residue.ParentSpanId,
 4303            residue.OperationName,
 4304            residue.Outcome,
 4305            residue.ActorId,
 4306            residue.EmitterStatus,
 4307            residue.EmitterProvider,
 4308            residue.OutboxSequence,
 4309            residue.GatewayExecutionId,
 4310            residue.DecisionStage,
 4311            payload,
 4312            NormalizeMetadata(residue.Metadata, metadata));
 313    }
 314
 315    /// <summary>
 316    /// Creates a provider-neutral governance emission envelope from an audit residue lifecycle event.
 317    /// </summary>
 318    public static GovernanceEmissionEnvelope FromLifecycleEvent(
 319        AuditResidueLifecycleEvent lifecycleEvent,
 320        string? envelopeId = null,
 321        DateTimeOffset? createdUtc = null,
 322        GovernanceEmissionPayload? payload = null,
 323        IReadOnlyDictionary<string, string>? metadata = null)
 324    {
 6325        ArgumentNullException.ThrowIfNull(lifecycleEvent);
 326
 6327        return new GovernanceEmissionEnvelope(
 6328            NormalizeIdentifier(envelopeId),
 6329            AsiBackboneSchemaVersions.StableArtifactsV1,
 6330            GovernanceEmissionEventType.AuditLifecycle,
 6331            lifecycleEvent.EventId,
 6332            lifecycleEvent.OccurredUtc,
 6333            createdUtc ?? DateTimeOffset.UtcNow,
 6334            lifecycleEvent.CorrelationId,
 6335            lifecycleEvent.AuditResidueId,
 6336            lifecycleEvent.Stage,
 6337            null,
 6338            null,
 6339            lifecycleEvent.TraceId,
 6340            null,
 6341            null,
 6342            lifecycleEvent.OperationName,
 6343            lifecycleEvent.Outcome,
 6344            null,
 6345            null,
 6346            null,
 6347            null,
 6348            null,
 6349            lifecycleEvent.Stage.ToString(),
 6350            payload,
 6351            NormalizeMetadata(lifecycleEvent.Metadata, metadata));
 352    }
 353
 354    private static string NormalizeIdentifier(string? identifier)
 355    {
 1437356        return string.IsNullOrWhiteSpace(identifier)
 1437357            ? Guid.NewGuid().ToString("N")
 1437358            : identifier.Trim();
 359    }
 360
 361    private static string? NormalizeOptional(string? value)
 362    {
 21491363        return string.IsNullOrWhiteSpace(value)
 21491364            ? null
 21491365            : value.Trim();
 366    }
 367
 368    private static long? NormalizeNonNegative(long? value, string parameterName)
 369    {
 1433370        return value < 0
 1433371            ? throw new ArgumentOutOfRangeException(parameterName, value, "Value must be greater than or equal to zero."
 1433372            : value;
 373    }
 374
 375    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 376        params IReadOnlyDictionary<string, string>?[] metadataSets)
 377    {
 1437378        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 379
 5768380        foreach (IReadOnlyDictionary<string, string>? metadata in metadataSets)
 381        {
 1447382            if (metadata is null || metadata.Count == 0)
 383            {
 384                continue;
 385            }
 386
 1536387            foreach (KeyValuePair<string, string> item in metadata)
 388            {
 450389                if (string.IsNullOrWhiteSpace(item.Key))
 390                {
 391                    continue;
 392                }
 393
 446394                normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 395            }
 396        }
 397
 1437398        return normalizedMetadata.Count == 0
 1437399            ? EmptyMetadata
 1437400            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 401    }
 402}

Methods/Properties

.cctor()
.ctor(System.String,System.String,AsiBackbone.Core.Emissions.GovernanceEmissionEventType,System.String,System.DateTimeOffset,System.DateTimeOffset,System.String,System.String,System.Nullable`1<AsiBackbone.Core.Audit.AuditResidueLifecycleStage>,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.Nullable`1<System.Int64>,System.String,System.String,AsiBackbone.Core.Emissions.GovernanceEmissionPayload,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
get_EnvelopeId()
get_SchemaVersion()
get_EventType()
get_EventId()
get_OccurredUtc()
get_CreatedUtc()
get_CorrelationId()
get_AuditResidueId()
get_LifecycleStage()
get_LifecycleStageSequence()
get_PolicyVersion()
get_PolicyHash()
get_TraceId()
get_SpanId()
get_ParentSpanId()
get_OperationName()
get_Outcome()
get_ActorId()
get_EmitterStatus()
get_EmitterProvider()
get_OutboxSequence()
get_GatewayExecutionId()
get_DecisionStage()
get_Payload()
get_Metadata()
get_HasCorrelation()
get_HasMetadata()
Create(AsiBackbone.Core.Emissions.GovernanceEmissionEventType,System.String,System.Nullable`1<System.DateTimeOffset>,System.String,System.Nullable`1<System.DateTimeOffset>,System.String,System.String,System.String,System.Nullable`1<AsiBackbone.Core.Audit.AuditResidueLifecycleStage>,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.String,System.Nullable`1<System.Int64>,System.String,System.String,AsiBackbone.Core.Emissions.GovernanceEmissionPayload,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
FromResidue(AsiBackbone.Core.Audit.IAsiBackboneAuditResidue,AsiBackbone.Core.Emissions.GovernanceEmissionEventType,System.String,System.Nullable`1<System.DateTimeOffset>,AsiBackbone.Core.Emissions.GovernanceEmissionPayload,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
FromLifecycleEvent(AsiBackbone.Core.Audit.AuditResidueLifecycleEvent,System.String,System.Nullable`1<System.DateTimeOffset>,AsiBackbone.Core.Emissions.GovernanceEmissionPayload,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
NormalizeIdentifier(System.String)
NormalizeOptional(System.String)
NormalizeNonNegative(System.Nullable`1<System.Int64>,System.String)
NormalizeMetadata(System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>[])