This example models multi step workflow where ordering matters and approvals can be blocked by policy.
It is the best sample to read if you want to understand how the engine behaves when one mutation must happen before the next one can safely proceed.
The domain state contains:
- a workflow ID
- an initiator
- an ordered list of workflow steps
Each step has status and may be approved or rejected by user.
The example includes two scenarios:
- a happy path where the steps are approved in sequence
- a rejection path where one or more approvals are blocked
- a side effects path where workflow start and rejection emit observable side effects
- ordered workflow mutation
- approval and rejection transitions
- policy checks that depend on prior state
- mutation context usage for audit and traceability
- failure handling when step is out of order or unauthorized
- side effect emission for monitoring, alerting, and follow-up workflows
Program.csWorkflowApprovals.csprojState/ApprovalWorkflowState.csState/WorkflowStep.csState/StepStatus.csMutations/StartApprovalMutation.csMutations/ApproveStepMutation.csMutations/RejectWorkflowMutation.csPolicies/EnforceOrderPolicy.csPolicies/RequireManagerApprovalPolicy.csScenarios/HappyPathScenario.csScenarios/RejectedScenario.csScenarios/SideEffectsScenario.cs
Program.cs:
- registers the engine with strict options
- resolves
IMutationEngine - registers workflow policies
- runs both scenarios
- prints engine statistics
The sample is intentionally sequential. It shows how stateful process can be advanced step by step while the engine keeps the mutation logic and policy logic separate.
StartApprovalMutation creates workflow from list of step names.
- validates initiator and step list
- creates workflow steps from names
- initializes a new workflow ID
- emits change entry for the created step list
- emits a
WorkflowStartedside effect throughSideEffect.Create(...)
ApproveStepMutation approves a single workflow step.
- validates the step index
- validates approver input
- updates the targeted step
- emits change entry for the step status
RejectWorkflowMutation marks the whole workflow as rejected.
- applies rejection to every step
- records the actor who rejected the workflow
- emits workflow level change
- emits a critical
WorkflowRejectedside effect throughSideEffect.Critical(...)
EnforceOrderPolicy prevents a step from being approved before the previous step has been approved.
This is the main rule that makes the example a proper ordered workflow.
RequireManagerApprovalPolicy limits approvals to designated managers.
This policy demonstrates:
- checking the specific mutation type
- validating approver identity
- rejecting unauthorized actors
HappyPathScenario starts workflow and approves each step in order.
It shows:
- successful workflow initialization
- sequential approvals
- final state printing
RejectedScenario starts workflow and then attempts approvals that may be blocked.
It shows:
- policy driven rejection
- per step logging
- final workflow state inspection
SideEffectsScenario starts a workflow and then rejects it to show side effects in the result object.
It shows:
- a standard side effect created with
SideEffect.Create(...) - a critical side effect created with
SideEffect.Critical(...) - how
Severity,RequiresAction, andDatacan be read fromMutationResult.SideEffects
State/ApprovalWorkflowState.csState/WorkflowStep.csState/StepStatus.csMutations/StartApprovalMutation.csMutations/ApproveStepMutation.csPolicies/EnforceOrderPolicy.csPolicies/RequireManagerApprovalPolicy.csScenarios/SideEffectsScenario.cs
dotnet run --project Examples/Core/WorkflowApprovals/WorkflowApprovals.csprojYou should see:
- workflow start output
- approvals or policy rejections for individual steps
- the final workflow state
- engine statistics at the end
This sample is the cleanest one to study for staged business processes and ordered execution rules.