From 33a0b110b59cbf19fcc086548b9963bf15c5bea4 Mon Sep 17 00:00:00 2001 From: Dotta Date: Wed, 10 Jun 2026 20:15:25 +0000 Subject: [PATCH] PAP-10829 preserve intake case fields Co-Authored-By: Paperclip --- .../shared/src/validators/pipeline.test.ts | 8 +-- server/src/__tests__/routines-routes.test.ts | 51 ++++++++++++++++++- server/src/routes/routines.ts | 5 ++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/packages/shared/src/validators/pipeline.test.ts b/packages/shared/src/validators/pipeline.test.ts index d5718d5ad7f..79d93e8ea58 100644 --- a/packages/shared/src/validators/pipeline.test.ts +++ b/packages/shared/src/validators/pipeline.test.ts @@ -5,13 +5,13 @@ describe("pipeline stage variable schema", () => { it("validates select variables require options", () => { expect( pipelineStageConfigSchema.safeParse({ - variables: [{ key: "status", type: "select", options: ["open", "done"] }], + variables: [{ key: "status", label: "Status", type: "select", options: ["open", "done"] }], }).success, ).toBe(true); expect( pipelineStageConfigSchema.safeParse({ - variables: [{ key: "status", type: "select", options: [] }], + variables: [{ key: "status", label: "Status", type: "select", options: [] }], }).success, ).toBe(false); }); @@ -20,8 +20,8 @@ describe("pipeline stage variable schema", () => { expect( pipelineStageConfigSchema.safeParse({ variables: [ - { key: "repo", type: "text" }, - { key: "repo", type: "text" }, + { key: "repo", label: "Repo", type: "text" }, + { key: "repo", label: "Repo", type: "text" }, ], }).success, ).toBe(false); diff --git a/server/src/__tests__/routines-routes.test.ts b/server/src/__tests__/routines-routes.test.ts index 89b7b91f430..b6e36c97e9c 100644 --- a/server/src/__tests__/routines-routes.test.ts +++ b/server/src/__tests__/routines-routes.test.ts @@ -473,6 +473,10 @@ describe("routine routes", () => { userName: "Ada", priority: "high", }, + caseFields: { + userName: "Ada", + priority: "high", + }, }, { agentId: null, userId: "board-user", @@ -480,10 +484,55 @@ describe("routine routes", () => { expect(mockLogActivity).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ action: "routine.run_triggered", entityId: "run-1", - details: { source: "api", status: "issue_created" }, + details: expect.objectContaining({ source: "api", status: "issue_created" }), })); }); + it("runs a routine from an intake form with explicit case fields", async () => { + mockAccessService.canUser.mockResolvedValue(true); + const app = await createApp({ + type: "board", + userId: "board-user", + source: "session", + isInstanceAdmin: false, + companyIds: [companyId], + }); + + mockRoutineService.runRoutine.mockResolvedValueOnce({ + id: "run-2", + source: "api", + status: "issue_created", + }); + + const res = await request(app) + .post(`/api/routines/${routineId}/intake-form`) + .send({ + projectId, + caseFields: { + repo: "paperclip", + }, + userName: "Ada", + }); + + expect(res.status).toBe(202); + expect(mockRoutineService.runRoutine).toHaveBeenCalledWith(routineId, { + source: "api", + projectId, + payload: { + userName: "Ada", + }, + variables: { + userName: "Ada", + }, + caseFields: { + repo: "paperclip", + }, + }, { + agentId: null, + userId: "board-user", + }); + }); + it("passes the board actor through when manually running a routine", async () => { mockAccessService.canUser.mockResolvedValue(true); const app = await createApp({ diff --git a/server/src/routes/routines.ts b/server/src/routes/routines.ts index 73078d1008d..48baca8d3c0 100644 --- a/server/src/routes/routines.ts +++ b/server/src/routes/routines.ts @@ -36,6 +36,7 @@ export function routineRoutes( "executionWorkspaceId", "executionWorkspacePreference", "executionWorkspaceSettings", + "caseFields", "source", ]); @@ -366,11 +367,15 @@ export function routineRoutes( const runPayload = "payload" in control ? control.payload as Record | null : payload; + const caseFields = Object.hasOwn(control, "caseFields") + ? (control.caseFields as Record | null) + : payload; const run = await svc.runRoutine(routine.id, { ...control, source: "api", payload: runPayload, variables: payload, + caseFields, }, { agentId: req.actor.type === "agent" ? req.actor.agentId : null, userId: req.actor.type === "board" ? req.actor.userId ?? null : null,