fix(api): validate request bodies with Zod in 4 routes — restores the t06 gate (#9737) - #9779
Merged
diegosouzapw merged 1 commit intoAug 8, 2026
Conversation
… t06 gate The release-green verdict (#9737) lists check:route-validation:t06 as a HARD failure and it is STILL red on the current tip: four routes call request.json() and hand-roll `typeof x === "string"` checks instead of using Zod, which Hard Rule #7 requires and the gate enforces (it scans source and has no allowlist). - src/app/api/plugins/marketplace/install (#9445): InstallBodySchema; the 400 'Missing or invalid name field' response is preserved verbatim. - src/app/api/services/dario/admin/accounts (#8523): DeleteAccountBodySchema for the optional { alias } DELETE body; query-param path untouched. - src/app/api/services/dario/admin/login-start (#8523): LoginStartBodySchema; trimming now happens in the schema, so the forward body is unchanged. - src/app/api/services/dario/admin/import-from-omniroute (#8523): ImportBodySchema for connectionId/alias; invalid shapes fall back to the same 'connectionId is required' 400 as before. All four keep their exact status codes and messages — this is a validation mechanism swap, not a contract change (plugins route suite still 33/33). Adds tests/unit/route-body-validation-t06.test.ts, which runs the gate's own rule inside the unit suite so the next such route fails on ITS OWN PR instead of surfacing weeks later in a base-red sweep. Guard verified by mutation: renaming .safeParse( in one route makes it fail (1 fail), restored from a pre-probe copy. Gates: route-validation:t06, file-size, test-discovery, mutation-test-coverage, dead-code exit 0; typecheck:core clean; eslint clean. Refs #9737
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
… t06 gate (diegosouzapw#9779) The release-green verdict (diegosouzapw#9737) lists check:route-validation:t06 as a HARD failure and it is STILL red on the current tip: four routes call request.json() and hand-roll `typeof x === "string"` checks instead of using Zod, which Hard Rule diegosouzapw#7 requires and the gate enforces (it scans source and has no allowlist). - src/app/api/plugins/marketplace/install (diegosouzapw#9445): InstallBodySchema; the 400 'Missing or invalid name field' response is preserved verbatim. - src/app/api/services/dario/admin/accounts (diegosouzapw#8523): DeleteAccountBodySchema for the optional { alias } DELETE body; query-param path untouched. - src/app/api/services/dario/admin/login-start (diegosouzapw#8523): LoginStartBodySchema; trimming now happens in the schema, so the forward body is unchanged. - src/app/api/services/dario/admin/import-from-omniroute (diegosouzapw#8523): ImportBodySchema for connectionId/alias; invalid shapes fall back to the same 'connectionId is required' 400 as before. All four keep their exact status codes and messages — this is a validation mechanism swap, not a contract change (plugins route suite still 33/33). Adds tests/unit/route-body-validation-t06.test.ts, which runs the gate's own rule inside the unit suite so the next such route fails on ITS OWN PR instead of surfacing weeks later in a base-red sweep. Guard verified by mutation: renaming .safeParse( in one route makes it fail (1 fail), restored from a pre-probe copy. Gates: route-validation:t06, file-size, test-discovery, mutation-test-coverage, dead-code exit 0; typecheck:core clean; eslint clean. Refs diegosouzapw#9737 Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Por que
O veredito do release-green (#9737) lista
check:route-validation:t06como HARD failure — e ele continua vermelho no tip atual (63cf354129), verificado numa worktree limpa. Quatro rotas chamamrequest.json()e validam à mão comtypeof x === "string", o que a Hard Rule #7 proíbe e o gate detecta (ele varre o fonte e não tem allowlist).O que muda
plugins/marketplace/installInstallBodySchemaservices/dario/admin/accountsDeleteAccountBodySchema(body opcional do DELETE; caminho por query-param intocado)services/dario/admin/login-startLoginStartBodySchema(o trim passa a ser do schema)services/dario/admin/import-from-omnirouteImportBodySchemaTroca de mecanismo, não de contrato: os quatro mantêm status e mensagens idênticos (a suíte de sanitização das rotas de plugins segue 33/33).
Guard
tests/unit/route-body-validation-t06.test.tsroda a mesma regra do gate dentro da suíte unitária — assim a próxima rota nesse padrão falha no PR dela, em vez de aparecer semanas depois numa varredura de base-red (foi exatamente o que aconteceu aqui). Validado por mutação: renomear.safeParse(numa das rotas derruba o teste (1 fail); restaurei de cópia pré-sonda.Gates
route-validation:t06·file-size·test-discovery·mutation-test-coverage·dead-code→ todos exit 0.typecheck:corelimpo, eslint limpo.Refs #9737