|
| 1 | +# Governance API |
| 2 | + |
| 3 | +This page shows the practical entry points used by the governance examples. |
| 4 | + |
| 5 | +## What this API is for |
| 6 | + |
| 7 | +Use the governance API when execution is not immediate and you need one of these steps first: |
| 8 | + |
| 9 | +- request creation |
| 10 | +- approval workflow |
| 11 | +- stale-version resolution |
| 12 | +- governed execution |
| 13 | +- request and decision history queries |
| 14 | + |
| 15 | +The core package owns direct mutation execution. Governance wraps that execution with a request |
| 16 | +model and stateful decision history. |
| 17 | + |
| 18 | +## Request creation |
| 19 | + |
| 20 | +Use `MutationRequestFactory` when you want to create a request from explicit strings and values: |
| 21 | + |
| 22 | +```csharp |
| 23 | +var request = MutationRequestFactory.PendingApproval( |
| 24 | + stateId: "tenant-42:roles", |
| 25 | + stateType: "IamRoleState", |
| 26 | + mutationType: "GrantRoleMutation", |
| 27 | + intent: new MutationIntent |
| 28 | + { |
| 29 | + OperationName = "GrantRole", |
| 30 | + Category = "Security", |
| 31 | + Description = "Grant elevated role to tenant operator" |
| 32 | + }, |
| 33 | + context: MutationContext.User("requester-1", "Requester One", "Incident escalation"), |
| 34 | + expectedStateVersion: "v10", |
| 35 | + approvalRequirements: |
| 36 | + [ |
| 37 | + MutationApprovalRequirement.SingleActorStep("security-lead"), |
| 38 | + MutationApprovalRequirement.SingleActorStep("platform-owner") |
| 39 | + ]); |
| 40 | +``` |
| 41 | + |
| 42 | +If you already have concrete CLR types, prefer the generic overloads such as: |
| 43 | + |
| 44 | +- `MutationRequestFactory.Approved<TState, TMutation>()` |
| 45 | +- `MutationRequestFactory.PendingApproval<TState, TMutation>()` |
| 46 | + |
| 47 | +They remove repeated `stateType` and `mutationType` strings at the call site. |
| 48 | + |
| 49 | +### Factory choices |
| 50 | + |
| 51 | +- `Pending(...)` for a request that should enter the lifecycle without approval requirements |
| 52 | +- `PendingApproval(...)` for a request that must collect one or more approval steps |
| 53 | +- `Approved(...)` for a request that is terminally approved at creation time |
| 54 | + |
| 55 | +Use the generic overloads when the CLR types already exist. Use the string-based overloads when the |
| 56 | +request metadata comes from an external system or serialized payload. |
| 57 | + |
| 58 | +## Decision history |
| 59 | + |
| 60 | +Use `MutationRequestDecision` when you need to record a lifecycle, approval, or version-resolution decision and the category is already known: |
| 61 | + |
| 62 | +```csharp |
| 63 | +var decision = MutationRequestDecision.Lifecycle( |
| 64 | + MutationRequestLifecycleDecisionType.Approved, |
| 65 | + MutationContext.System("governance-runtime", "Approved by governance")); |
| 66 | +``` |
| 67 | + |
| 68 | +The category-specific helpers are: |
| 69 | + |
| 70 | +- `MutationRequestDecision.Lifecycle(...)` |
| 71 | +- `MutationRequestDecision.Approval(...)` |
| 72 | +- `MutationRequestDecision.VersionResolution(...)` |
| 73 | + |
| 74 | +Use the low-level `MutationRequestDecision.Create(...)` only when the decision type is already dynamic and you do not know the category up front. |
| 75 | + |
| 76 | +### Decision categories |
| 77 | + |
| 78 | +- lifecycle decisions describe request state transitions such as submitted, pending, approved, rejected, executed, canceled, or expired |
| 79 | +- approval decisions describe workflow-level approval actions such as requested, approved, rejected, or quorum satisfied |
| 80 | +- version-resolution decisions describe how the runtime handled stale or matching versions before execution |
| 81 | + |
| 82 | +The helper methods exist so call sites stay readable when the category is already known. |
| 83 | + |
| 84 | +## Governed execution |
| 85 | + |
| 86 | +Use `IGovernanceExecutionManager.ExecuteApproved(...)` when the runtime should resolve an approved request and execute the mutation: |
| 87 | + |
| 88 | +```csharp |
| 89 | +var execution = await executionManager.ExecuteApproved( |
| 90 | + request.RequestId, |
| 91 | + mutation, |
| 92 | + currentState, |
| 93 | + governanceContext: MutationContext.Service("governance-runtime", "Execute approved governance request"), |
| 94 | + strategy: VersionedRequestResolutionStrategy.RejectStale); |
| 95 | +``` |
| 96 | + |
| 97 | +If your state implements `IVersionedState`, use the overload that accepts `currentState` directly and reads `state.Version` for both version selectors. |
| 98 | + |
| 99 | +### Typical execution flow |
| 100 | + |
| 101 | +1. create or load a request |
| 102 | +2. approve the request if needed |
| 103 | +3. resolve the request against the current state version |
| 104 | +4. execute the underlying mutation through the core engine |
| 105 | +5. record the terminal request decision |
| 106 | + |
| 107 | +That flow is what the `GovernedExecution` example demonstrates end to end. |
| 108 | + |
| 109 | +## Common operations |
| 110 | + |
| 111 | +### Create a pending approval request |
| 112 | + |
| 113 | +```csharp |
| 114 | +var request = MutationRequestFactory.PendingApproval( |
| 115 | + stateId: "tenant-42:roles", |
| 116 | + stateType: "IamRoleState", |
| 117 | + mutationType: "GrantRoleMutation", |
| 118 | + intent: new MutationIntent |
| 119 | + { |
| 120 | + OperationName = "GrantRole", |
| 121 | + Category = "Security", |
| 122 | + Description = "Grant elevated role to tenant operator" |
| 123 | + }, |
| 124 | + context: MutationContext.User("requester-1", "Requester One", "Incident escalation"), |
| 125 | + expectedStateVersion: "v10", |
| 126 | + approvalRequirements: |
| 127 | + [ |
| 128 | + MutationApprovalRequirement.SingleActorStep("security-lead"), |
| 129 | + MutationApprovalRequirement.SingleActorStep("platform-owner") |
| 130 | + ]); |
| 131 | +``` |
| 132 | + |
| 133 | +### Record an approval decision |
| 134 | + |
| 135 | +```csharp |
| 136 | +var decision = MutationRequestDecision.Approval( |
| 137 | + MutationRequestApprovalDecisionType.Approved, |
| 138 | + MutationContext.User("approver-1", "Approver One", "Approved after review")); |
| 139 | +``` |
| 140 | + |
| 141 | +### Execute an already approved request |
| 142 | + |
| 143 | +```csharp |
| 144 | +var result = await executionManager.ExecuteApproved( |
| 145 | + request.RequestId, |
| 146 | + mutation, |
| 147 | + currentState, |
| 148 | + governanceContext: MutationContext.Service("governance-runtime", "Execute approved governance request"), |
| 149 | + strategy: VersionedRequestResolutionStrategy.RejectStale); |
| 150 | +``` |
| 151 | + |
| 152 | +## Where to look next |
| 153 | + |
| 154 | +- `README.md` for the package overview |
| 155 | +- `Examples/Governance/*/README.md` for runnable scenarios |
| 156 | +- `src/Governance/Abstractions/Requests/Factory/MutationRequestFactory.cs` for request creation |
| 157 | +- `src/Governance/Abstractions/Requests/Decisions/MutationRequestDecision.cs` for decision helpers |
| 158 | +- `src/Governance/Runtime/Execution/Orchestration/GovernanceExecutionManager.cs` for governed execution |
0 commit comments