Hi A2UI maintainers — thanks for the project.
Context
We're a downstream consumer vendoring a minimal subset of the v0.9 renderers (renderers/web_core schema + renderers/react adapter). We're trying to decide whether/when to move to Zod v4 and wanted to surface one concrete blocker before investing in a migration PR.
The CSP issue with Zod v4
Zod v4 introduces a breaking CSP-relevant change: the schema JIT compiler uses new Function(...) at schema-construction time to generate optimized validators. Under a strict Content Security Policy (script-src 'self', no 'unsafe-eval'), any z.object({...}) etc. throws at import/construction time.
Zod ships a mitigation — z.config({ jitless: true }) — which disables JIT and falls back to the interpreter. That works, but it has two caveats:
- It must be called before any schema is parsed/constructed, app-wide.
- It is process-global, so every copy of Zod in the module graph must honor it. In a monorepo with multiple installs of
zod, it's easy to accidentally bypass. A singleton install (root overrides / peerDep) is effectively required.
For anyone shipping a browser app with a strict CSP, this is a real ergonomic regression versus v3, which works under script-src 'self' out of the box.
What we're doing locally
We're currently pinning our vendored slice of v0.9 to Zod v3 (rolling back an in-flight v4 bump) specifically to restore strict CSP without 'unsafe-eval'. Not ideal long-term — we'd like to pick up v4's perf wins and modern syntax eventually.
Questions for maintainers
- Roadmap: Are there plans to migrate the A2UI renderers (
renderers/react, renderers/web_core, any ng-* renderers) to Zod v4? If so, any ballpark timeline?
- CSP stance: How do you intend to address the CSP/
unsafe-eval implication for downstream consumers? Document the jitless pattern, enforce it in the renderer bootstrap, pin a peer dep, something else?
- Contribution: If it's on your roadmap but unscoped, would a migration PR from a downstream consumer be welcome? We've scoped the upstream churn at roughly ~6–10
z.record(V) call sites (need the two-arg z.record(K, V) form), possible .merge() / .partial() / z.string().email() → z.email() adjustments, and zod dep bumps in the affected renderer packages — on the order of 100–300 lines total. Happy to draft it against a branch if useful.
No urgency on our end — we have a working v3 pin — but we'd rather coordinate than fork.
Thanks!
Hi A2UI maintainers — thanks for the project.
Context
We're a downstream consumer vendoring a minimal subset of the v0.9 renderers (
renderers/web_coreschema +renderers/reactadapter). We're trying to decide whether/when to move to Zod v4 and wanted to surface one concrete blocker before investing in a migration PR.The CSP issue with Zod v4
Zod v4 introduces a breaking CSP-relevant change: the schema JIT compiler uses
new Function(...)at schema-construction time to generate optimized validators. Under a strict Content Security Policy (script-src 'self', no'unsafe-eval'), anyz.object({...})etc. throws at import/construction time.Zod ships a mitigation —
z.config({ jitless: true })— which disables JIT and falls back to the interpreter. That works, but it has two caveats:zod, it's easy to accidentally bypass. A singleton install (rootoverrides/ peerDep) is effectively required.For anyone shipping a browser app with a strict CSP, this is a real ergonomic regression versus v3, which works under
script-src 'self'out of the box.What we're doing locally
We're currently pinning our vendored slice of v0.9 to Zod v3 (rolling back an in-flight v4 bump) specifically to restore strict CSP without
'unsafe-eval'. Not ideal long-term — we'd like to pick up v4's perf wins and modern syntax eventually.Questions for maintainers
renderers/react,renderers/web_core, any ng-* renderers) to Zod v4? If so, any ballpark timeline?unsafe-evalimplication for downstream consumers? Document thejitlesspattern, enforce it in the renderer bootstrap, pin a peer dep, something else?z.record(V)call sites (need the two-argz.record(K, V)form), possible.merge()/.partial()/z.string().email()→z.email()adjustments, andzoddep bumps in the affected renderer packages — on the order of 100–300 lines total. Happy to draft it against a branch if useful.No urgency on our end — we have a working v3 pin — but we'd rather coordinate than fork.
Thanks!