|
1 | | -# ModularityKit.Mutators |
| 1 | + |
2 | 2 |
|
3 | | -[](LICENSE) |
4 | | -[](https://dotnet.microsoft.com/) |
5 | | - |
6 | | -A deterministic, async safe mutation engine with built in policy enforcement, audit logging, and execution context. |
7 | | - |
8 | | ---- |
9 | | - |
10 | | -## Features |
| 3 | + |
11 | 4 |
|
12 | | -- **Deterministic State Mutations** – Apply and simulate state changes safely |
13 | | -- **Policy Enforcement** – Declarative, composable mutation policies |
14 | | -- **Async Safe Execution** – Works across `async/await` boundaries |
15 | | -- **Immutable State Models** – Encourages safe, concurrent operations |
16 | | -- **Audit & Change Tracking** – `ChangeSet` captures granular modifications |
17 | | -- **High Performance** – Minimal overhead per mutation execution |
| 5 | +# ModularityKit.Mutator |
18 | 6 |
|
19 | | ---- |
20 | | - |
21 | | -## Quick Start (Example) |
22 | | - |
23 | | -```csharp |
24 | | -using Microsoft.Extensions.DependencyInjection; |
25 | | -using ModularityKit.Mutators.Abstractions; |
26 | | -using ModularityKit.Mutators.Abstractions.Engine; |
27 | | -using ModularityKit.Mutators.Runtime; |
28 | | -using ModularityKit.Mutators.Runtime.Loggers; |
29 | | -using Mutators.Examples.BillingQuotas.Policies; |
30 | | -using Mutators.Examples.IamRoles.Policies; |
31 | | -using Mutators.Examples.WorkflowApprovals.Policies; |
32 | | -using IamTwoManApprovalPolicy = Mutators.Examples.IamRoles.Policies.RequireTwoManApprovalPolicy; |
33 | | -using FeatureFlagsTwoManApprovalPolicy = Mutators.Examples.FeatureFlags.Policies.RequireTwoManApprovalPolicy; |
| 7 | +[](LICENSE) |
| 8 | +[](https://dotnet.microsoft.com/) |
34 | 9 |
|
35 | | -var services = new ServiceCollection(); |
36 | 10 |
|
37 | | -// 1. Register Mutators engine with options |
38 | | -services.AddMutators(MutationEngineOptions.Strict, addDefaultLoggingInterceptor: true); |
| 11 | +## Packages |
39 | 12 |
|
40 | | -// 2. Build DI provider |
41 | | -var provider = services.BuildServiceProvider(); |
42 | | -var engine = provider.GetRequiredService<IMutationEngine>(); |
| 13 | +- [`ModularityKit.Mutator`](src/README.md) - core mutation runtime |
| 14 | +- [`ModularityKit.Mutator.Governance`](src/Governance/README.md) - request lifecycle, approvals, and governed execution |
43 | 15 |
|
44 | | -// 3. Register policies |
45 | | -engine.RegisterPolicy(new MaxQuotaPolicy()); |
46 | | -engine.RegisterPolicy(new PreventNegativeQuotaPolicy()); |
47 | | -engine.RegisterPolicy(new IamTwoManApprovalPolicy()); |
48 | | -engine.RegisterPolicy(new PreventLastAdminRemovalPolicy()); |
49 | | -engine.RegisterPolicy(new FeatureFlagsTwoManApprovalPolicy()); |
50 | | -engine.RegisterPolicy(new EnforceOrderPolicy()); |
51 | | -engine.RegisterPolicy(new RequireManagerApprovalPolicy()); |
| 16 | +## Repository |
52 | 17 |
|
53 | | -// 4. Execute example scenarios |
54 | | -await Examples.FeatureFlags.Scenarios.EnableNewCheckoutScenario.Run(engine); |
55 | | -await Examples.BillingQuotas.Scenarios.EmergencyIncreaseScenario.Run(engine); |
56 | | -await Examples.IamRoles.Scenarios.GrantAdminScenario.Run(engine); |
| 18 | +- [`Examples`](Examples/README.md) |
| 19 | +- [`Benchmarks`](Benchmarks/README.md) |
| 20 | +- [`Docs`](Docs/) |
| 21 | +- [`Tests`](Tests/) |
57 | 22 |
|
58 | | -// 5. Inspect history |
59 | | -var history = await engine.GetHistoryAsync(stateId: "EnableNewCheckout"); |
60 | | -MutationHistoryLogger.LogHistory(history); |
| 23 | +## Build |
61 | 24 |
|
62 | | -// 6. Metrics & statistics |
63 | | -var stats = await engine.GetStatisticsAsync(); |
64 | | -Console.WriteLine($"Total executed: {stats.TotalExecuted}"); |
65 | | -Console.WriteLine($"Average execution time: {stats.AverageExecutionTime.TotalMilliseconds:F2} ms"); |
| 25 | +```bash |
| 26 | +dotnet build ModularityKit.Mutator.slnx -c Release |
66 | 27 | ``` |
67 | | - |
68 | | -___ |
69 | | -## Core Concepts |
70 | | - |
71 | | -### **Mutation** |
72 | | - |
73 | | -Represents single atomic change to specific state. |
74 | | - |
75 | | -- Implement `IMutation<TState>` |
76 | | -- Define intent (`MutationIntent`) |
77 | | -- Implement `Validate(TState)` |
78 | | -- Implement `Apply(TState)` and optionally `Simulate(TState)` |
79 | | - |
80 | | -___ |
81 | | -### **State** |
82 | | - |
83 | | -Immutable representation of domain data. |
84 | | - |
85 | | -- use `record` types. |
86 | | -- Concurrent safe |
87 | | -- Represents the source of truth for mutations |
88 | | - |
89 | | -___ |
90 | | -### **Policy** |
91 | | - |
92 | | -Controls which mutations are allowed. |
93 | | - |
94 | | -- Implement `IMutationPolicy<TState>` |
95 | | -- Evaluate mutations before application |
96 | | -- Return `PolicyDecision.Allow()` or `PolicyDecision.Deny(reason)` |
97 | | - |
98 | | ---- |
99 | | -## Best Practices |
100 | | - |
101 | | -1. **Immutable State** – Always use `record` types or read-only properties. |
102 | | -2. **Explicit Context** – Pass `MutationContext` per mutation. |
103 | | -3. **Validate Before Apply** – Call `Validate()` before applying a mutation. |
104 | | -4. **Enforce Policies** – Never skip policy evaluation. |
105 | | -5. **Scoped Execution** – Execute mutations inside a controlled engine. |
106 | | -6. **Do Not Share Mutable State** – Each logical operation gets its own state snapshot. |
107 | | -7. **Use Clear IDs for Tracking** – Helps with audit logs and debugging. |
108 | | -8. **Centralized Registration** – Register all policies at engine startup. |
109 | | - |
110 | | ---- |
111 | | -## API Reference |
112 | | - |
113 | | -### Core Interfaces |
114 | | - |
115 | | -- `IMutation<TState>` – Base interface for mutations |
116 | | -- `IMutationPolicy<TState>` – Policy controlling allowed mutations |
117 | | -- `IMutationEngine` – Engine for applying mutations |
118 | | -- `MutationContext` – Context carrying metadata about execution |
119 | | -- `MutationResult<TState>` – Wraps the new state and change set |
120 | | -- `ChangeSet` – Captures state modifications |
121 | | - |
122 | | -## Package Layout |
123 | | - |
124 | | -- `ModularityKit.Mutator` - core mutation runtime, policies, audit, history, and side effects |
125 | | -- [`ModularityKit.Mutator.Governance`](src/Governance/README.md) - governed mutation request lifecycle, pending execution, and approval-oriented contracts |
126 | | - |
127 | | ---- |
128 | | -## Metrics & Logging |
129 | | - |
130 | | -The engine supports: |
131 | | -- Mutation execution history (`GetHistoryAsync`) |
132 | | -- Execution statistics (`GetStatisticsAsync`) |
133 | | -- Logging via `MutationHistoryLogger` |
134 | | -- Optional interceptors for audit and diagnostics |
135 | | - |
136 | | ---- |
137 | | -## Architecture Decision Records (ADR) |
138 | | - |
139 | | -Key architectural decisions for **ModularityKit.Mutators** are tracked as ADRs. They document engine design, policy evaluation, context handling, change tracking, and DI registration. |
140 | | - |
141 | | -| ADR | Title | Summary | |
142 | | -| ------- | --------------------------- | -------------------------------------------------------------------------------------------- | |
143 | | -| ADR-001 | Mutation Engine Design | Defines `IMutationEngine`, engine options, strict vs lenient execution modes | |
144 | | -| ADR-002 | Policy Evaluation | Centralized policy evaluation for validation, risk assessment, and allow/deny decisions | |
145 | | -| ADR-003 | Context & MutationContext | Explicit, per execution flow context for audit, tracing, and tenant isolation | |
146 | | -| ADR-004 | ChangeSet Model | Immutable, granular state changes for audit, rollback, and history inspection | |
147 | | -| ADR-005 | Mutation Audit Abstractions | Structured, immutable audit entries capturing intent, context, changes, and policy decisions | |
148 | | - |
149 | | -See full ADR documentation in [`Docs/Decision/Adr`](Docs/Decision/listadr) for details on each architectural decision. |
150 | | - |
151 | | -## Roadmap |
152 | | - |
153 | | -The planned evolution of the engine is documented in [`Docs/Roadmap.md`](Docs/Roadmap.md). |
0 commit comments