Skip to content

fix(ui,schema): drop unknown form fields and coerce checkbox values for JSON [#2980]#2996

Merged
viniciusdacal merged 1 commit intomainfrom
worktree-fix-2980
Apr 24, 2026
Merged

fix(ui,schema): drop unknown form fields and coerce checkbox values for JSON [#2980]#2996
viniciusdacal merged 1 commit intomainfrom
worktree-fix-2980

Conversation

@viniciusdacal
Copy link
Copy Markdown
Contributor

Summary

Closes #2980.

form() was sending checkbox values as raw strings in JSON bodies ("concluida":"true") when the SDK lacked meta.bodySchema, causing the server to reject the request with 422 Expected boolean, received string. Two changes:

  • coerceFormDataToSchema now treats the schema as the contract: only fields declared in the shape are included; unknown form keys are dropped. Prevents tenantId injection via DevTools and removes a class of .strict()-rejection footguns.
  • form() no-schema fallback uses formDataToObject(fd, { nested: true, coerce: true }) so plain checkbox / number inputs serialize as boolean / number even when there is no schema to drive precise coercion.

Custom non-Vertz schema adapters keep their existing behavior — values pass through untouched so user-supplied parsers stay in control.

Public API Changes

  • coerceFormDataToSchema(formData, vertzSchema)breaking: no longer forwards form fields that are not declared in the schema's shape. Previously these survived to schema.parse() for .strict() schemas to reject; now they are silently dropped both client-side and on the server's form-encoded body parsing path.
  • form() no-schema fallback — additive: now coerces "true" / "false" / numeric strings before sending JSON.
  • No type signature changes.

Test plan

  • New regression tests in packages/ui/src/form/__tests__/form-coercion.test.ts cover both form() does not coerce checkbox string values to boolean when sending JSON #2980 scenarios (no meta + checkbox value="true", no meta + numeric input).
  • New regression test asserts unknown fields are dropped when a schema is present.
  • Existing coerceFormDataToSchema — unknown keys tests updated to assert drop behavior (top-level and nested).
  • vtz test packages/schema packages/ui packages/server packages/integration-tests — all passing (pre-existing JSX/dts failures unrelated).
  • Pre-push gates passed locally: lint, build-typecheck, test, trojan-source.

🤖 Generated with Claude Code

…or JSON [#2980]

Closes #2980.

`form()` was sending checkbox values as raw strings in JSON bodies
(`"concluida":"true"`) when the SDK lacked `meta.bodySchema`, causing
the server to reject with `422 Expected boolean, received string`.

- `coerceFormDataToSchema` now treats the schema as the contract: only
  fields declared in the shape are included, unknown form keys are
  dropped (no `tenantId` injection via DevTools, no leaked stale inputs).
- `form()` no-schema fallback uses `formDataToObject(fd, { nested: true,
  coerce: true })` so plain checkbox/number inputs serialize as boolean
  / number when there is no schema to drive precise coercion.

Custom non-Vertz schema adapters keep their existing behavior — values
pass through untouched so user-supplied parsers stay in control.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@viniciusdacal viniciusdacal merged commit 4855184 into main Apr 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

form() does not coerce checkbox string values to boolean when sending JSON

1 participant