Skip to content

Commit be0ac08

Browse files
committed
fix(v2-api): accept the redacting log status and envelope the knowledge-search 413
The v2 log presenters parsed status against a five-value enum, but the execution logger persists a sixth, redacting, while a finished run's output is scrubbed. Any such row failed the response parse; on the list route one row 500'd the whole page. The enum is now derived from PersistedWorkflowExecutionStatus with a compile-time exhaustiveness assertion, so a future status is a type error rather than a production 500. POST /api/v2/knowledge/search declared maxBodyBytes without payloadTooLargeResponse, so its 413 returned a bare string instead of the v2 error envelope. It now matches the sibling deploy/rollback routes.
1 parent c8498b8 commit be0ac08

4 files changed

Lines changed: 30 additions & 7 deletions

File tree

apps/docs/openapi-v2-logs.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,8 @@
640640
},
641641
"status": {
642642
"type": "string",
643-
"enum": ["pending", "running", "completed", "failed", "cancelled"],
644-
"description": "Current execution status."
643+
"enum": ["pending", "running", "redacting", "completed", "failed", "cancelled"],
644+
"description": "Current execution status. `redacting` is transient while run output is scrubbed."
645645
},
646646
"level": {
647647
"type": "string",
@@ -1028,8 +1028,8 @@
10281028
},
10291029
"status": {
10301030
"type": "string",
1031-
"enum": ["pending", "running", "completed", "failed", "cancelled"],
1032-
"description": "Current execution status."
1031+
"enum": ["pending", "running", "redacting", "completed", "failed", "cancelled"],
1032+
"description": "Current execution status. `redacting` is transient while run output is scrubbed."
10331033
},
10341034
"level": {
10351035
"type": "string",

apps/sim/app/api/v2/knowledge/search/route.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ describe('POST /api/v2/knowledge/search', () => {
158158

159159
expect(response.status).toBe(413)
160160
expect(await response.json()).toEqual({
161-
error: `Request body exceeds the maximum allowed size of ${V2_KNOWLEDGE_SEARCH_MAX_BODY_BYTES} bytes`,
161+
error: { code: 'PAYLOAD_TOO_LARGE', message: 'Request body is too large' },
162162
})
163163
expect(mockSearch).not.toHaveBeenCalled()
164164
expect(response.headers.get('x-ratelimit-limit')).toBe('100')

apps/sim/app/api/v2/knowledge/search/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const POST = defineV2JsonRoute({
2525
parseOptions: {
2626
maxBodyBytes: V2_KNOWLEDGE_SEARCH_MAX_BODY_BYTES,
2727
invalidJsonResponse: () => v2Error('BAD_REQUEST', 'Request body must be valid JSON'),
28+
payloadTooLargeResponse: () => v2Error('PAYLOAD_TOO_LARGE', 'Request body is too large'),
2829
},
2930
mapInput: ({ body }) => ({
3031
workspaceId: body.workspaceId,

apps/sim/lib/api/contracts/v2/logs.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
v2FolderPathSchema,
1111
v2TimestampSchema,
1212
} from '@/lib/api/contracts/v2/shared'
13+
import type { PersistedWorkflowExecutionStatus } from '@/lib/logs/types'
1314

1415
/**
1516
* v2 logs contracts. The query schemas are reused verbatim from v1 (the request
@@ -21,9 +22,30 @@ const v2LogCostSchema = z
2122
.object({ total: z.number().describe('Total execution cost in USD.') })
2223
.nullable()
2324
.describe('Cost charged for the run, or null when unavailable.')
25+
/**
26+
* Every status the execution logger can persist, including the transient
27+
* `redacting` state written while a finished run's output is scrubbed. The
28+
* column is free text, so a value missing here fails the response parse and
29+
* turns a single row into a 500 for the whole page. `_ExhaustiveLogStatus`
30+
* makes a future addition to the persisted union a compile error instead.
31+
*/
32+
const V2_LOG_STATUSES = [
33+
'pending',
34+
'running',
35+
'redacting',
36+
'completed',
37+
'failed',
38+
'cancelled',
39+
] as const satisfies readonly PersistedWorkflowExecutionStatus[]
40+
41+
type AssertNever<T extends never> = T
42+
type _ExhaustiveLogStatus = AssertNever<
43+
Exclude<PersistedWorkflowExecutionStatus, (typeof V2_LOG_STATUSES)[number]>
44+
>
45+
2446
export const v2LogStatusSchema = z
25-
.enum(['pending', 'running', 'completed', 'failed', 'cancelled'])
26-
.describe('Current execution status.')
47+
.enum(V2_LOG_STATUSES)
48+
.describe('Current execution status. `redacting` is transient while run output is scrubbed.')
2749

2850
/** Execution `files` is a per-run jsonb array of attachment metadata. */
2951
const v2LogFilesSchema = z

0 commit comments

Comments
 (0)