fix(validation): stop unrecognised boolean strings coercing to a silent false
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s

checkField in packages/validation/src/index.ts (and its browser mirror in
runtime.ts) treated any string other than "true"/"on" as false with no
error, so typos like "treu" or values like "yes"/"1"/"TRUE" silently
passed as false.

Now:
- true/false booleans pass through unchanged
- recognised true strings (case-insensitive, trimmed): true, on, 1, yes
- recognised false strings: false, off, 0, no
- numeric 1/0 coerce (JSON payloads)
- undefined/null/"" still coerce to false (unchecked-checkbox semantics)
- anything else is now a type error (desc.typeMessage or "Must be true or
  false") instead of a silent false

Locked-in behaviours preserved: a required boolean given false still
errors, and parseEnv DEBUG: "true" coercion still works.

Added coverage for recognised strings, numeric 1/0, the type-error
regression guard, absent/empty handling, the required+false case, and a
client/server parity test driving both checkField and the browser runtime
through the same inputs.

Blast radius: searched packages/, examples/, services/ for v.boolean()
usage; all existing call sites (auth consent/rememberDevice, db 'active'
default, example consent checkboxes) feed true/false/'on'/absent values,
none of which change behavior.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 21:26:20 +05:30
co-authored by Claude Opus 5
parent 3ae5d7cf97
commit 281615a4b0
4 changed files with 193 additions and 2 deletions
+15
View File
@@ -2,6 +2,21 @@
## Unreleased
- Fixed `v.boolean()` coercion in `@wrnexus/validation` (`checkField` in both `src/index.ts`
and the browser mirror in `src/runtime.ts`): previously any string other than `"true"` or
`"on"` silently coerced to `false` with no error, so typos and unrecognised values (e.g.
`"yes"`, `"1"`, `"TRUE"`, `"treu"`) passed validation as a silent, wrong `false`. Now
recognised true strings (`"true"`, `"on"`, `"1"`, `"yes"`, case-insensitive and trimmed) and
false strings (`"false"`, `"off"`, `"0"`, `"no"`) coerce as expected, numeric `1`/`0` coerce
(for JSON payloads), and absent/empty input (`undefined`/`null`/`""`) still coerces to
`false` exactly as before (unchanged HTML-checkbox semantics). **Behavior change for
downstream apps:** any other value — an unrecognised string, an object, an array — is now a
type error (`desc.typeMessage` or "Must be true or false") instead of a silent `false`. A
required boolean field given `false` still errors, as before (checkbox-required semantics
are unchanged). A repo-wide search of `packages/`, `examples/`, and `services/` found no
existing `v.boolean()` usage that feeds an unrecognised value, so no call sites are expected
to start failing.
- Fixed `defineEndpoint` (`@wrnexus/core`) so routes invoked through the real HTTP router
(which calls handlers as `handler(ctx)`, with no second argument) actually receive their
request input: it now parses query parameters for GET/HEAD and the JSON body otherwise