Tracking the actionable part of #507 as a 2.0 improvement.
Problem
"use server" functions type their arguments as written (e.g. email: string), but the input actually crosses a serialization boundary and is attacker-controlled. Typing it honestly as unknown destroys caller-side DX. Users want "typed on the outside, validated on the inside."
Userland wrappers can't solve this: composing a validator around a "use server" function runs into server-function compilation constraints (Server Functions cannot be nested in other blocks or functions - see #507 (comment)), so first-class router support is the only clean path.
Proposal
Accept an optional Standard Schema validator in query and action:
const getUser = query(z.string().email(), async (email) => {
"use server";
// email: string, already validated at the boundary
}, "get-user");
- Caller-side argument types derive from the schema's input type.
- The function body receives the schema's output type, validated server-side before the body runs.
- Standard Schema keeps the router decoupled from any particular validation library (Zod, Valibot, ArkType all implement it), same approach TanStack Router took.
Open design questions:
- Overload shape (
query(schema, fn, name) vs options object) and how it interacts with multi-argument functions.
- Validation failure behavior (throw a typed error? 400-style response for actions?).
- Whether validation also runs on direct server-side calls or only across the RPC boundary.
Refs #507
Tracking the actionable part of #507 as a 2.0 improvement.
Problem
"use server"functions type their arguments as written (e.g.email: string), but the input actually crosses a serialization boundary and is attacker-controlled. Typing it honestly asunknowndestroys caller-side DX. Users want "typed on the outside, validated on the inside."Userland wrappers can't solve this: composing a validator around a
"use server"function runs into server-function compilation constraints (Server Functions cannot be nested in other blocks or functions- see #507 (comment)), so first-class router support is the only clean path.Proposal
Accept an optional Standard Schema validator in
queryandaction:Open design questions:
query(schema, fn, name)vs options object) and how it interacts with multi-argument functions.Refs #507