Add StellaOps.Workflow engine: 14 libraries, WebService, 8 test projects

Extract product-agnostic workflow engine from Ablera.Serdica.Workflow into
standalone StellaOps.Workflow.* libraries targeting net10.0.

Libraries (14):
- Contracts, Abstractions (compiler, decompiler, expression runtime)
- Engine (execution, signaling, scheduling, projections, hosted services)
- ElkSharp (generic graph layout algorithm)
- Renderer.ElkSharp, Renderer.ElkJs, Renderer.Msagl, Renderer.Svg
- Signaling.Redis, Signaling.OracleAq
- DataStore.MongoDB, DataStore.PostgreSQL, DataStore.Oracle

WebService: ASP.NET Core Minimal API with 22 endpoints

Tests (8 projects, 109 tests pass):
- Engine.Tests (105 pass), WebService.Tests (4 E2E pass)
- Renderer.Tests, DataStore.MongoDB/Oracle/PostgreSQL.Tests
- Signaling.Redis.Tests, IntegrationTests.Shared

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-03-20 19:14:44 +02:00
parent e56f9a114a
commit f5b5f24d95
422 changed files with 85428 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
{
"schemaVersion": "serdica.workflow.definition/v1",
"workflowName": "ApprovalExample",
"workflowVersion": "1.0.0",
"displayName": "Approval Example",
"workflowRoles": ["DBA", "UR_UNDERWRITER"],
"start": {
"initializeStateExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "start.policyId" } },
{ "name": "annexId", "expression": { "$type": "path", "path": "start.annexId" } }
]
},
"sequence": {
"steps": [
{
"$type": "call-transport",
"stepName": "Validate",
"invocation": {
"address": { "$type": "legacy-rabbit", "command": "pas_policy_validate", "mode": "Envelope" },
"payloadExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "state.policyId" } }
]
}
},
"whenFailure": { "steps": [{ "$type": "complete" }] },
"whenTimeout": { "steps": [{ "$type": "complete" }] }
},
{
"$type": "activate-task",
"taskName": "Approve Policy",
"timeoutSeconds": 86400
}
]
}
},
"tasks": [
{
"taskName": "Approve Policy",
"taskType": "PolicyApproval",
"routeExpression": { "$type": "string", "value": "business/policies" },
"taskRoles": ["UR_UNDERWRITER"],
"payloadExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "state.policyId" } },
{ "name": "annexId", "expression": { "$type": "path", "path": "state.annexId" } }
]
},
"onCompleteSequence": {
"steps": [
{ "$type": "set-state", "stateKey": "answer", "valueExpression": { "$type": "path", "path": "payload.answer" } },
{
"$type": "decision",
"decisionName": "Rejected?",
"conditionExpression": {
"$type": "binary", "operator": "eq",
"left": { "$type": "path", "path": "payload.answer" },
"right": { "$type": "string", "value": "reject" }
},
"whenTrue": {
"steps": [
{
"$type": "call-transport",
"stepName": "Cancel Application",
"invocation": {
"address": { "$type": "legacy-rabbit", "command": "pas_annexprocessing_cancelaplorqt", "mode": "Envelope" },
"payloadExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "state.policyId" } }
]
}
},
"whenFailure": { "steps": [{ "$type": "complete" }] },
"whenTimeout": { "steps": [{ "$type": "complete" }] }
},
{ "$type": "complete" }
]
},
"whenElse": {
"steps": [
{
"$type": "call-transport",
"stepName": "Perform Operations",
"resultKey": "operations",
"invocation": {
"address": { "$type": "legacy-rabbit", "command": "pas_operations_perform", "mode": "MicroserviceConsumer" },
"payloadExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "state.policyId" } },
{ "name": "stages", "expression": { "$type": "array", "items": [
{ "$type": "string", "value": "UNDERWRITING" },
{ "$type": "string", "value": "CONFIRMATION" }
]}}
]
}
},
"whenFailure": { "steps": [{ "$type": "complete" }] },
"whenTimeout": { "steps": [{ "$type": "complete" }] }
},
{ "$type": "set-state", "stateKey": "passed", "valueExpression": { "$type": "path", "path": "result.operations.passed" } },
{
"$type": "decision",
"decisionName": "Operations Passed?",
"conditionExpression": { "$type": "path", "path": "state.passed" },
"whenTrue": {
"steps": [
{
"$type": "call-transport",
"stepName": "Convert To Policy",
"invocation": {
"address": { "$type": "legacy-rabbit", "command": "pas_polreg_convertapltopol", "mode": "Envelope" },
"payloadExpression": {
"$type": "object",
"properties": [
{ "name": "policyId", "expression": { "$type": "path", "path": "state.policyId" } }
]
}
},
"whenFailure": { "steps": [{ "$type": "complete" }] },
"whenTimeout": { "steps": [{ "$type": "complete" }] }
},
{ "$type": "complete" }
]
},
"whenElse": {
"steps": [
{ "$type": "activate-task", "taskName": "Approve Policy" }
]
}
}
]
}
}
]
}
}
]
}