22using ModularityKit . Mutator . Abstractions . Engine ;
33using ModularityKit . Mutator . Abstractions . Intent ;
44using ModularityKit . Mutator . Abstractions . Results ;
5+ using ModularityKit . Mutator . Governance . Abstractions . Requests . Model ;
56
67namespace ModularityKit . Mutator . Governance . Runtime . Execution . Mutation ;
78
89/// <summary>
9- /// Wraps a mutation so governance request identifiers flow into core execution audit and history metadata.
10+ /// Wraps mutation so governance request identifiers flow into core execution audit and history metadata.
1011/// </summary>
1112internal sealed class GovernedMutation < TState > : IMutation < TState >
1213{
14+ private const string GovernanceRequestIdMetadataKey = "GovernanceRequestId" ;
15+ private const string GovernanceRequestMetadataKey = "GovernanceRequestMetadata" ;
16+ private const string GovernanceIntentMetadataKey = "GovernanceIntentMetadata" ;
17+ private const string GovernanceEstimatedBlastRadiusMetadataKey = "GovernanceEstimatedBlastRadius" ;
18+
1319 private readonly IMutation < TState > _inner ;
1420
15- public GovernedMutation ( IMutation < TState > inner , string requestId , string stateId )
21+ public GovernedMutation ( IMutation < TState > inner , MutationRequest request )
1622 {
1723 _inner = inner ?? throw new ArgumentNullException ( nameof ( inner ) ) ;
24+ ArgumentNullException . ThrowIfNull ( request ) ;
1825
1926 Intent = new MutationIntent
2027 {
@@ -23,17 +30,17 @@ public GovernedMutation(IMutation<TState> inner, string requestId, string stateI
2330 Description = _inner . Intent . Description ,
2431 RiskLevel = _inner . Intent . RiskLevel ,
2532 IsReversible = _inner . Intent . IsReversible ,
26- EstimatedBlastRadius = _inner . Intent . EstimatedBlastRadius ,
27- Tags = _inner . Intent . Tags ,
33+ EstimatedBlastRadius = request . Intent . EstimatedBlastRadius ?? _inner . Intent . EstimatedBlastRadius ,
34+ Tags = MergeTags ( request . Intent . Tags , _inner . Intent . Tags ) ,
2835 CreatedAt = _inner . Intent . CreatedAt ,
29- Metadata = MergeMetadata ( _inner . Intent . Metadata , requestId )
36+ Metadata = MergeIntentMetadata ( request )
3037 } ;
3138
3239 Context = _inner . Context with
3340 {
34- StateId = string . IsNullOrWhiteSpace ( _inner . Context . StateId ) ? stateId : _inner . Context . StateId ,
35- CorrelationId = string . IsNullOrWhiteSpace ( _inner . Context . CorrelationId ) ? requestId : _inner . Context . CorrelationId ,
36- Metadata = MergeMetadata ( _inner . Context . Metadata , requestId )
41+ StateId = string . IsNullOrWhiteSpace ( _inner . Context . StateId ) ? request . StateId : _inner . Context . StateId ,
42+ CorrelationId = string . IsNullOrWhiteSpace ( _inner . Context . CorrelationId ) ? request . RequestId : _inner . Context . CorrelationId ,
43+ Metadata = MergeContextMetadata ( request )
3744 } ;
3845 }
3946
@@ -47,15 +54,40 @@ public GovernedMutation(IMutation<TState> inner, string requestId, string stateI
4754
4855 public MutationResult < TState > Simulate ( TState state ) => _inner . Simulate ( state ) ;
4956
50- private static IReadOnlyDictionary < string , object > MergeMetadata (
51- IReadOnlyDictionary < string , object > source ,
52- string requestId )
57+ private IReadOnlyDictionary < string , object > MergeContextMetadata ( MutationRequest request )
5358 {
54- var metadata = new Dictionary < string , object > ( source )
59+ var metadata = new Dictionary < string , object > ( _inner . Context . Metadata )
5560 {
56- [ "GovernanceRequestId" ] = requestId
61+ [ GovernanceRequestIdMetadataKey ] = request . RequestId
5762 } ;
5863
64+ if ( request . Metadata . Count > 0 )
65+ metadata [ GovernanceRequestMetadataKey ] = request . Metadata ;
66+
67+ if ( request . Intent . Metadata . Count > 0 )
68+ metadata [ GovernanceIntentMetadataKey ] = request . Intent . Metadata ;
69+
70+ if ( request . Intent . EstimatedBlastRadius is not null )
71+ metadata [ GovernanceEstimatedBlastRadiusMetadataKey ] = request . Intent . EstimatedBlastRadius ;
72+
5973 return metadata ;
6074 }
75+
76+ private IReadOnlyDictionary < string , object > MergeIntentMetadata ( MutationRequest request )
77+ {
78+ var metadata = new Dictionary < string , object > ( request . Intent . Metadata )
79+ {
80+ [ GovernanceRequestIdMetadataKey ] = request . RequestId
81+ } ;
82+
83+ if ( _inner . Intent . Metadata . Count > 0 )
84+ metadata [ "ExecutionIntentMetadata" ] = _inner . Intent . Metadata ;
85+
86+ return metadata ;
87+ }
88+
89+ private static IReadOnlySet < string > MergeTags (
90+ IReadOnlySet < string > requestTags ,
91+ IReadOnlySet < string > executionTags )
92+ => new HashSet < string > ( requestTags . Concat ( executionTags ) , StringComparer . Ordinal ) ;
6193}
0 commit comments