fix(documents): folder PATCH rejects bodies with both name and parentId

z.union picks the first member that parses successfully, so a body
with { name, parentId } would silently be parsed as a rename and the
parentId dropped. The route comment claimed this was rejected — it
wasn't. Adding .strict() to each branch makes the rejection real:
both members refuse extra keys, the union produces a 400, and the
rep gets feedback instead of a silent half-op.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 19:58:10 +02:00
parent 1082b80542
commit e9d5df647d

View File

@@ -4,10 +4,7 @@ import { z } from 'zod';
import { withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { errorResponse, NotFoundError } from '@/lib/errors';
import {
renameFolderSchema,
moveFolderSchema,
} from '@/lib/validators/document-folders';
import { renameFolderSchema, moveFolderSchema } from '@/lib/validators/document-folders';
import {
renameFolder,
moveFolder,
@@ -20,7 +17,11 @@ import {
* (one operation per call) and prevents the rep from accidentally
* doing two unrelated changes in one click.
*/
const patchBodySchema = z.union([renameFolderSchema, moveFolderSchema]);
// `.strict()` on each branch so a body with BOTH name and parentId is
// rejected by both members and the union produces a 400 — without it,
// z.union silently picks the first match and drops the other key,
// which would let a rename request silently swallow a move attempt.
const patchBodySchema = z.union([renameFolderSchema.strict(), moveFolderSchema.strict()]);
export const PATCH = withAuth(
withPermission('documents', 'manage_folders', async (req, ctx, params) => {