Problem
The primary way actions are called (importing them from a client component, which becomes the RPC stub) has no built-in input validation seam. route.validate is only honored inside the expose() REST path (actions.js:423); invokeAction (the /__webjs/action RPC path the docs push as 'the API') deserializes args and calls fn(...args) with no validation hook. Every action hand-writes argument coercion and returns an ad-hoc single-string error, and the validator cannot be declared once and shared by both call paths.
Design / approach
Let a validate option (a plain function or zod schema the app owns) attach to an action and run on both the RPC and expose paths, returning a structured field-error shape. The framework only invokes the validator and shapes the result; it ships no validation library.
Web-standards fit: Validation is the app's own small function; the framework just calls it on both call paths, adding no dependency or DSL.
Prior art: Next server actions wrapping zod safeParse returning fieldErrors; Remix action zod field errors; tRPC per-procedure input validator across transports; Fastify uniform body validation.
Acceptance criteria
Filed from the production-readiness audit (webjs vs Next.js / Remix / Rails / Turbo / Lit). Theme: data-forms. Priority: P1. Kept to webjs identity: no-build, progressive enhancement, web-components-first, AI-first, batteries-included, close to web standards.
Problem
The primary way actions are called (importing them from a client component, which becomes the RPC stub) has no built-in input validation seam. route.validate is only honored inside the expose() REST path (actions.js:423); invokeAction (the /__webjs/action RPC path the docs push as 'the API') deserializes args and calls fn(...args) with no validation hook. Every action hand-writes argument coercion and returns an ad-hoc single-string error, and the validator cannot be declared once and shared by both call paths.
Design / approach
Let a validate option (a plain function or zod schema the app owns) attach to an action and run on both the RPC and expose paths, returning a structured field-error shape. The framework only invokes the validator and shapes the result; it ships no validation library.
Web-standards fit: Validation is the app's own small function; the framework just calls it on both call paths, adding no dependency or DSL.
Prior art: Next server actions wrapping zod safeParse returning fieldErrors; Remix action zod field errors; tRPC per-procedure input validator across transports; Fastify uniform body validation.
Acceptance criteria
Filed from the production-readiness audit (webjs vs Next.js / Remix / Rails / Turbo / Lit). Theme: data-forms. Priority: P1. Kept to webjs identity: no-build, progressive enhancement, web-components-first, AI-first, batteries-included, close to web standards.