Changelog
All notable changes to vld and its integration crates.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.6.0 - 2026-11-07
Breaking changes
- Regex:
regex-liteis no longer public.string().regex(Regex)/regex_msgand thevld::regex_litere-export are removed; usestring().pattern("...")/pattern_msg, orvld::rules::Pattern::new(..)to handle an invalid pattern. - optional / nullable / nullish now differ:
nullable()object fields are required (absent →missing_field,null→None) and listed in JSON Schemarequired;optional()no longer addsnullto its JSON Schema (parsing still acceptsnull, which serde writes forNone). TypeScript output follows:x?: T,x: T | null,x?: T | null. - Unions:
Either/Either3serialize untagged, so a union inside an object round-trips as the bare value instead of{"Left": ...}; unions forwardoutput_jsonto the matching variant. - Removed everything deprecated in 0.5: the
serialize/deserializefeatures,ZFloat::finite,ZObject::field_schema/deep_partial,vld-actix::VldJsonError,vld-diesel/vld-sqlx::validate_update,vld-surrealdb::validate_record,vld-http-common::{ValidationIssueWithCode, format_issues_with_code, format_json_parse_error, format_utf8_error},vld-tower/vld-rama::try_validated,vld-tauri::{validate_event, validate_state, validate_plugin_config, validate_channel_message},impl_to_lapin!,impl_to_redis!,impl_to_redis_async!,vld-utoipa::{impl_into_params!, impl_to_schema_query!, impl_to_schema_path!}. DynSchemahas a new required methoddyn_parse_missing(implemented for everyVldSchema; only hand-written impls need it).
Migration from 0.5
See the migration guide.
Added
- Custom rules (
vld::rules): theRule<T>trait (key, check, optional message and JSON Schema keywords),rules::from_fn,ZString::rule/rule_msg(keeps the string builder) andVldSchema::rule/rule_msgon any schema. A failing rule reportsCustom { code: <key> }, so it can be translated by key. #[derive(Validate)]on enums, following serde: externally tagged,tag,tag+content,untagged; unit, newtype, tuple and struct variants; variantrename/alias/skip/other/rename_alland enumrename_all/rename_all_fields. The output is the enum itself; the JSON Schema isoneOfwith an OpenAPIdiscriminator(anyOfwhen untagged).#[derive(Validate)]supports#[serde(flatten)]on fields: parsed from the same object, JSON Schema properties merged.VldSchema::parse_missing: what an absent object key parses to (wrappers forward it).vld::Schema:VldSchemaplus the JSON Schema traits underopenapi, forfn f() -> impl vld::Schema<Output = T>.ValidationIssue::path_string()(.lab.fund[0].vigor).- Inherent
vld_parse_valueon#[derive(Validate)]/schema!types (noVldParseimport needed). Either::into_innerwhen both sides have the same type.
Fixed
vld-schemars:patternandpatternPropertiesregexes are compiled once and cached instead of on every validated value.
0.5.1 - 2026-11-06
Changed
- All crates use Rust edition 2024 (MSRV unchanged: 1.85).
- Dependencies used only by tests are no longer normal dependencies (
serde/serde_jsonin several integration crates); unused ones are removed (hyper,http-body-utilinvld-axum,serdeinvld-config,tokioinvld-tonic,hyper/hyper-utilinvld-tower). vld-fake: password generation no longer usesunsafe; every crate forbidsunsafe_code.- Every public item has rustdoc documentation (
missing_docsis on in every library crate).
0.5.0 - 2026-11-06
Breaking changes
- Features: the
stdfeature is gone (everything it gated is always available);serialize/deserializeare deprecated no-ops (removed in 0.6);diffenablesopenapi. - Date backends are additive:
ZDate/ZDateTimeare generic over the backend and each feature has its own module (vld::chrono,vld::jiff,vld::time).vld::date()/vld::datetime()and the prelude aliases exist only when exactly one backend is enabled. Previously the backend was picked silently (chrono > jiff > time). - Issue codes:
IssueCodehas a typed variant for every built-in check (InvalidLength,InvalidFormat,InvalidDate,NotMultipleOf,InvalidEnumValue,InvalidUnion,NotUnique,MissingField,FileTypeNotAllowed,SerializeError, …);Customis for user codes only.TooSmall/TooBigcarryorigin: SizeOriginand aserde_json::Valuebound instead of anf64.IssueCode,StringValidationandDateKindare#[non_exhaustive]. - Messages: default messages come from one English template table; an absent required key reports
missing_field(a presentnullstaysinvalid_type);Displayno longer appends ", received X" toinvalid_type. - Module layout: core split into
schema/,error/,object/,macros/,openapi/(old pathsvld::json_schema,vld::diff,vld::format,vld::i18n,vld::inputremain as aliases); the inherentto_json_schema()duplicates are gone (use theJsonSchematrait). - JSON Schema: optional / nullable / nullish fields and unions emit
anyOf(wasoneOf);ZNullable::is_required()isfalse. - Caching:
schema!,impl_validate_fields!,impl_rules!and#[derive(Validate)]build field schemas once per process, so field schemas must beSend + Sync + 'static;VldInput::to_json_valuereturnsCow<Value>. #[derive(Validate)]:validate_fields()/parse_lenient()are generated only with#[vld(lenient)];#[serde(flatten)]/aliasare compile errors.- Web adapters: every
VldJsonextractor answers 415 unless the content type isapplication/jsonorapplication/*+json; malformed JSON is 422 with the validation body (was 400); 422 issues carry acodefield; query/path/form/header/cookie values fall back to the original text when the schema wants a string (parse_coerced). vld-tower/vld-rama:validated()returnsOption<T>; the tower inner service receivesRequest<ValidatedBody<B>>(non-JSON bodies are no longer buffered).vld-warp:handle_rejectionmaps warp rejections to their real status (unknown → 500 instead of 404); bodies are read as a stream with a limit (413).vld-ntex: ntex 4 is the default (ntex-4);default-features = false, features = ["ntex-3"]keeps ntex 3. Crate MSRV 1.97.vld-ts:with_defaultemitsx.nullish().transform((v) => v ?? d)(Zod) /v.nullish(x, d)(Valibot), matching vld, which acceptsnullthere.vld-clap:validate_or_exitrequiresclap::CommandFactoryand reports clap's real argument names; depends on clap 4.- Issue paths in
vld-tauri,vld-leptos,vld-dioxus,vld-surrealdbhave no leading dot (user.email,items[0]).
Migration from 0.4
- Cargo features: drop
std,serialize,deserializefrom your feature lists. - Dates: with one backend nothing changes. With several, call
vld::chrono::date(),vld::jiff::datetime(),vld::time::time()and namevld::chrono::ZDateetc. - Matching on issue codes: replace
IssueCode::Custom { code: "…" }checks for built-in errors with the typed variants;TooSmall { minimum, .. }now hasoriginand a JSONminimum(minimum.as_f64()). Add a_ =>arm (non-exhaustive enums). PreferIssueCode::key()for stable string codes. - Messages / i18n: tests that compared full English messages may need updating (
missing_field, no ", received X"); custom translation tables can add the new keys (missing_field,type.<name>,too_small.<origin>, …), the specific key is tried before the generic one. - JSON Schema consumers: expect
anyOfinstead ofoneOffor optional / nullable fields and unions. - Web clients: send
Content-Type: application/json; handle 415 and 422 (malformed JSON), read the newcodefield. - Derive: add
#[vld(lenient)]where you callvalidate_fields()/parse_lenient(). - ntex 3 users:
vld-ntex = { version = "0.5", default-features = false, features = ["ntex-3"] }. - vld-ts: regenerate client schemas; defaults now accept
null. - vld-clap: derive
clap::Parser(or implementCommandFactory) forvalidate_or_exit, or callvalidate_cli. - tower / rama:
validated()returnsOption;try_validatedis deprecated. - MSRV: see MSRV.md.
Added
- Schemas: sized integers
vld::i8()…u64(),isize(),usize(),vld::f32();vld::null(),vld::never(),vld::char();vld::from_serde(),vld::from_str(),vld::enum_of(); time-of-dayvld::{chrono,jiff,time}::time()/vld::time_of_day();vld::record_with_keys()andZRecord::ordered(); tuples up to arity 12; string formatsbase64url()andjson();ZInt::coerce();ZDecimalgt/lt/multiple_of. parse_coerced: schema-aware fallback for values coerced from text.duration()accepts fractional seconds (1.5,"1.5s","PT1.5S").ZFile::within(base); accessors onZLiteral,ZMap,ZPipe,ZDiscriminatedUnion,ZLazy;type_error()onZBoolean/ZEnum/ZJsonValue.- Complete Russian, German and Spanish message tables; translated type names.
vld-integration-common(new crate): shared DB column wrappers, errors and form helpers for the integration crates.vld-http-common:VldHttpError, shared JSON / form / header / cookie helpers,require_json_content_type, aconformancetest suite (test-only feature).vld-redis: asyncAsyncRedisConn(aiofeature); the selected redis crate is re-exported.vld-ntex: ntex 4 support.vld-rocket:vld_413_catcher,vld_415_catcher,vld_catchers().vld-diesel:VldFloat,VldBool; wrappers usable inInsertable/.filter().vld-sea:with-json,with-chrono,with-uuid,with-rust_decimal,with-bigdecimalfeatures.vld-clap:validate_cli.vld-ts: named exports (to_zod_export,to_valibot_export).vld-schemars: OpenAPI 3.0 output underSchemaSettings::openapi3().
Changed
- Faster parsing:
serde_json::Valueinput is borrowed, cached field schemas (regexes compiled once), default messages rendered without allocations per key. vld-aidereusesvld-schemarsinstead of duplicating the bridge.vld-fakegenerates values that satisfy far more schemas (patterns, all core formats,$ref,multipleOf, property counts) and seeds its randomness.imageis built without its defaultavifencoder (only image headers are read).- Packages ship only
src/, README, LICENSE (and the changelog forvld).
Fixed
- Strings: char-safe ISO date/time parsing (calendar-checked), strict IPv4/IPv6/CIDR via std,
url_strictblocks loopback / private / link-local hosts, stricter email / phone / credit-card / emoji / cuid2,base64url()rejects+and/. - Numbers: exact
ZInt(no f64 round-trip), NaN never passes a bound, tolerantmultiple_of, the strictest bound is reported,f32::MAXaccepted. - Collections / combinators: an inner error without issues no longer turns into success; union errors keep per-variant issues; maps reject duplicate keys; unique compares numbers by value; no panics in intersection / tuple /
schema!/ derive. - Dates: one strict format for all backends;
timedatetime defaults rendered as RFC 3339. ZPath::within/ZFile::within: lexical containment with symlink resolution of existing ancestors; file reads are bounded.- JSON Schema / OpenAPI: resolvable
$refs and nested components forschema!and derive,requiredomits optional fields, literals emitconst, mapsprefixItems, recordspropertyNames/ min/maxProperties;diffsees changes inside optional fields and composites. - Derive: generics, raw identifiers, serde
rename_all/rename(deserialize)/skip/default;synerrors instead of panics. - Web adapters: body limits → 413 everywhere (ntex overflow detection, salvo forms, rocket mount paths and form limits, warp chunked bodies, rama limit errors), actix
{id:\d+}path patterns, percent-decoded path params and cookies, lossless query coercion, repeated keys as arrays. vld-lapin:nack_decode/reject_decodesettle invalid messages instead of valid ones.vld-sea: chrono / uuid / json / decimal / bytes columns no longer validate asnull.vld-sqlx:VldIntdecodes INT4 / INT2 columns.vld-utoipa: annotations kept on refs / composites / arrays,anyOfand type arrays supported, exact u64 bounds, tupleprefixItems.vld-schemars:$refs point at the generator's definitions path; the validator handles$ref,additionalProperties,prefixItems.vld-ts: valid JS output (escaped literals, quoted keys,new RegExp), descriptions and defaults kept.vld-tonic,vld-tauri,vld-clap,vld-surrealdb,vld-leptos,vld-dioxus: clean issue paths.vld-config:VldConfigError::source(); env example usestry_parsing.
Security
- All 0.4.7 security fixes (see below).
vld-tower:Application/JSONand+jsonbodies no longer bypass validation; JSON bodies are size-limited.- Dependencies refreshed: 21 of 23 RustSec advisories cleared (two remaining, documented in
deny.toml).
Removed
- The
stdfeature. - Inherent
to_json_schema_inner()/ per-typeto_json_schema()duplicates (theJsonSchematrait remains;ZObject::to_json_schemastays). vld-http-common::extract_path_param_names(unused).
0.4.7 - 2026-11-06
Fixed
- Security
vld-poem:VldPathread the query string instead of the matched route parameters, so/users/42failed validation and/users/42?id=7validatedid = 7(client-controlled). It now usesRequest::path_params. - Security
vld: a string longer than 100 bytes whose 97th byte falls inside a multi-byte character (e.g. Cyrillic, accented Latin) panicked while being stored asreceivedin an error — any request body could crash the process. Truncation is now char-based. - Security
vld:string().iso_date()/iso_time()/iso_datetime()panicked on non-ASCII input ("123é56789") and on"2024-01-01T". - Security
vld(timebackend):datetime()panicked when the UTC instant left the supported year range ("9999-12-31T23:00:00-05:00"); it is now a validation error. Requirestime >= 0.3.47. - Security
vld:string().url_strict()never checked IPv6 hosts (http://[::1]/,http://[fd00::1]/,http://[::ffff:127.0.0.1]/passed) and allowed0.0.0.0,localhost.and*.localhost. - Security
vld:path().within(base)acceptedbase/../outsidewhen the target did not exist (lexical..was not resolved). - Security
vld-http-common: with duplicate cookie names the last value won, allowing cookie tossing; the first occurrence now wins.
0.4.6 - 2026-11-05
Fixed
- JSON Schema / OpenAPI:
.with_default(value)now emits"default": value(#8). TheJsonSchemaimpl forZDefaultrequires the output type to beserde::Serialize chrono,jiff,time(human-readable) andipnetoptional deps now enable theirserdefeatures so date/network outputs keep working withwith_defaultin schemas
0.4.5 - 2026-10-01
Fixed
- HTTP adapters: enforce body size limits (axum
Bytes/DefaultBodyLimit, warpcontent_length_limit, poeminto_bytes_limit, ramaBody::limited) and return 413 on overflow vld-warphandle_rejection: mapLengthRequired→ 411 andPayloadTooLarge→ 413 (no longer collapse to 404)- actix/ntex/salvo: remapped payload overflow to 413 instead of always 422
- poem: malformed JSON uses
format_vld_error(422); ramaValidateJsonLayeraligned to 422 + validation body vld-http-common: consistent issue path formatting (.user.age) forformat_issues/format_issues_with_code
0.4.4 - 2026-10-01
Changed
- Bump optional core pins:
infer0.22,rust_decimal1.43,ipnet2.12.2,phonenumber0.3.10 vld-salvo: Salvo 1.x only (salvo = "1"); crate MSRV 1.94 (cross-major>=0.89,<2dual-loadssalvo_core/ breaksExtractible)vld-sea: dual featuressea-orm-1(default) /sea-orm-2;Value::Enum→ JSON string on 2.x; entity-macro integration tests stay on 1.x;sea-orm-2requires Rust 1.94+vld-utoipa: dual featuresutoipa-5(default) /utoipa-6(CI tests both);utoipa-6requires Rust 1.88+
Deferred
syn3, ntex 4 (beta), aide 0.16 (alpha) — wait for stable / lower churn
0.4.3 - 2026-10-01
Fixed
- Omit
.optional()/.nullish()/.with_default()fields from JSON Schemarequired(and keep.nullable()required) acrossschema!,#[derive(Validate)], andZObject(#6) - Forward
JsonSchema::is_requiredthrough describe/refine/message/transform/catch wrappers vld-utoipa::json_schema_to_paramsuses the objectrequiredarray (so.nullable()query/path params stay required; oneOf+null no longer forcesRequired::False)
0.4.2 - 2026-09-27
Added
- Add vld-rama for Rama HTTP validation
Fixed
- Bring VldSchema into schema! OpenAPI helpers
- Drop unused VldSchema imports after schema! fix
0.4.1 - 2026-09-26
Fixed
- Register transitive nested OpenAPI schemas
- Alias NestedSchemaCollectFn for clippy type_complexity
0.4.0 - 2026-07-02
Changed
- Refresh crate links and dependency versions
- Enhance build and test process for vld-diesel
Fixed
- Make path-within check deterministic in CI
- Restore integration examples and tests build
chore
- Downgrade workspace and crate versions to 0.3.0
- Update dependencies and versions in Cargo files
- Normalize integration dependency compatibility
- Implement workspace-wide pre-release hook and update preflight script
- Update pre-release hook and streamline release preflight script
ci
- Unify workspace checks and restore crate version badges
release
- V0.4.0 — unified utoipa OpenAPI, jiff/time date backends
0.3.0 - 2026-03-20
Added
- Add native vld transport integrations
- Add bytes schema and stricter datetime validation
- Add timezone-aware datetime and file schema validation
- Extend file storage access and refresh formatting
- Add advanced typed schemas and cross-crate format support
Changed
- Simplify Zod/Valibot generation API
- Remove unused full-file generation internals
- Gate heavy validators behind opt-in features
Fixed
- Run per-crate preflight safely
- Satisfy strict clippy assertions
- Replace approximate float constant in test
- Keep float coercion expectation exact
- Remove unused prelude imports
- Remove unused prelude imports
- Remove unused VldSchema import in tests
- Align prelude trait imports for optional combinators
- Stabilize clippy around optional combinator trait imports
chore
- Automate changelog generation with git-cliff
0.2.0 - 2026-03-19
Added
- Add tonic gRPC integration for vld validation
- Add Leptos integration for shared server/WASM validation
- Add SQLx integration for vld validation
- Add Dioxus integration for shared server/WASM validation
- Add ntex web framework integration
- Add aide/schemars integration for OpenAPI generation
- Add SurrealDB integration for JSON document validation
- Add bidirectional bridge between vld and schemars
- Add reverse direction — schemars → vld validation
- Add nested schema auto-registration for OpenAPI
- Auto-register nested schemas in utoipa components
- Auto-register nested schemas in schemars definitions
Changed
- Replace standalone functions with macro+trait API
- Add nested schema auto-registration section to README
- Add dead code allowance for unused schema methods
Fixed
- Formatting, clippy warnings, and missing imports across workspace
chore
- Register vld-tonic and vld-leptos in workspace, update root README
- Register vld-sqlx in workspace, update root README
- Register vld-dioxus in workspace, update root README
- Register vld-ntex in workspace, update root README
- Register vld-aide in workspace, update root README
- Register vld-surrealdb in workspace, update root README
- Register vld-schemars in workspace, update root README
0.1.3 - 2026-03-19
Added
- Add health check endpoint and response schemas
- Generate json_schema() for derive(Validate), enabling utoipa integration
chore
- Bump workspace version to 0.1.2
- Remove .idea/ from git tracking