diff --git a/packages/api/src/dto/application.test.ts b/packages/api/src/dto/application.test.ts index b91108b73..ed3ad7410 100644 --- a/packages/api/src/dto/application.test.ts +++ b/packages/api/src/dto/application.test.ts @@ -83,3 +83,24 @@ describe("applicationDto zero-argument inputs", () => { expect(applicationDto.tags.input.parse(undefined)).toEqual({}); }); }); + +// Bulk operations cap `ids` at 200 to bound memory/DB work from a single call. +describe("applicationDto bulk id caps", () => { + const idsOfLength = (n: number) => Array.from({ length: n }, (_, i) => String(i)); + + it("rejects a bulkDelete ids array over the cap", () => { + expect(applicationDto.bulkDelete.input.safeParse({ ids: idsOfLength(201) }).success).toBe(false); + }); + + it("accepts a bulkDelete ids array at the cap", () => { + expect(applicationDto.bulkDelete.input.safeParse({ ids: idsOfLength(200) }).success).toBe(true); + }); + + it("rejects a bulkUpdate ids array over the cap", () => { + expect(applicationDto.bulkUpdate.input.safeParse({ ids: idsOfLength(201) }).success).toBe(false); + }); + + it("accepts a bulkUpdate ids array at the cap", () => { + expect(applicationDto.bulkUpdate.input.safeParse({ ids: idsOfLength(200) }).success).toBe(true); + }); +}); diff --git a/packages/api/src/dto/application.ts b/packages/api/src/dto/application.ts index 0fc0753fb..9f9e26255 100644 --- a/packages/api/src/dto/application.ts +++ b/packages/api/src/dto/application.ts @@ -162,7 +162,7 @@ export const applicationDto = { // Table bulk actions: move stage, archive/unarchive, add tags across a selection. bulkUpdate: { input: z.object({ - ids: z.array(z.string()).min(1), + ids: z.array(z.string()).min(1).max(200, "Too many items in a single bulk operation"), status: applicationStatusSchema.optional(), archived: z.boolean().optional(), addTags: z.array(z.string()).optional(), @@ -171,7 +171,7 @@ export const applicationDto = { }, bulkDelete: { - input: z.object({ ids: z.array(z.string()).min(1) }), + input: z.object({ ids: z.array(z.string()).min(1).max(200, "Too many items in a single bulk operation") }), output: z.object({ deleted: z.number() }), },