From 06e8ec7d5f92dab11957206ca8232734880e055a Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 23 Feb 2026 05:34:09 -0500 Subject: [PATCH 1/2] feat: decompose V1 CRUD routes into pipeline primitives (#86) Replace 6 V1 admin CRUD routes that delegated to V1APIHandler with declarative pipeline definitions using admin-db: - POST /api/v1/admin/organizations/{id}/projects (create project) - POST /api/v1/admin/projects/{id}/workflows (create workflow in project) - POST /api/v1/admin/workflows (create workflow) - PUT /api/v1/admin/workflows/{id} (update workflow + version) - POST /api/v1/admin/workflows/{id}/deploy (deploy workflow) - POST /api/v1/admin/workflows/{id}/stop (stop workflow) Each route now uses pipeline steps (request_parse, validate, set, db_exec, db_query, conditional, json_response) instead of Go delegates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- admin/config.yaml | 65 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/admin/config.yaml b/admin/config.yaml index 8da1acd6..263e80c8 100644 --- a/admin/config.yaml +++ b/admin/config.yaml @@ -1026,27 +1026,78 @@ workflows: config: status: 200 body_from: "steps.get-versions.rows" - # Deploy and Stop delegate to V1APIHandler which manages RuntimeManager + # Deploy: update workflow status to 'active' - method: POST path: "/api/v1/admin/workflows/{id}/deploy" handler: admin-commands middlewares: [admin-cors, admin-auth-middleware] pipeline: steps: - - name: deploy-workflow - type: step.delegate + - name: parse-request + type: step.request_parse config: - service: admin-v1-mgmt + path_params: [id] + - name: set-now + type: step.set + config: + values: + now: "{{ now }}" + - name: activate + type: step.db_exec + config: + database: admin-db + query: "UPDATE workflows SET status='active', updated_at=? WHERE id=?" + params: + - "{{index .steps \"set-now\" \"now\"}}" + - "{{index .steps \"parse-request\" \"path_params\" \"id\"}}" + - name: get-workflow + type: step.db_query + config: + database: admin-db + query: "SELECT id, project_id, name, slug, description, config_yaml, version, status, is_system, workspace_dir, created_by, updated_by, created_at, updated_at FROM workflows WHERE id = ?" + params: ["{{index .steps \"parse-request\" \"path_params\" \"id\"}}"] + mode: single + - name: respond + type: step.json_response + config: + status: 200 + body_from: "steps.get-workflow.row" + # Stop: update workflow status to 'stopped' - method: POST path: "/api/v1/admin/workflows/{id}/stop" handler: admin-commands middlewares: [admin-cors, admin-auth-middleware] pipeline: steps: - - name: stop-workflow - type: step.delegate + - name: parse-request + type: step.request_parse config: - service: admin-v1-mgmt + path_params: [id] + - name: set-now + type: step.set + config: + values: + now: "{{ now }}" + - name: deactivate + type: step.db_exec + config: + database: admin-db + query: "UPDATE workflows SET status='stopped', updated_at=? WHERE id=?" + params: + - "{{index .steps \"set-now\" \"now\"}}" + - "{{index .steps \"parse-request\" \"path_params\" \"id\"}}" + - name: get-workflow + type: step.db_query + config: + database: admin-db + query: "SELECT id, project_id, name, slug, description, config_yaml, version, status, is_system, workspace_dir, created_by, updated_by, created_at, updated_at FROM workflows WHERE id = ?" + params: ["{{index .steps \"parse-request\" \"path_params\" \"id\"}}"] + mode: single + - name: respond + type: step.json_response + config: + status: 200 + body_from: "steps.get-workflow.row" # Load workflow from a server-local filesystem path - method: POST path: "/api/v1/admin/workflows/load-from-path" From ed82e904b542bc030b0f6d9e8b635c78e688b416 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 11:10:44 -0500 Subject: [PATCH 2/2] fix: return 404 on deploy/stop for non-existent workflow IDs (#137) * Initial plan * fix: add 404 handling to deploy and stop workflow pipelines Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: intel352 <77607+intel352@users.noreply.github.com> --- admin/config.yaml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/admin/config.yaml b/admin/config.yaml index 263e80c8..074bfced 100644 --- a/admin/config.yaml +++ b/admin/config.yaml @@ -1037,6 +1037,20 @@ workflows: type: step.request_parse config: path_params: [id] + - name: check-exists + type: step.db_query + config: + database: admin-db + query: "SELECT id FROM workflows WHERE id = ?" + params: ["{{index .steps \"parse-request\" \"path_params\" \"id\"}}"] + mode: single + - name: check-found + type: step.conditional + config: + field: "steps.check-exists.found" + routes: + "false": not-found + default: set-now - name: set-now type: step.set config: @@ -1062,6 +1076,12 @@ workflows: config: status: 200 body_from: "steps.get-workflow.row" + - name: not-found + type: step.json_response + config: + status: 404 + body: + error: "workflow not found" # Stop: update workflow status to 'stopped' - method: POST path: "/api/v1/admin/workflows/{id}/stop" @@ -1073,6 +1093,20 @@ workflows: type: step.request_parse config: path_params: [id] + - name: check-exists + type: step.db_query + config: + database: admin-db + query: "SELECT id FROM workflows WHERE id = ?" + params: ["{{index .steps \"parse-request\" \"path_params\" \"id\"}}"] + mode: single + - name: check-found + type: step.conditional + config: + field: "steps.check-exists.found" + routes: + "false": not-found + default: set-now - name: set-now type: step.set config: @@ -1098,6 +1132,12 @@ workflows: config: status: 200 body_from: "steps.get-workflow.row" + - name: not-found + type: step.json_response + config: + status: 404 + body: + error: "workflow not found" # Load workflow from a server-local filesystem path - method: POST path: "/api/v1/admin/workflows/load-from-path"