Skip to content

Commit ae696de

Browse files
committed
Docs: Organize governance examples and references
1 parent c76c330 commit ae696de

9 files changed

Lines changed: 191 additions & 5 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\..\..\src\ModularityKit.Mutator.Governance.csproj" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using DecisionTaxonomy.Scenarios;
2+
3+
GovernanceDecisionTaxonomyScenario.Run();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Governance DecisionTaxonomy
2+
3+
This example shows why governance request decisions are split into separate categories instead of being kept in one flat enum.
4+
5+
It demonstrates:
6+
7+
- lifecycle decisions such as `Submitted` and `Approved`
8+
- approval decisions such as `Requested`, `Granted`, and `Rejected`
9+
- version-resolution decisions such as `Validated` and `RejectedAsStale`
10+
- the shared `MutationRequestDecisionType` wrapper with:
11+
- `Category`
12+
- `Code`
13+
- `ToString()`
14+
15+
## Key files
16+
17+
- [`Program.cs`](Program.cs)
18+
- [`Scenarios/GovernanceDecisionTaxonomyScenario.cs`](Scenarios/GovernanceDecisionTaxonomyScenario.cs)
19+
- [`src/Governance/Abstractions/Requests/Decisions/MutationRequestDecisionType.cs`](../../../src/Governance/Abstractions/Requests/Decisions/MutationRequestDecisionType.cs)
20+
- [`src/Governance/Abstractions/Requests/Decisions/MutationRequestDecisionCategory.cs`](../../../src/Governance/Abstractions/Requests/Decisions/MutationRequestDecisionCategory.cs)
21+
- [`src/Governance/Abstractions/Requests/Decisions/MutationRequestLifecycleDecisionType.cs`](../../../src/Governance/Abstractions/Requests/Decisions/MutationRequestLifecycleDecisionType.cs)
22+
- [`src/Governance/Abstractions/Requests/Decisions/MutationRequestApprovalDecisionType.cs`](../../../src/Governance/Abstractions/Requests/Decisions/MutationRequestApprovalDecisionType.cs)
23+
- [`src/Governance/Abstractions/Requests/Decisions/MutationRequestVersionResolutionDecisionType.cs`](../../../src/Governance/Abstractions/Requests/Decisions/MutationRequestVersionResolutionDecisionType.cs)
24+
25+
## Run
26+
27+
```bash
28+
dotnet run --project Examples/Governance/DecisionTaxonomy/DecisionTaxonomy.csproj
29+
```
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using ModularityKit.Mutator.Abstractions.Context;
2+
using ModularityKit.Mutator.Governance.Abstractions.Requests.Decisions;
3+
4+
namespace DecisionTaxonomy.Scenarios;
5+
6+
internal static class GovernanceDecisionTaxonomyScenario
7+
{
8+
public static void Run()
9+
{
10+
PrintSection("Lifecycle Decisions");
11+
PrintDecision(MutationRequestDecision.Create(
12+
MutationRequestDecisionType.Lifecycle(MutationRequestLifecycleDecisionType.Submitted),
13+
MutationContext.User("requester", "Requester", "Submit request"),
14+
reason: "Request was submitted into governance."));
15+
PrintDecision(MutationRequestDecision.Create(
16+
MutationRequestDecisionType.Lifecycle(MutationRequestLifecycleDecisionType.Approved),
17+
MutationContext.User("system", "System", "Request reached executable state"),
18+
reason: "Request is now approved for execution."));
19+
20+
PrintSection("Approval Decisions");
21+
PrintDecision(MutationRequestDecision.Create(
22+
MutationRequestDecisionType.Approval(MutationRequestApprovalDecisionType.Requested),
23+
MutationContext.User("requester", "Requester", "Approval needed for sensitive change"),
24+
reason: "Sensitive change requires explicit sign-off."));
25+
PrintDecision(MutationRequestDecision.Create(
26+
MutationRequestDecisionType.Approval(MutationRequestApprovalDecisionType.Granted),
27+
MutationContext.User("alice", "Alice", "Manager approved"),
28+
reason: "Manager granted the required approval."));
29+
PrintDecision(MutationRequestDecision.Create(
30+
MutationRequestDecisionType.Approval(MutationRequestApprovalDecisionType.Rejected),
31+
MutationContext.User("bob", "Bob", "Security rejected"),
32+
reason: "Security review rejected the request."));
33+
34+
PrintSection("Version Resolution Decisions");
35+
PrintDecision(MutationRequestDecision.Create(
36+
MutationRequestDecisionType.VersionResolution(MutationRequestVersionResolutionDecisionType.Validated),
37+
MutationContext.User("approver", "Approver", "Version still matches"),
38+
reason: "Current state version still matches the approved request."));
39+
PrintDecision(MutationRequestDecision.Create(
40+
MutationRequestDecisionType.VersionResolution(MutationRequestVersionResolutionDecisionType.RejectedAsStale),
41+
MutationContext.User("approver", "Approver", "State drift invalidated the request"),
42+
reason: "Request was rejected because the approved version is stale."));
43+
PrintDecision(MutationRequestDecision.Create(
44+
MutationRequestDecisionType.VersionResolution(MutationRequestVersionResolutionDecisionType.RenewedApprovalRequired),
45+
MutationContext.User("approver", "Approver", "Re-approval required on latest state"),
46+
reason: "Request must be approved again on the latest state version."));
47+
}
48+
49+
private static void PrintSection(string title)
50+
{
51+
Console.WriteLine();
52+
Console.WriteLine($"=== {title} ===");
53+
}
54+
55+
private static void PrintDecision(MutationRequestDecision decision)
56+
{
57+
Console.WriteLine($"Category: {decision.Type.Category}");
58+
Console.WriteLine($"Code: {decision.Type.Code}");
59+
Console.WriteLine($"Display: {decision.Type}");
60+
Console.WriteLine($"Actor: {decision.Context.ActorId ?? "system"}");
61+
Console.WriteLine($"Reason: {decision.Reason ?? "-"}");
62+
Console.WriteLine();
63+
}
64+
}

Examples/Governance/RequestLifecycle/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ It focuses on `MutationRequest`, `IMutationRequestStore`, and `MutationRequestLi
2121

2222
- [`Program.cs`](Program.cs)
2323
- [`Scenarios/GovernanceRequestLifecycleScenario.cs`](Scenarios/GovernanceRequestLifecycleScenario.cs)
24-
- [`src/Governance/Abstractions/Requests/MutationRequest.cs`](../../../src/Governance/Abstractions/Requests/MutationRequest.cs)
24+
- [`src/Governance/Abstractions/Requests/Model/MutationRequest.cs`](../../../src/Governance/Abstractions/Requests/Model/MutationRequest.cs)
2525
- [`src/Governance/Abstractions/Lifecycle/IMutationRequestLifecycleManager.cs`](../../../src/Governance/Abstractions/Lifecycle/IMutationRequestLifecycleManager.cs)
2626
- [`src/Governance/Runtime/MutationRequestLifecycleManager.cs`](../../../src/Governance/Runtime/MutationRequestLifecycleManager.cs)
2727
- [`src/Governance/Runtime/InMemoryMutationRequestStore.cs`](../../../src/Governance/Runtime/InMemoryMutationRequestStore.cs)

Examples/Governance/VersionedResolution/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ It is the direct runnable example for the semantics introduced around `ExpectedS
1717

1818
- [`Program.cs`](Program.cs)
1919
- [`Scenarios/GovernanceVersionedResolutionScenario.cs`](Scenarios/GovernanceVersionedResolutionScenario.cs)
20-
- [`src/Governance/Runtime/Resolution/MutationRequestVersionResolver.cs`](../../../src/Governance/Runtime/Resolution/MutationRequestVersionResolver.cs)
21-
- [`src/Governance/Runtime/Resolution/MutationRequestVersionResolutionManager.cs`](../../../src/Governance/Runtime/Resolution/MutationRequestVersionResolutionManager.cs)
22-
- [`src/Governance/Abstractions/Resolution/VersionedRequestResolutionStrategy.cs`](../../../src/Governance/Abstractions/Resolution/VersionedRequestResolutionStrategy.cs)
23-
- [`src/Governance/Abstractions/Resolution/MutationRequestVersionResolution.cs`](../../../src/Governance/Abstractions/Resolution/MutationRequestVersionResolution.cs)
20+
- [`src/Governance/Runtime/Resolution/Execution/MutationRequestVersionResolver.cs`](../../../src/Governance/Runtime/Resolution/Execution/MutationRequestVersionResolver.cs)
21+
- [`src/Governance/Runtime/Resolution/Execution/MutationRequestVersionResolutionManager.cs`](../../../src/Governance/Runtime/Resolution/Execution/MutationRequestVersionResolutionManager.cs)
22+
- [`src/Governance/Abstractions/Resolution/Strategies/VersionedRequestResolutionStrategy.cs`](../../../src/Governance/Abstractions/Resolution/Strategies/VersionedRequestResolutionStrategy.cs)
23+
- [`src/Governance/Abstractions/Resolution/Model/MutationRequestVersionResolution.cs`](../../../src/Governance/Abstractions/Resolution/Model/MutationRequestVersionResolution.cs)
2424

2525
## Run
2626

Examples/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ The projects are intentionally small and focused. Each one demonstrates a differ
2323
| Example | Focus | Readme |
2424
| --- | --- | --- |
2525
| `RequestLifecycle` | pending requests, lifecycle transitions, expiration, and cancellation | [`Examples/Governance/RequestLifecycle/README.md`](Governance/RequestLifecycle/README.md) |
26+
| `DecisionTaxonomy` | lifecycle, approval, and version-resolution decision categories | [`Examples/Governance/DecisionTaxonomy/README.md`](Governance/DecisionTaxonomy/README.md) |
27+
| `ApprovalWorkflow` | request-level approvals, multi-step sign-off, and governed approval actions | [`Examples/Governance/ApprovalWorkflow/README.md`](Governance/ApprovalWorkflow/README.md) |
2628
| `VersionedResolution` | stale request handling and expected state version semantics | [`Examples/Governance/VersionedResolution/README.md`](Governance/VersionedResolution/README.md) |
2729

2830
## How to use these examples
@@ -52,6 +54,8 @@ dotnet build Examples/Core/FeatureFlags/FeatureFlags.csproj -c Release
5254
dotnet build Examples/Core/IamRoles/IamRoles.csproj -c Release
5355
dotnet build Examples/Core/WorkflowApprovals/WorkflowApprovals.csproj -c Release
5456
dotnet build Examples/Governance/RequestLifecycle/RequestLifecycle.csproj -c Release
57+
dotnet build Examples/Governance/DecisionTaxonomy/DecisionTaxonomy.csproj -c Release
58+
dotnet build Examples/Governance/ApprovalWorkflow/ApprovalWorkflow.csproj -c Release
5559
dotnet build Examples/Governance/VersionedResolution/VersionedResolution.csproj -c Release
5660
```
5761

@@ -67,6 +71,8 @@ dotnet run --project Examples/Core/FeatureFlags/FeatureFlags.csproj
6771
dotnet run --project Examples/Core/IamRoles/IamRoles.csproj
6872
dotnet run --project Examples/Core/WorkflowApprovals/WorkflowApprovals.csproj
6973
dotnet run --project Examples/Governance/RequestLifecycle/RequestLifecycle.csproj
74+
dotnet run --project Examples/Governance/DecisionTaxonomy/DecisionTaxonomy.csproj
75+
dotnet run --project Examples/Governance/ApprovalWorkflow/ApprovalWorkflow.csproj
7076
dotnet run --project Examples/Governance/VersionedResolution/VersionedResolution.csproj
7177
```
7278

@@ -131,6 +137,18 @@ Shows the governance runtime as a request lifecycle system instead of an immedia
131137

132138
See [`Governance/RequestLifecycle/README.md`](Governance/RequestLifecycle/README.md).
133139

140+
### ApprovalWorkflow
141+
142+
Shows how governance turns approval requirements into explicit request-level approval actions with ordered steps and terminal approval or rejection behavior.
143+
144+
See [`Governance/ApprovalWorkflow/README.md`](Governance/ApprovalWorkflow/README.md).
145+
146+
### DecisionTaxonomy
147+
148+
Shows why governance request decisions are split into lifecycle, approval, and version-resolution categories instead of being kept in one flat enum.
149+
150+
See [`Governance/DecisionTaxonomy/README.md`](Governance/DecisionTaxonomy/README.md).
151+
134152
### VersionedResolution
135153

136154
Shows how governance resolves approved requests once the underlying state version has moved. This is the example to read if you want concrete stale request semantics.

ModularityKit.Mutator.slnx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<Project Path="Examples/Core/FeatureFlags/FeatureFlags.csproj" />
99
<Project Path="Examples/Core/IamRoles/IamRoles.csproj" />
1010
<Project Path="Examples/Core/WorkflowApprovals/WorkflowApprovals.csproj" />
11+
<Project Path="Examples/Governance/ApprovalWorkflow/ApprovalWorkflow.csproj" />
12+
<Project Path="Examples/Governance/DecisionTaxonomy/DecisionTaxonomy.csproj" />
1113
<Project Path="Examples/Governance/RequestLifecycle/RequestLifecycle.csproj" />
1214
<Project Path="Examples/Governance/VersionedResolution/VersionedResolution.csproj" />
1315
</Folder>

src/Governance/README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The core package stays responsible for direct mutation execution. Governance bui
99
- **Mutation Requests** - model governed mutation submission as a durable request
1010
- **Pending Lifecycle** - represent requests that cannot execute immediately
1111
- **Decision History** - record approvals, rejections, cancellations, and other lifecycle transitions
12+
- **Approval Workflow** - model request-level approval requirements and explicit approver actions
1213
- **Request Storage Contracts** - define a persistence seam for governance-oriented stores
1314
- **Runtime Lifecycle Management** - move requests through pending, approval, expiration, and execution transitions
1415
- **In-Memory Runtime Support** - provide lightweight request runtime services for development and tests
@@ -20,6 +21,7 @@ The core package stays responsible for direct mutation execution. Governance bui
2021
The package defines governance-first abstractions under:
2122

2223
- `Abstractions/Requests`
24+
- `Abstractions/Approval`
2325
- `Abstractions/Lifecycle`
2426
- `Abstractions/Storage`
2527
- `Abstractions/Resolution`
@@ -28,31 +30,85 @@ The package defines governance-first abstractions under:
2830
Key types:
2931

3032
- `MutationRequest`
33+
- `MutationApprovalRequirement`
34+
- `MutationApprovalRequirementStatus`
3135
- `MutationRequestDecision`
3236
- `MutationRequestDecisionType`
37+
- `MutationRequestDecisionCategory`
38+
- `MutationRequestLifecycleDecisionType`
39+
- `MutationRequestApprovalDecisionType`
40+
- `MutationRequestVersionResolutionDecisionType`
3341
- `MutationRequestStatus`
3442
- `PendingMutationReason`
3543
- `IMutationRequestStore`
44+
- `IMutationRequestApprovalWorkflowManager`
3645
- `IMutationRequestLifecycleManager`
3746
- `IMutationRequestVersionResolver`
3847
- `IMutationRequestVersionResolutionManager`
3948
- `MutationRequestVersionResolution`
4049
- `MutationRequestVersionResolutionOutcome`
4150
- `VersionedRequestResolutionStrategy`
4251
- `MutationRequestAlreadyExistsException`
52+
- `MutationApprovalRequirementNotFoundException`
53+
- `InvalidMutationApprovalActionException`
4354
- `MutationRequestConcurrencyException`
4455
- `MutationRequestNotFoundException`
4556
- `InvalidMutationRequestTransitionException`
4657

58+
`Abstractions/Requests` is further split into:
59+
60+
- `Requests/Model`
61+
- `Requests/Decisions`
62+
63+
`Abstractions/Approval` is further split into:
64+
65+
- `Approval/Contracts`
66+
- `Approval/Model`
67+
- `Approval/Mapping`
68+
69+
`Abstractions/Resolution` is further split into:
70+
71+
- `Resolution/Contracts`
72+
- `Resolution/Model`
73+
- `Resolution/Strategies`
74+
75+
`Abstractions/Lifecycle` is further split into:
76+
77+
- `Lifecycle/Contracts`
78+
- `Lifecycle/Model`
79+
80+
`Abstractions/Exceptions` is further split into:
81+
82+
- `Exceptions/Approval`
83+
- `Exceptions/Lifecycle`
84+
- `Exceptions/Storage`
85+
4786
### Runtime
4887

4988
The initial runtime layer currently provides:
5089

5190
- `Runtime/Storage/InMemoryMutationRequestStore`
91+
- `Runtime/Approval/MutationRequestApprovalWorkflowManager`
5292
- `Runtime/Lifecycle/MutationRequestLifecycleManager`
5393
- `Runtime/Resolution/MutationRequestVersionResolver`
5494
- `Runtime/Resolution/MutationRequestVersionResolutionManager`
5595

96+
`Runtime/Resolution` is further split into:
97+
98+
- `Resolution/Evaluation`
99+
- `Resolution/Execution`
100+
101+
`Runtime/Lifecycle` is further split into:
102+
103+
- `Lifecycle/Execution`
104+
- `Lifecycle/Validation`
105+
- `Lifecycle/State`
106+
107+
`Runtime/Approval` is further split into:
108+
109+
- `Approval/Execution`
110+
- `Approval/State`
111+
56112
This keeps the first version small while leaving room for later persistence providers such as Entity Framework Core or PostgreSQL-backed governance stores.
57113

58114
## Relationship to Core

0 commit comments

Comments
 (0)