feat(api): Add unwrap query param to /wait#2535
Conversation
Lets workflows-as-APIs return the result directly as the response body. Inline results are returned raw via JSONResponse; externalized results respond 413 with the download envelope in detail so callers can still fetch the data. Webhook docs now cover every query param and add a dedicated /wait section explaining the kind envelope and the externalization rationale. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
✅ No security or compliance issues detected. Reviewed everything up to 6a69958. Security OverviewDetected Code Changes| Change Type | Relevant files |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 448e626fc9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Setting response_model=None dropped the typed 200 schema from OpenAPI, regressing generated SDK types to `unknown`. Restore response_model to WaitResultOutput; JSONResponse returns for unwrap=true still bypass serialization at runtime, so the envelope-mode contract stays typed for SDK consumers. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ceb6f548c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| raise HTTPException( | ||
| status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, | ||
| detail=envelope, |
There was a problem hiding this comment.
Declare 413 response schema for unwrap overflow
When unwrap=true and the result was externalized, the handler raises HTTP 413 with a structured download envelope in detail, but that response is not declared in the route metadata. As a result, OpenAPI/SDK output omits this documented control-flow path, so clients cannot type or reliably handle detail.kind without ad-hoc parsing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tracecat/webhooks/router.py">
<violation number="1" location="tracecat/webhooks/router.py:388">
P2: `response_model=WaitResultOutput` is too narrow for `/wait` because `unwrap=true` returns raw JSON on 200. This produces an incorrect OpenAPI contract/client type for successful unwrapped responses.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5da8f9b9d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @router.post("/wait") | ||
| @router.post( | ||
| "/wait", | ||
| response_model=WaitResultOutput | WaitResultUnwrappedOutput, |
There was a problem hiding this comment.
Keep /wait default response schema discriminated
Defining response_model as WaitResultOutput | WaitResultUnwrappedOutput makes the OpenAPI 200 schema include a catch-all object branch (dict[str, Any]), so generated clients can no longer rely on the {kind, ...} discriminator even when unwrap is omitted (the default behavior that still returns the envelope). This is a contract regression for existing typed consumers of /wait because kind-based handling is no longer type-safe. Fresh evidence: the generated client now unions WaitResultUnwrappedOutput into PublicIncomingWebhookWaitResponse, and that unwrapped type includes { [key: string]: unknown }, which subsumes the envelope shape.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/unit/test_webhook_execution_path.py">
<violation number="1" location="tests/unit/test_webhook_execution_path.py:1066">
P3: The 200 schema assertion is too strict for a union `response_model`; FastAPI emits an `anyOf` for the member schemas, not a single `WaitResultOutput` ref.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| success_schema = responses["200"]["content"]["application/json"]["schema"] | ||
| overflow_schema = responses["413"]["content"]["application/json"]["schema"] | ||
|
|
||
| assert success_schema == {"$ref": "#/components/schemas/WaitResultOutput"} |
There was a problem hiding this comment.
P3: The 200 schema assertion is too strict for a union response_model; FastAPI emits an anyOf for the member schemas, not a single WaitResultOutput ref.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/unit/test_webhook_execution_path.py, line 1066:
<comment>The 200 schema assertion is too strict for a union `response_model`; FastAPI emits an `anyOf` for the member schemas, not a single `WaitResultOutput` ref.</comment>
<file context>
@@ -1051,6 +1052,22 @@ async def test_wait_webhook_unwrap_returns_413_for_collection_object(self):
+ success_schema = responses["200"]["content"]["application/json"]["schema"]
+ overflow_schema = responses["413"]["content"]["application/json"]["schema"]
+
+ assert success_schema == {"$ref": "#/components/schemas/WaitResultOutput"}
+ assert overflow_schema == {
+ "$ref": "#/components/schemas/WaitResultUnwrapOverflowResponse"
</file context>
Summary by cubic
Add
unwraptoPOST /webhooks/{workflow_id}/{secret}/waitso workflows-as-APIs can return the raw result when it fits inline; externalized results return413with a download envelope indetail. OpenAPI keeps200typed as the envelope (WaitResultOutput), with413as a typed overflow response.New Features
POST /wait?unwrap=true: returns the workflow’sreturnvalue directly; inline only.unwrap=true: respond413 Payload Too Largeand include thedownload_*envelope indetail.200isWaitResultOutput;413isWaitResultUnwrapOverflowResponse.publicIncomingWebhookWaitsupportsunwrap./wait, envelope kinds, externalization, and query params (incl.vendor=okta). Tests cover unwrap for inline, external file, collection, and OpenAPI invariants.Migration
publicIncomingWebhookWaitacceptsunwrap;200staysWaitResultOutput, and413isWaitResultUnwrapOverflowResponse.unwrapand handle{ kind: "value" | "download_file" | "download_export", ... }.unwrap=true, expect:413with the download envelope underdetail.Written for commit 6a69958. Summary will update on new commits.