← Index
Source: projects/verex/docs/features/zod-validation.md (auto-generated by scripts/generate-docs-html.mjs — edit the .md, not this file)

Zod — Runtime Validation + Type Inference (env / ABI / external inputs)

Goal: validate every external input at the boundary — env vars, JSON from RPC/APIs, request bodies, agent tool args — with Zod, getting runtime failure-fast and inferred TS types from a single schema definition.

Source: jay's Zod note, pasted in session 2026-07-17 (no source file). Not yet a dependency anywhere in the monorepo (checked 2026-07-17) — this is a fresh adoption item.

Why

TypeScript types vanish at runtime; process.env and JSON are any-shaped at the edges. One Zod schema gives both: parse-or-throw at startup and the static type (z.infer<typeof Env>) — no drift between validation and types.

Canonical example (from the note)

import { z } from "zod";
const Env = z.object({
  RPC_URL: z.string().url(),
  CHAIN_ID: z.coerce.number().int().positive(),
  VEREX_ADDR: z.string().regex(/^0x[a-fA-F0-9]{40}$/),
});
export const env = Env.parse(process.env); // throws immediately on failure

Key details worth copying: z.coerce.number() (env values are strings), the 0x-address regex, and parsing once at module load so a bad config kills the process at startup, not mid-trade.

Adoption map (per package)

Package What to validate Notes
shared Address, Hex, TxHash schemas + a common parseEnv() helper Put schemas in @verex/sdk (types already flow from there) so all packages share them
sdk RPC/JSON inputs at the SDK boundary (order payloads, market params) Complements viem's own types — Zod covers what arrives as raw JSON
api (S4) Env + request/response validation on Fastify routes fastify-type-provider-zod — schemas become both validation and OpenAPI-ready types
cli Env (RPC_URL, CHAIN_ID, addresses) + command args Also the natural home for the audit item A2 (chainId guard) — a CHAIN_ID: z.literal(31337) dev schema is the guard
mm-agent (S2.5) config.ts per-market config loader (spread, max exposure, on/off) Malformed market config must fail at startup, never mid-quote
web NEXT_PUBLIC_* env at build/boot Client env is stringly-typed too

Dev items

Sequencing & estimate

Not a standalone phase — adopt incrementally: shared schemas + CLI env now (~0.5d, and it closes audit A2), then each package as it's built (api at S4, mm-agent at S2.5). Near-zero marginal cost when done at package-creation time; expensive to retrofit later.