< 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{
 515    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 516        new ReadOnlyDictionary<string, string>(
 517            new Dictionary<string, string>(StringComparer.Ordinal));
 18
 24119    private GovernanceEmissionEnvelope(
 24120        string envelopeId,
 24121        string schemaVersion,
 24122        GovernanceEmissionEventType eventType,
 24123        string? eventId,
 24124        DateTimeOffset occurredUtc,
 24125        DateTimeOffset createdUtc,
 24126        string? correlationId,
 24127        string? auditResidueId,
 24128        AuditResidueLifecycleStage? lifecycleStage,
 24129        string? policyVersion,
 24130        string? policyHash,
 24131        string? traceId,
 24132        string? spanId,
 24133        string? parentSpanId,
 24134        string? operationName,
 24135        string? outcome,
 24136        string? actorId,
 24137        string? emitterStatus,
 24138        string? emitterProvider,
 24139        long? outboxSequence,
 24140        string? gatewayExecutionId,
 24141        string? decisionStage,
 24142        GovernanceEmissionPayload? payload,
 24143        IReadOnlyDictionary<string, string> metadata)
 44    {
 24145        ArgumentException.ThrowIfNullOrWhiteSpace(envelopeId);
 46
 24147        if (!Enum.IsDefined(eventType))
 48        {
 149            throw new ArgumentOutOfRangeException(nameof(eventType), eventType, "Governance emission event type must be 
 50        }
 51
 24052        if (lifecycleStage.HasValue && !Enum.IsDefined(lifecycleStage.Value))
 53        {
 154            throw new ArgumentOutOfRangeException(nameof(lifecycleStage), lifecycleStage, "Lifecycle stage must be defin
 55        }
 56
 23957        EnvelopeId = envelopeId.Trim();
 23958        SchemaVersion = AsiBackboneSchemaVersions.Normalize(schemaVersion);
 23959        EventType = eventType;
 23960        EventId = NormalizeOptional(eventId);
 23961        OccurredUtc = occurredUtc.ToUniversalTime();
 23962        CreatedUtc = createdUtc.ToUniversalTime();
 23963        CorrelationId = NormalizeOptional(correlationId);
 23964        AuditResidueId = NormalizeOptional(auditResidueId);
 23965        LifecycleStage = lifecycleStage;
 23966        LifecycleStageSequence = lifecycleStage.HasValue ? (int)lifecycleStage.Value : null;
 23967        PolicyVersion = NormalizeOptional(policyVersion);
 23968        PolicyHash = NormalizeOptional(policyHash);
 23969        TraceId = NormalizeOptional(traceId);
 23970        SpanId = NormalizeOptional(spanId);
 23971        ParentSpanId = NormalizeOptional(parentSpanId);
 23972        OperationName = NormalizeOptional(operationName);
 23973        Outcome = NormalizeOptional(outcome);
 23974        ActorId = NormalizeOptional(actorId);
 23975        EmitterStatus = NormalizeOptional(emitterStatus);
 23976        EmitterProvider = NormalizeOptional(emitterProvider);
 23977        OutboxSequence = NormalizeNonNegative(outboxSequence, nameof(outboxSequence));
 23878        GatewayExecutionId = NormalizeOptional(gatewayExecutionId);
 23879        DecisionStage = NormalizeOptional(decisionStage);
 23880        Payload = payload;
 23881        Metadata = metadata;
 23882    }
 83
 84    /// <summary>
 85    /// Gets the stable envelope identifier.
 86    /// </summary>
 12687    public string EnvelopeId { get; }
 88
 89    /// <summary>
 90    /// Gets the schema version for this provider-neutral envelope shape.
 91    /// </summary>
 11492    public string SchemaVersion { get; }
 93
 94    /// <summary>
 95    /// Gets the provider-neutral event category.
 96    /// </summary>
 10897    public GovernanceEmissionEventType EventType { get; }
 98
 99    /// <summary>
 100    /// Gets the source governance event identifier, when available.
 101    /// </summary>
 101102    public string? EventId { get; }
 103
 104    /// <summary>
 105    /// Gets the UTC timestamp when the source governance event occurred.
 106    /// </summary>
 94107    public DateTimeOffset OccurredUtc { get; }
 108
 109    /// <summary>
 110    /// Gets the UTC timestamp when this emission envelope was created.
 111    /// </summary>
 92112    public DateTimeOffset CreatedUtc { get; }
 113
 114    /// <summary>
 115    /// Gets the correlation identifier that links the emission to the host workflow, when available.
 116    /// </summary>
 144117    public string? CorrelationId { get; }
 118
 119    /// <summary>
 120    /// Gets the audit residue identifier linked to this emission, when available.
 121    /// </summary>
 108122    public string? AuditResidueId { get; }
 123
 124    /// <summary>
 125    /// Gets the audit residue lifecycle stage linked to this emission, when available.
 126    /// </summary>
 133127    public AuditResidueLifecycleStage? LifecycleStage { get; }
 128
 129    /// <summary>
 130    /// Gets the stable lifecycle stage sequence value, when a lifecycle stage is supplied.
 131    /// </summary>
 98132    public int? LifecycleStageSequence { get; }
 133
 134    /// <summary>
 135    /// Gets the policy version associated with the source governance event, when available.
 136    /// </summary>
 101137    public string? PolicyVersion { get; }
 138
 139    /// <summary>
 140    /// Gets the policy hash associated with the source governance event, when available.
 141    /// </summary>
 101142    public string? PolicyHash { get; }
 143
 144    /// <summary>
 145    /// Gets the trace identifier associated with the source governance event, when available.
 146    /// </summary>
 108147    public string? TraceId { get; }
 148
 149    /// <summary>
 150    /// Gets the span identifier associated with the source governance event, when available.
 151    /// </summary>
 99152    public string? SpanId { get; }
 153
 154    /// <summary>
 155    /// Gets the parent span identifier associated with the source governance event, when available.
 156    /// </summary>
 99157    public string? ParentSpanId { get; }
 158
 159    /// <summary>
 160    /// Gets the operation name associated with the source governance event, when available.
 161    /// </summary>
 102162    public string? OperationName { get; }
 163
 164    /// <summary>
 165    /// Gets the outcome associated with the source governance event, when available.
 166    /// </summary>
 98167    public string? Outcome { get; }
 168
 169    /// <summary>
 170    /// Gets the actor identifier associated with the source governance event, when available.
 171    /// </summary>
 93172    public string? ActorId { get; }
 173
 174    /// <summary>
 175    /// Gets the provider-neutral emitter status, when available.
 176    /// </summary>
 99177    public string? EmitterStatus { get; }
 178
 179    /// <summary>
 180    /// Gets the provider-neutral emitter provider name, when available.
 181    /// </summary>
 93182    public string? EmitterProvider { get; }
 183
 184    /// <summary>
 185    /// Gets the outbox sequence associated with the emission, when available.
 186    /// </summary>
 96187    public long? OutboxSequence { get; }
 188
 189    /// <summary>
 190    /// Gets the gateway execution identifier associated with the emission, when available.
 191    /// </summary>
 99192    public string? GatewayExecutionId { get; }
 193
 194    /// <summary>
 195    /// Gets the provider-neutral decision stage associated with the emission, when available.
 196    /// </summary>
 98197    public string? DecisionStage { get; }
 198
 199    /// <summary>
 200    /// Gets the minimized provider-neutral payload descriptor, when available.
 201    /// </summary>
 122202    public GovernanceEmissionPayload? Payload { get; }
 203
 204    /// <summary>
 205    /// Gets minimized provider-neutral metadata.
 206    /// </summary>
 113207    public IReadOnlyDictionary<string, string> Metadata { get; }
 208
 209    /// <summary>
 210    /// Gets a value indicating whether correlation metadata is available.
 211    /// </summary>
 8212    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>
 5217    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    {
 236248        return new GovernanceEmissionEnvelope(
 236249            NormalizeIdentifier(envelopeId),
 236250            schemaVersion ?? AsiBackboneSchemaVersions.StableArtifactsV1,
 236251            eventType,
 236252            eventId,
 236253            occurredUtc ?? DateTimeOffset.UtcNow,
 236254            createdUtc ?? DateTimeOffset.UtcNow,
 236255            correlationId,
 236256            auditResidueId,
 236257            lifecycleStage,
 236258            policyVersion,
 236259            policyHash,
 236260            traceId,
 236261            spanId,
 236262            parentSpanId,
 236263            operationName,
 236264            outcome,
 236265            actorId,
 236266            emitterStatus,
 236267            emitterProvider,
 236268            outboxSequence,
 236269            gatewayExecutionId,
 236270            decisionStage,
 236271            payload,
 236272            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    {
 2286        ArgumentNullException.ThrowIfNull(residue);
 287
 2288        return new GovernanceEmissionEnvelope(
 2289            NormalizeIdentifier(envelopeId),
 2290            residue.SchemaVersion,
 2291            eventType,
 2292            residue.EventId,
 2293            residue.OccurredUtc,
 2294            createdUtc ?? DateTimeOffset.UtcNow,
 2295            residue.CorrelationId,
 2296            residue.AuditResidueId,
 2297            null,
 2298            residue.PolicyVersion,
 2299            residue.PolicyHash,
 2300            residue.TraceId,
 2301            residue.SpanId,
 2302            residue.ParentSpanId,
 2303            residue.OperationName,
 2304            residue.Outcome,
 2305            residue.ActorId,
 2306            residue.EmitterStatus,
 2307            residue.EmitterProvider,
 2308            residue.OutboxSequence,
 2309            residue.GatewayExecutionId,
 2310            residue.DecisionStage,
 2311            payload,
 2312            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    {
 3325        ArgumentNullException.ThrowIfNull(lifecycleEvent);
 326
 3327        return new GovernanceEmissionEnvelope(
 3328            NormalizeIdentifier(envelopeId),
 3329            AsiBackboneSchemaVersions.StableArtifactsV1,
 3330            GovernanceEmissionEventType.AuditLifecycle,
 3331            lifecycleEvent.EventId,
 3332            lifecycleEvent.OccurredUtc,
 3333            createdUtc ?? DateTimeOffset.UtcNow,
 3334            lifecycleEvent.CorrelationId,
 3335            lifecycleEvent.AuditResidueId,
 3336            lifecycleEvent.Stage,
 3337            null,
 3338            null,
 3339            lifecycleEvent.TraceId,
 3340            null,
 3341            null,
 3342            lifecycleEvent.OperationName,
 3343            lifecycleEvent.Outcome,
 3344            null,
 3345            null,
 3346            null,
 3347            null,
 3348            null,
 3349            lifecycleEvent.Stage.ToString(),
 3350            payload,
 3351            NormalizeMetadata(lifecycleEvent.Metadata, metadata));
 352    }
 353
 354    private static string NormalizeIdentifier(string? identifier)
 355    {
 241356        return string.IsNullOrWhiteSpace(identifier)
 241357            ? Guid.NewGuid().ToString("N")
 241358            : identifier.Trim();
 359    }
 360
 361    private static string? NormalizeOptional(string? value)
 362    {
 3583363        return string.IsNullOrWhiteSpace(value)
 3583364            ? null
 3583365            : value.Trim();
 366    }
 367
 368    private static long? NormalizeNonNegative(long? value, string parameterName)
 369    {
 239370        return value < 0
 239371            ? throw new ArgumentOutOfRangeException(parameterName, value, "Value must be greater than or equal to zero."
 239372            : value;
 373    }
 374
 375    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 376        params IReadOnlyDictionary<string, string>?[] metadataSets)
 377    {
 241378        Dictionary<string, string> normalizedMetadata = new(StringComparer.Ordinal);
 379
 974380        foreach (IReadOnlyDictionary<string, string>? metadata in metadataSets)
 381        {
 246382            if (metadata is null || metadata.Count == 0)
 383            {
 384                continue;
 385            }
 386
 910387            foreach (KeyValuePair<string, string> item in metadata)
 388            {
 289389                if (string.IsNullOrWhiteSpace(item.Key))
 390                {
 391                    continue;
 392                }
 393
 287394                normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 395            }
 396        }
 397
 241398        return normalizedMetadata.Count == 0
 241399            ? EmptyMetadata
 241400            : 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>[])