Orchestrator decomposition: replace JobEngine with release-orchestrator + workflow services
- Remove jobengine and jobengine-worker containers from docker-compose - Create release-orchestrator service (120 endpoints) with full auth, tenant, and infrastructure DI - Wire workflow engine to PostgreSQL with definition store (wf_definitions table) - Deploy 4 canonical workflow definitions on startup (release-promotion, scan-execution, advisory-refresh, compliance-sweep) - Fix workflow definition JSON to match canonical contract schema (set-state, call-transport, decision) - Add WorkflowClient to release-orchestrator for starting workflow instances on promotion - Add WorkflowTriggerClient + endpoint to scheduler for triggering workflows from system schedules - Update gateway routes from jobengine.stella-ops.local to release-orchestrator.stella-ops.local - Remove Platform.Database dependency on JobEngine.Infrastructure - Fix workflow csproj duplicate Content items (EmbeddedResource + SDK default) - System-managed schedules with source column, SystemScheduleBootstrap, inline edit UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -855,8 +855,10 @@ services:
|
||||
CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
|
||||
Router__Enabled: "${CONCELIER_ROUTER_ENABLED:-true}"
|
||||
Router__Messaging__ConsumerGroup: "concelier"
|
||||
CONCELIER_IMPORT__STAGINGROOT: "/var/lib/concelier/import"
|
||||
volumes:
|
||||
- concelier-jobs:/var/lib/concelier/jobs
|
||||
- ${STELLAOPS_AIRGAP_IMPORT_DIR:-./airgap-import}:/var/lib/concelier/import:ro
|
||||
- *cert-volume
|
||||
- *ca-bundle
|
||||
ports:
|
||||
@@ -1173,16 +1175,16 @@ services:
|
||||
- riskengine-worker.stella-ops.local
|
||||
labels: *release-labels
|
||||
|
||||
# --- Slot 17: Orchestrator -------------------------------------------------
|
||||
jobengine:
|
||||
<<: *resources-heavy
|
||||
image: stellaops/orchestrator:dev
|
||||
container_name: stellaops-jobengine
|
||||
# --- Slot 48: Release Orchestrator ------------------------------------------
|
||||
release-orchestrator:
|
||||
<<: *resources-medium
|
||||
image: stellaops/release-orchestrator:dev
|
||||
container_name: stellaops-release-orchestrator
|
||||
restart: unless-stopped
|
||||
depends_on: *depends-infra
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://+:8080"
|
||||
<<: [*kestrel-cert, *router-microservice-defaults, *gc-heavy]
|
||||
<<: [*kestrel-cert, *router-microservice-defaults, *gc-medium]
|
||||
ConnectionStrings__Default: *postgres-connection
|
||||
ConnectionStrings__Redis: "cache.stella-ops.local:6379"
|
||||
Authority__ResourceServer__Authority: "https://authority.stella-ops.local/"
|
||||
@@ -1194,43 +1196,28 @@ services:
|
||||
Authority__ResourceServer__BypassNetworks__2: "::1/128"
|
||||
Authority__ResourceServer__BypassNetworks__3: "0.0.0.0/0"
|
||||
Authority__ResourceServer__BypassNetworks__4: "::/0"
|
||||
Router__Enabled: "${ORCHESTRATOR_ROUTER_ENABLED:-true}"
|
||||
Router__Messaging__ConsumerGroup: "jobengine"
|
||||
Router__Enabled: "${RELEASE_ORCHESTRATOR_ROUTER_ENABLED:-true}"
|
||||
Router__Messaging__ConsumerGroup: "release-orchestrator"
|
||||
volumes:
|
||||
- *cert-volume
|
||||
- *ca-bundle
|
||||
ports:
|
||||
- "127.1.0.17:80:80"
|
||||
- "127.1.0.47:80:8080"
|
||||
networks:
|
||||
stellaops:
|
||||
aliases:
|
||||
- jobengine.stella-ops.local
|
||||
- orchestrator.stella-ops.local
|
||||
- release-orchestrator.stella-ops.local
|
||||
frontdoor: {}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/$(hostname)/80'"]
|
||||
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/$(hostname)/8080'"]
|
||||
<<: *healthcheck-tcp
|
||||
labels: *release-labels
|
||||
|
||||
jobengine-worker:
|
||||
<<: *resources-medium
|
||||
image: stellaops/orchestrator-worker:dev
|
||||
container_name: stellaops-jobengine-worker
|
||||
restart: unless-stopped
|
||||
depends_on: *depends-infra
|
||||
environment:
|
||||
<<: [*kestrel-cert, *gc-medium]
|
||||
ConnectionStrings__Default: *postgres-connection
|
||||
ConnectionStrings__Redis: "cache.stella-ops.local:6379"
|
||||
volumes:
|
||||
- *cert-volume
|
||||
healthcheck:
|
||||
<<: *healthcheck-worker
|
||||
networks:
|
||||
stellaops:
|
||||
aliases:
|
||||
- jobengine-worker.stella-ops.local
|
||||
labels: *release-labels
|
||||
# --- Slot 17: Orchestrator (DECOMPOSED) -------------------------------------
|
||||
# jobengine and jobengine-worker removed.
|
||||
# Release endpoints → release-orchestrator service (Slot 47)
|
||||
# Workflow orchestration → workflow service (Slot 46)
|
||||
# Scheduler remains in Slot 14 (scheduler-web / scheduler-worker)
|
||||
|
||||
# --- Slot 18: TaskRunner ---------------------------------------------------
|
||||
taskrunner-web:
|
||||
@@ -2428,6 +2415,37 @@ services:
|
||||
<<: *healthcheck-tcp
|
||||
labels: *release-labels
|
||||
|
||||
# --- Workflow Engine --------------------------------------------------------
|
||||
workflow:
|
||||
<<: *resources-medium
|
||||
image: stellaops/workflow-web:dev
|
||||
container_name: stellaops-workflow
|
||||
restart: unless-stopped
|
||||
depends_on: *depends-infra
|
||||
environment:
|
||||
ASPNETCORE_URLS: "http://+:8080"
|
||||
<<: [*kestrel-cert, *router-microservice-defaults, *gc-medium]
|
||||
ConnectionStrings__WorkflowPostgres: *postgres-connection
|
||||
WorkflowBackend__Provider: "Postgres"
|
||||
WorkflowBackend__Postgres__SchemaName: "workflow"
|
||||
WorkflowBackend__Postgres__ConnectionStringName: "WorkflowPostgres"
|
||||
WorkflowSignalDriver__Provider: "Native"
|
||||
Router__Enabled: "true"
|
||||
Router__Messaging__ConsumerGroup: "workflow"
|
||||
volumes:
|
||||
- *cert-volume
|
||||
ports:
|
||||
- "127.1.0.46:80:8080"
|
||||
networks:
|
||||
stellaops:
|
||||
aliases:
|
||||
- workflow.stella-ops.local
|
||||
frontdoor: {}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/$(hostname)/8080'"]
|
||||
<<: *healthcheck-tcp
|
||||
labels: *release-labels
|
||||
|
||||
# --- Console (Angular frontend) -------------------------------------------
|
||||
# web-ui is replaced by router-gateway serving static files from console-dist volume.
|
||||
# The console-builder init container copies Angular dist to the shared volume.
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
"attestor",
|
||||
"evidencelocker",
|
||||
"sbomservice",
|
||||
"jobengine",
|
||||
"release-orchestrator",
|
||||
"workflow",
|
||||
"authority",
|
||||
"vexhub",
|
||||
"concelier"
|
||||
@@ -67,8 +68,8 @@
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/evidence(.*)", "IsRegex": true, "TranslatesTo": "https://evidencelocker.stella-ops.local/api/v1/evidence$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/proofs(.*)", "IsRegex": true, "TranslatesTo": "https://evidencelocker.stella-ops.local/api/v1/proofs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/verdicts(.*)", "IsRegex": true, "TranslatesTo": "https://evidencelocker.stella-ops.local/api/v1/verdicts$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/release-orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/release-orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/approvals(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/approvals$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/release-orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/v1/release-orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/approvals(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/v1/approvals$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/attestations(.*)", "IsRegex": true, "TranslatesTo": "http://attestor.stella-ops.local/api/v1/attestations$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/sbom(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/sbom$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/lineage(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/lineage$1" },
|
||||
@@ -77,7 +78,7 @@
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/policy(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/policy$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/governance(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/governance$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/determinization(.*)", "IsRegex": true, "TranslatesTo": "http://policy-engine.stella-ops.local/api/v1/determinization$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/workflows(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/workflows$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/workflows(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/v1/workflows$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/aoc(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/aoc$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/administration(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/administration$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/authority/quotas(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/authority/quotas$1" },
|
||||
@@ -105,13 +106,14 @@
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/topology(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/topology$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/evidence(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/evidence$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/integrations(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/integrations$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/scripts(.*)", "IsRegex": true, "TranslatesTo": "http://scheduler.stella-ops.local/api/v2/scripts$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/([^/]+)(.*)", "IsRegex": true, "TranslatesTo": "http://$1.stella-ops.local/api/v1/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/([^/]+)(.*)", "IsRegex": true, "TranslatesTo": "http://$1.stella-ops.local/api/v2/$1$2" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/api/(cvss|gate|exceptions|policy)(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(risk|risk-budget)(.*)", "IsRegex": true, "TranslatesTo": "http://policy-engine.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(release-orchestrator|releases|approvals)(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(release-orchestrator|releases|approvals)(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(compare|change-traces|sbomservice)(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/fix-verification(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/fix-verification$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/verdicts(.*)", "IsRegex": true, "TranslatesTo": "https://evidencelocker.stella-ops.local/api/verdicts$1" },
|
||||
@@ -122,8 +124,8 @@
|
||||
{ "Type": "Microservice", "Path": "^/api/analytics(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/analytics$1" },
|
||||
{ "Type": "Microservice", "Path": "^/scheduler(?=/|$)(.*)", "IsRegex": true, "TranslatesTo": "http://scheduler.stella-ops.local$1" },
|
||||
{ "Type": "Microservice", "Path": "^/doctor(?=/|$)(.*)", "IsRegex": true, "TranslatesTo": "http://doctor.stella-ops.local$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/jobengine(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/jobengine$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/jobengine(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/api/jobengine$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/scheduler(.*)", "IsRegex": true, "TranslatesTo": "http://scheduler.stella-ops.local/api/scheduler$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/doctor(.*)", "IsRegex": true, "TranslatesTo": "http://doctor.stella-ops.local/api/doctor$1" },
|
||||
|
||||
@@ -132,7 +134,7 @@
|
||||
{ "Type": "Microservice", "Path": "^/policy(?=/|$)(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/policy$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/v1/evidence-packs(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/evidence-packs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/runs(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/v1/runs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/runs(.*)", "IsRegex": true, "TranslatesTo": "http://release-orchestrator.stella-ops.local/v1/runs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/advisory-ai(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/advisory-ai$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/audit-bundles(.*)", "IsRegex": true, "TranslatesTo": "https://exportcenter.stella-ops.local/v1/audit-bundles$1" },
|
||||
|
||||
|
||||
@@ -38,9 +38,8 @@ policy|devops/docker/Dockerfile.hardened.template|src/Policy/StellaOps.Policy.Ga
|
||||
# ── Slot 16: RiskEngine ─────────────────────────────────────────────────────────
|
||||
riskengine-web|devops/docker/Dockerfile.hardened.template|src/Findings/StellaOps.RiskEngine.WebService/StellaOps.RiskEngine.WebService.csproj|StellaOps.RiskEngine.WebService|8080
|
||||
riskengine-worker|devops/docker/Dockerfile.hardened.template|src/Findings/StellaOps.RiskEngine.Worker/StellaOps.RiskEngine.Worker.csproj|StellaOps.RiskEngine.Worker|8080
|
||||
# ── Slot 17: Orchestrator ───────────────────────────────────────────────────────
|
||||
orchestrator|devops/docker/Dockerfile.hardened.template|src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.WebService/StellaOps.JobEngine.WebService.csproj|StellaOps.JobEngine.WebService|8080
|
||||
orchestrator-worker|devops/docker/Dockerfile.hardened.template|src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.Worker/StellaOps.JobEngine.Worker.csproj|StellaOps.JobEngine.Worker|8080
|
||||
# ── Slot 17: Orchestrator (DECOMPOSED — see release-orchestrator + workflow) ──
|
||||
# orchestrator and orchestrator-worker removed; replaced by release-orchestrator (Slot 47) + workflow (Slot 46)
|
||||
# ── Slot 18: TaskRunner ─────────────────────────────────────────────────────────
|
||||
taskrunner-web|devops/docker/Dockerfile.hardened.template|src/JobEngine/StellaOps.TaskRunner/StellaOps.TaskRunner.WebService/StellaOps.TaskRunner.WebService.csproj|StellaOps.TaskRunner.WebService|8080
|
||||
taskrunner-worker|devops/docker/Dockerfile.hardened.template|src/JobEngine/StellaOps.TaskRunner/StellaOps.TaskRunner.Worker/StellaOps.TaskRunner.Worker.csproj|StellaOps.TaskRunner.Worker|8080
|
||||
@@ -107,5 +106,9 @@ advisory-ai-web|devops/docker/Dockerfile.hardened.template|src/AdvisoryAI/Stella
|
||||
advisory-ai-worker|devops/docker/Dockerfile.hardened.template|src/AdvisoryAI/StellaOps.AdvisoryAI.Worker/StellaOps.AdvisoryAI.Worker.csproj|StellaOps.AdvisoryAI.Worker|8080
|
||||
# ── Slot 46: Unknowns ───────────────────────────────────────────────────────────
|
||||
unknowns-web|devops/docker/Dockerfile.hardened.template|src/Unknowns/StellaOps.Unknowns.WebService/StellaOps.Unknowns.WebService.csproj|StellaOps.Unknowns.WebService|8080
|
||||
# ── Slot 47: Workflow ───────────────────────────────────────────────────────────
|
||||
workflow-web|devops/docker/Dockerfile.hardened.template|src/Workflow/StellaOps.Workflow.WebService/StellaOps.Workflow.WebService.csproj|StellaOps.Workflow.WebService|8080
|
||||
# ── Slot 48: ReleaseOrchestrator ────────────────────────────────────────────────
|
||||
release-orchestrator|devops/docker/Dockerfile.hardened.template|src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/StellaOps.ReleaseOrchestrator.WebApi.csproj|StellaOps.ReleaseOrchestrator.WebApi|8080
|
||||
# ── Console (Angular frontend) ──────────────────────────────────────────────────
|
||||
console|devops/docker/Dockerfile.console|src/Web/StellaOps.Web|StellaOps.Web|8080
|
||||
|
||||
Reference in New Issue
Block a user