Repository navigation
Net11 extensions - #62
Merged
Merged
Conversation
…age formatting - ZodPath/ZodPathSegment: typed member/index/key segments with one renderer (Items[0].Name), JSON Pointer, JSONPath, configuration keys and parsing - ValidationError: FullPath, Lower/Upper ErrorBound, MessageFormat, WithPathPrefix, sequence-based equality; legacy Path keeps Zod's "0" form - ZodMessageFormat: lenient named/positional formatting that never throws; RuleMessage uses it and formats with the invariant culture - ZodException lists issues with dotted paths; Merge tolerates default results - ZodIssueCategories/ZodIssueParameters constants - ProblemDetails keys use the canonical renderer - CI SDK pinned to 11.0.100-rc.3 to match global.json
…and rule identity contracts
… by default (G1) The generated check was inverted: the default AllowEmptyStrings=false only rejected null while AllowEmptyStrings=true rejected empty strings. It now follows RequiredAttribute.
…converter errors - J1/J5: map JsonException/JsonReaderException/JsonSerializationException paths via ZodPath.ParseJsonPath, add line/position parameters, fixed generic message naming the expected Zod type - J2: single invalid_json code (category invalid_type) replaces json_error/deserialization_failed - J3: map STJ NotSupportedException/InvalidOperationException raised while deserializing - J4: ZodJsonValidationException (STJ) and ZodNewtonsoftJsonValidationException carry full errors under the converter's JSON path; DeserializeAndValidate unwraps them - J6: Newtonsoft DeserializeAndValidateAsync awaits ValidateAsync - J7-J10: JSON Schema import re-paths with typed index/key segments, mirrors ZodArray length failures, reports JSON kinds with Zod type names and no longer echoes literal input
Benchmarks did not exercise [ZodSchema] validation; the project now loads the merged generator explicitly because it does not import Purview.BuildSdk.
…rules
- Re-path every element/field/catchall/record/tuple error with WithPathPrefix (A1, A2, A4)
- Separate array min/max/length messages reporting the count (A3); tuple arity bounds,
index-prefixed element errors and null pass-through (A5, A6)
- Union issues grouped per option under unionErrors, kept by typed/native unions (A7, A8);
discriminator errors at the discriminator path in declaration order (A9, A10)
- Shared identities: ZodIssueCodes, ZodMessages, ZodIssues, ZodTypeNames (A11-A17);
one aggregated unrecognized_keys issue (A13); typed RefineCtx issues (A18, A19);
intersection de-dup (A20); span rule errors via ZodRuleErrors (A21)
- Every built-in rule reports origin, Zod category, bounds with inclusivity and parameters;
IZodFailureDescriber for direction-dependent categories (B1-B4)
- Default messages never echo the input; ZodErrorOptions.IncludeReceivedValues (B9);
consistent UUID arguments, null custom-message default, invariant formatting (B5-B8);
RequiredRule shares the "{displayName} is required" identity (B10)
# Conflicts: # CHANGELOG.md
…gistration, JSON paths) Adds ZodValidationDepth (MaxDepth 32, M.E.V semantics), ZodGeneratedValidation/ZodGeneratedMember (runtime message formatting, typed nested re-pathing, reflection-free member walking), IZodJsonPathMapper, ZodSchemaRegistration + AddZodSchemaRegistration (applied by AddZodSharpFactory), ZodAsyncMemberAttribute and RegexRule.DefaultMatchTimeoutMilliseconds.
…ion and document transformers Describes what ZodSharp enforces in ASP.NET Core 11 OpenAPI documents. Core JSON Schema export gains method-based vendor extensions, ConvertUntyped, discriminated-union oneOf export, inner-schema unwrapping for validator adapters, and JSON Schema mappings for the IP, CIDR, JWT, duration, base64, date, date-time and time string rules.
# Conflicts: # src/src/ZodSharp/Rules/Base64StringRule.cs # src/src/ZodSharp/Rules/CidrRule.cs # src/src/ZodSharp/Rules/DateStringRule.cs # src/src/ZodSharp/Rules/DatetimeStringRule.cs # src/src/ZodSharp/Rules/DurationRule.cs # src/src/ZodSharp/Rules/IPAddressRule.cs # src/src/ZodSharp/Rules/JWTRule.cs # src/src/ZodSharp/Rules/TimeStringRule.cs # src/src/ZodSharp/Schemas/ZodDiscriminatedUnion.cs
- ZodSchemaOptionsValidator<T> implements IAsyncValidateOptions<T> on .NET 11;
ValidateOnStart runs async and service-aware rules in a scope, synchronous
access checks the synchronous rules only (the platform contract).
- OptionsBuilder<T>.AddZodSchemaValidator registers through Validate<TValidator>()
on .NET 11 and validates only the builder's options name; new overload with
validateOnStart and configurationSection.
- Failures read "{name}: {location}: {message} ({code})", using configuration
keys (Smtp:Servers:0:Host) when a section is recorded (defect O1);
ZodValidateOptionsResult keeps the full errors.
- Core IZodMessageFormatter / DefaultZodMessageFormatter localization hook and
the shared ZodPathNaming enum.
- Microsoft.Extensions.Options 11 on net11.0; TestHost versions per TFM.
…and typed results - ZodProblemDetailsWriter is the single implementation behind the endpoint filter, ZodExceptionHandler, ZodTypedResults and every To*ProblemDetails / ToValidationProblem overload; a contract test proves byte-identical bodies. - Keys from FullPath.ToDottedString with ZodPathNaming; messages through IZodMessageFormatter in the request culture; ErrorType templates only when complete; FormatMessages honoured; StatusCodeSelector/StatusCodeOverride win; reserved members protected; per-issue camel-cased safe parameters; full MVC copies; traceId everywhere; safe ValidationIssue DTO with segments, typed bounds and unionErrors (defects D1-D10). - WithZodSharpValidation() on any IEndpointConventionBuilder (route groups included) via an endpoint filter factory: build-time parameter selection and validator resolution, every argument validated, build-time missing-validator failures, .NET 11 binding-failure pass-through or conversion, and 400 problem+json response metadata (defects D6, D11, D12). - ZodTypedResults.ValidationProblem/Problem, ToValidationProblem(HttpContext), options overloads, Apply() for merging foreign errors (for the Microsoft.Extensions.Validation bridge), source-generated JSON metadata for Native AOT, and BindAndValidateWithZod(section). - Skill and package README updated; CHANGELOG records the behaviour changes.
…osoft.Extensions.Validation New net11.0 package that registers ZodSharp as the first .NET 11 validation resolver, so minimal APIs, Blazor Server and Blazor WebAssembly validate ZodSharp types with ZodSharp. - AddZodSharpValidation(): registers the factory and ZodValidatableInfoResolver, and places the resolver through IPostConfigureOptions<ValidationOptions>, so it is first whether AddValidation() is called before, after or not at all (proved against the real M.E.V generator interceptor). - Type, property and parameter adapters: Container/Name resolution (IZodMemberResolver, reflection fallback, dictionary-backed schemas), CurrentValidationPath prefixing, MaxDepth parity, sync Validate throwing on async-only rules, M.E.V parameter path conventions, union case following. - Rich-error side channel: ValidateContext.ZodReport and IZodValidationReportSink. - StringLocalizerZodMessageFormatter, auto-enabled with an IStringLocalizerFactory. - ValidationOptions.ValidateAsync<T> for non-HTTP hosts. - IZodMessageFormatter in ZodSharp.Core.
# Conflicts: # Directory.Packages.props # src/src/ZodSharp/Core/IZodMessageFormatter.cs
…add OpenAPI test suite Adds AspNetCore.OpenApi.UnitTests (net11.0): every keyword mapping row for OpenAPI 3.1 and 3.2, conflict policy and Development logging, unknown types untouched, polymorphic oneOf with resolvable case references, C# union cases constrained without restructuring, operation responses (body, [AsParameters], union, WithZodSharpValidation, ProducesValidationProblem merge, 422 from the registry) and a JsonSchema.Net cross-check of fixture payloads against the emitted document. Registers the package in the solution, pack validation and the changelog.
# Conflicts: # .config/purview-build.json # .csharpierignore # CHANGELOG.md
…, async graph, member lookup
Change 1: Validate calls one ValidateMember_X method per member. Change 2:
ValidateMember/ValidateMemberAsync/IsValidatableMember (no nested recursion). Change 3:
TryResolveMember (reflection-free). Change 4: Paths constants, typed index/key segments,
WithPathPrefix, JsonNames + ToJsonNamedPath, MessageFormat + parameters formatted at runtime
with ZodMessageFormat. Change 5: per-assembly Register/AddZodSharp{Assembly}Schemas, adapters
implement IZodUntypedValidator, depth guard. G11 async graph, G23
IValidatableObject/IAsyncValidatableObject/AsyncValidationAttribute, Change 9 service-aware
custom method + [ZodAsyncMember], Change 7 union/closed dispatch, G21 options failures.
…ation pipeline On net11.0 AddZodSharpProblemDetails() registers a scoped ZodRequestValidationReport as the bridge's IZodValidationReportSink and post-configures ProblemDetailsOptions.CustomizeProblemDetails so the ZodSharp callback runs before any application callback. Pipeline responses are rewritten with ZodProblemDetailsWriter.Apply (DataAnnotations entries merged, ErrorType/selector/override status mirrored to the response), and DataAnnotations-only failures gain only the issues projection. WithZodSharpValidation() skips parameters the bridge already validates on endpoints the pipeline covers, logged once at Debug. The AspNetCore package references Extensions.Validation for net11.0 only. The contract test now covers Mode A alongside the filter, exception and manual paths.
…mpatible; bump version to 2.5.0
…AddValidation() call
…onents, problem details)
…harp client rules
…ion context and tests ZODSGEN047-052 (+ code fix for 047), G22 ErrorType.Origin and MessageFormat, CreateValidationContext without reflection, a JSON Schema rule-construction fix for argument-less rules, and tests: one per G defect, ValidateMember parity, TryResolveMember round trip, registration/untyped validators, service-aware and member-targeted async, depth guard, .NET 11 async DataAnnotations, unions, closed hierarchies, IAsyncValidateOptions and pipeline caching. Benchmarks add member validation and member resolution.
scripts/test-packed-consumers.ps1 (just smoke-packed-consumers) packs every shipping package to an isolated feed and package cache, then publishes and runs consumers that reference packages only: a Native AOT console, a Blazor WebAssembly app (trimmed, and RunAOTCompilation when wasm-tools is installed) and a Native AOT minimal API. scripts/assert-no-compiler-host-assemblies.ps1 scans build and publish output by file name and by deps.json, runtimeconfig.json and boot manifest content. Every publish job and recipe now runs it, and the new packed-consumers PR job runs the gate and the forbidden-content rule proof. It fails first, with what to do, if Purview.SourceGeneratorFramework cannot be restored. Release-Flow.md lists every gate and a pre-release checklist; AGENTS.md matches.
The leak scan must catch each kind of leak it claims to (file names, fingerprinted and compressed WebAssembly files, deps.json, runtimeconfig.json and boot manifests), must fail when it has nothing to scan, and -Allow must not hide a leak elsewhere. Every workflow job that publishes must run the scan, the packed-consumers job must run the gate and the rule proof, and ForbiddenContent must keep every rule.
ZodType<TOutput, TInput>.Or returns ZodTypedUnion<TOutput, TOther>, which derives from ZodType<Union<TOutput, TOther>, object>, and Union is a struct, so rooting expands Union<Union<...>> without bound. Every change that breaks the cycle breaks the 2.4.2 API: sealing is CP0009 and, measured, still leaves 32 IL3054 warnings. The tolerance stays, scoped to the rooted mode.
…Transitive PrivateAssets="none" on Microsoft.AspNetCore.OpenApi flowed its build/ targets into in-repo ProjectReference consumers as well, where its XML-comment target fed duplicate doc IDs to the generator and every AspNetCore.OpenApi unit test failed with a 500. Revert that and ship buildTransitive/Purview.ZodSharp.AspNetCore.OpenApi.targets instead: it adds only the Microsoft.AspNetCore.OpenApi.Generated interceptor namespace, which is what a package-only consumer lacked (CS9137). A direct Microsoft.AspNetCore.OpenApi reference still builds; the namespace is then listed twice, which is harmless.
…le proof input publish-aot-sample, verify-trim and wasm-size now leak-scan the project's bin/Release as well as the publish folder, as the CI jobs do. verify-pack-rules reads artifacts/, which pipeline-local-release empties into the local feed, so say to pass -PackagesFolder there.
…f generating them The generators emitted ZodSchemaAttribute and ErrorTypeAttribute, public and documented, into every compilation as post-initialization output. Every project in a solution then documented the same type IDs, and the ASP.NET Core OpenAPI XML-comment generator - which reads an app's own public and internal types plus each referenced project's XML file - added the same key twice and threw: "An item with the same key has already been added. Key: T:ZodSharp.Core.ErrorTypeAttribute". [Embedded] already prevented CS0436, and internal copies would still have collided, so both attributes are now ordinary public types in Purview.ZodSharp, with the members the package already exposed as generated [Embedded] copies, and the generators emit no marker types at all. 2.x is affected too (reproduced with 2.4.2 on net10.0).
…umer gate Consumer (d) is a [ZodSchema]/[ErrorType] class library referenced by a minimal API that references Microsoft.AspNetCore.OpenApi directly, with XML documentation on in both projects. The gate publishes and starts it, checks the OpenAPI comment cache has no duplicate documentation ID and no ZodSharp marker attribute, and asserts /openapi/v1.json carries both projects' schemas, the ZodSharp constraints and the XML-comment descriptions, plus the library's issue paths and ErrorType at runtime. Against the previous packages it fails with the duplicate-key crash.
BuildSdk 1.2.0 rewrites its managed .editorconfig and adds PRBLZ0001: every project a Blazor WebAssembly client references must be browser-safe. Purview.ZodSharp, Extensions.Validation, Blazor and Examples.Shared run in the browser, so they set PurviewBrowserSafe=true, which turns the browser-unsupported API, trim and AOT diagnostics into errors; all four build clean under them.
… bind The generator emitted value.Member == null and != null. A [Required] Nullable<T> member whose type defines ==(string?, T) plus an implicit conversion to string (every string-backed value object) failed with CS9342, and a reference type with a ==(T?, string?) overload failed the same way. Every emitted null test is now is null / is not null. 2.4.2 emitted the same comparison.
An adapted or required rule's identity was emitted as (object)rule as IZodRule, a runtime type test on a boxed struct that crashed the Mono AOT compiler (0xC0000005) for a scalar with a type-level [ZodRule]. The generator knows whether the rule implements IZodRule, so it emits (IZodRule)rule, or null when it does not. The packed Blazor WebAssembly consumer now carries such a scalar.
An error inside a value object (Email.Value) resolved to a boxed copy of the struct, which cannot be a FieldIdentifier model, so DataAnnotationsValidator and Server-side ZodValidator dropped the message and WebAssembly showed it only in the summary. The generated TryResolveMember, the validation bridge and the Blazor field locator now attribute it to the nearest reference-type owner and its member. A nested scalar's messages also use the owning member's display name.
The 2.x overloads that take only a status code, a registry or a lookup (and ToValidationProblem()) cannot see the ZodProblemDetailsOptions an application registers, so their body diverged from the exception handler. There is no ambient options instance to read without a request, so they keep their 2.x output, are marked [Obsolete] with the exactly equivalent options, and point to the HttpContext and options overloads.
…ibutes ZodSharp 2 generated [Embedded] copies of ZodSchemaAttribute and ErrorTypeAttribute into every compilation, so a library rebuilt against ZodSharp 3 loses them and package validation against a 2.x baseline reports CP0001. The upgrade note explains why the removal is safe and gives the suppression command and entries.
…ation The .NET 11 endpoint filter validates every parameter a registered resolver claims, so registering the bridge from AddZodSharpBlazor answered invalid requests before handlers ran. AddValidation() alone adds nothing. AddZodSharpBlazor now registers type validation only; AddZodSharpValidation(configure, validateParameters) and ZodValidationOptions.ValidateParameters choose explicitly, and any registration that asks for parameters wins.
…issues Generated validators attach declaringType (a full CLR type name) and member to every error for localization, and issues[].parameters sent both to API clients. They are now omitted by default and stay on ValidationError.Parameters; ZodProblemDetailsOptions.IncludeDiagnosticParameters writes them again.
Every generated schema now has ValidateAsync, so CA1849 reports each Validate call in async code. The generated Validate remarks now say whether the type requires async validation, and the upgrade notes recommend awaiting ValidateAsync, which completes synchronously for such types, instead of suppressing the analyzer.
….claude copy
The skills installed from other repositories were committed twice, once under .agents/skills/ and
once under .claude/skills/. The two trees were identical, so the .claude copy is removed and
/.claude/ is now gitignored. This repository is not agent-specific.
The installed set was refreshed with the skills CLI, into the universal location only:
npx -y skills@1 add purview-dev/build-sdk -s '*' -a universal -y
npx -y skills@1 add purview-dev/sourcegenerator-framework -s '*' -a universal -y
npx -y skills@1 add purview-dev/engineering-playbook -s '*' -a universal -y
The six purview-sourcegenerator-* skills are new; AGENTS.md already told contributors to load
them, but they were never installed. The build-sdk and engineering-playbook skills are updated to
their current content.
src/Directory.Build.props sets PurviewSkillsAgents to universal, so the SDK's InstallPurviewSkills
target no longer defaults to writing a copy for every agent. InstalledSkillTests checks that the
lockfile and .agents/skills/ agree, that no authored skill is copied there, and that neither a
.claude/skills/ folder nor a CLAUDE.md exists.
AGENTS.md said .agents/skills/ was gitignored. It is committed, together with skills-lock.json, and is written only by the skills CLI with -a universal. A new Installed skills section lists each skill, its source and when to load it, gives the commands to add, update and restore them, and states the rule that no .claude/ folder or CLAUDE.md is committed. The scattered npx skills add hints now point at that section, and the copilot instructions say the same.
…r installed here AGENTS.md now says plainly that skills/ is authored for consumers of the packages, so it is never installed into this repository's .agents/skills/; InstalledSkillTests enforces it.
…oesn't fail the step
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.