fix(api): widen the cancel-execution reason contract to what the route emits - #6592
Conversation
…e emits The internal cancel route mints four outcomes the cancellation service never produces — queue_cancelled, already_cancelled, active_resume_signal_failed and cancellation_not_finalized — but the contract enumerated only the five service reasons. requestJson validates every 2xx against that contract, so a stop that genuinely applied threw on the client. Keep the service enum narrow for the public v2 contract, which delegates wholly to the service and cannot emit the other four, and validate the internal route against a superset. Route the seven success bodies through one contract-typed constructor so drift is a compile error, and delete the dead duplicate cancel contract left behind in contracts/logs.ts.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview Splits the reason vocabulary: the public v2 schema stays on the narrow service enum, and the internal contract uses a superset. Route success bodies now go through a typed Reviewed by Cursor Bugbot for commit fac8b3b. Configure here. |
Greptile SummaryThis PR aligns the internal cancellation response contract with all outcomes already emitted by its route while preserving the narrower public v2 API vocabulary.
Confidence Score: 5/5The PR appears safe to merge; the internal and public cancellation contracts match their respective reachable response vocabularies. All internal route response shapes conform to the widened schema, the public v2 endpoint remains constrained to service-produced reasons, and removal of the duplicate logs contract leaves no unresolved consumers.
|
| Filename | Overview |
|---|---|
| apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.ts | Centralizes seven cancellation response sites behind a typed constructor; all reachable response reasons and required fields conform to the internal contract. |
| apps/sim/lib/api/contracts/workflows.ts | Adds a nine-value internal reason schema while retaining the service’s five-value schema for the public v2 cancellation contract. |
| apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts | Wraps route calls so every successful test response is parsed against the client-enforced contract. |
| apps/sim/lib/api/contracts/workflows.test.ts | Verifies that internal-only reasons remain excluded from the public cancellation enum. |
| apps/sim/lib/api/contracts/logs.ts | Removes an unused duplicate cancellation contract with no remaining importers. |
| apps/sim/lib/execution/cancel-workflow-execution.ts | Clarifies that the service reason type defines the complete vocabulary reachable through the public v2 path. |
Reviews (1): Last reviewed commit: "fix(api): widen the cancel-execution rea..." | Re-trigger Greptile
Summary
cancelWorkflowExecutionReasonSchemaenumerated only the five reasons the cancellation service produces, but the internal cancel route mints four more (queue_cancelled,already_cancelled,active_resume_signal_failed,cancellation_not_finalized).requestJsonvalidates every 2xx against the contract, so a stop that genuinely applied threw on the client — killingpollForTerminalExecutionand rolling back the optimisticcancellingrow in the logs listmain, introduced by improvement(external-endpoints): v2 versions with clean signatures + updated docs based on openapi spec #5273, which tightenedreasonfromz.string().optional()to the enum without touching the route. Not onmain, so it never reached prodcancelWorkflowRundelegates wholly to the service and structurally cannot emit the other four, and the v2 OpenAPI schema documents the enum value by value. Added a superset enum for the internal contract instead.check:openapiconfirms the published spec is unchangedcancelWorkflowExecutionContractincontracts/logs.ts— zero importers, and a stricter wrong copy (narrow enum andreasonrequired), waiting to reintroduce this exact bugType of Change
Testing
route.test.tsnow drives every case through a wrapper that parses each success body against the contract, so all 47 tests are contract-checkedpaused_database_cancel_failedappears in zero tests, so the runtime wrapper alone did not cover it)lib/api,app/api/workflows,hooks/queries,lib/execution,lib/logscheck:api-validation:strict,check:openapi, andbun run lintall passFollow-up (not in this PR)
968 of 1098
route.tsfiles export a rawwithRouteHandler, and 637 of those alreadyparseRequesta contract while never validating their response — this route was one instance. The tractable lever is a ratcheted counter inscripts/check-api-validation-contracts.tsfor that class. Migrating this route todefineInternalJsonRouteis separately blocked: no builder auth policy coverscheckHybridAuth, and its ~600 lines of orchestration have no application use case yet.Checklist