Skip to content

v0.3.0

Latest

Choose a tag to compare

@adcodicem-valueobjects-release adcodicem-valueobjects-release released this 29 Oct 07:47
· 4 commits to main since this release
Immutable release. Only release title and notes can be modified.

0.3.0 (2026-10-29)

⚠ BREAKING CHANGES

  • AdCodicem.ValueObjects.Marten, .Wolverine.Http, .HotChocolate.Data, .Orleans,
    .CommandLine and .CsvHelper are no longer published; their previews stay on nuget.org, deprecated.
    VO0048 is gone.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

  • efcore: under ConfigureValueObjects, an entity whose primary key is a single Guid value object that nothing
    generates is refused with an InvalidOperationException carrying value_object.required when it is added, attached,
    updated or removed with its key unset, or found unset through a navigation, rather than stored with Guid.Empty;
    HasData can no longer seed such a key with Guid.Empty. A key whose type refuses Guid.Empty is now refused there, at
    Add, with that exception, rather than at SaveChanges with a DbUpdateException around a ValueObjectException; both carry
    value_object.required, which ValueObjectErrors.TryGetCode reads. Attach or Update of an aggregate whose dependent's key
    holds a foreign key to such a key, left at its default for the navigation to fill in, a dependent sharing its
    principal's key or one keyed by its principal's key and a number, now tracks that dependent as added, as for a Guid
    key, where it was tracked unchanged: set its foreign key, or its state, by hand. Assign the key, generate it with
    HasValueObjectKeyGeneration(), or opt the key out with ValueGeneratedNever().
  • declare known values and the example as typed members

Features

  • abstractions,analyzers,openapi,swashbuckle: hold raw text to a value object's rules with [ParsesAs], and refuse a default one with [NotDefault] (4ccd44c), closes #156 #159 #114 dotnet/aspnetcore#65348 #160
  • abstractions,aspnetcore,aspnetcore-http,azurefunctions-aspnetcore,hotchocolate: one GraphQL scalar per value object under HotChocolate 16, a refused value answered with its rule code (f17ddf2), closes #162 #158
  • abstractions,aspnetcore,aspnetcore-http,fluentvalidation: answer refused value objects in the application's language, keyed by rule code (9c3fce2), closes #127
  • abstractions,efcore: carry the rule code of a violated CHECK constraint on the provider's error, with UseValueObjectCheckErrors() (6e2f1f0), closes #131 #114 #155
  • abstractions,generator,analyzers,efcore,dapper: declare once that a value object's text is non-Unicode, so SQL Server stores it in varchar and receives varchar parameters (1e4bea4), closes #pragma #if #pragma #171
  • abstractions: make ValueObjectException the FormatException IParsable documents (277a8c2), closes #101
  • ai: carry value objects' rules to Microsoft.Extensions.AI tools and structured output, and answer a refused tool argument with its rule code (38e5b17), closes 102/#114 #126 #132 #125
  • analyzers,marten: fail the build on a value object held by a Marten compiled query, which Marten refuses or answers with the first call's value (9f7ad92), closes #pragma #pragma #pragma #186
  • analyzers: fail the build on a serializer's contract attribute that makes a value object lose its value, with a fix naming protobuf-net's serializer (e952f3e), closes #pragma #132 #pragma #pragma #pragma #pragma #pragma #pragma #serializable #169
  • analyzers: report a static Regex Pattern written without IValueObjectPatternValidator (3e06a79)
  • analyzers: report a value object that Mapperly or the configuration binder creates uninitialized (89b42da), closes #104 #111 #100
  • analyzers: report a value object the Request Delegate Generator would bind from the request body (3a91d57), closes #107
  • analyzers: warn when a logging method writes a value object classified as personal data in clear, and copy its classification where the logging generator reads it (0bbb326), closes #102 #pragma #170
  • aspnetcore-http,azurefunctions,azurefunctions-aspnetcore: bind value objects in the Azure Functions isolated worker, and answer a refused one in an HTTP trigger with its rule code (cc07c90), closes azure-functions-dotnet-worker#2899 #157
  • aspnetcore-http: answer a value object a minimal API refuses with problem details carrying its rule code (d39c2c7), closes #120
  • aspnetcore-newtonsoftjson: apply JSON Patch documents through the value objects' rules, with the codes of the rules a value broke in the problem details (872f4e8), closes #172
  • aspnetcore-newtonsoftjson: carry the rule code of a value a Newtonsoft.Json body refuses into problem details (6175758), closes #114 #139
  • autofixture,bogus,fscheck: create value objects their rules accept in AutoFixture, Bogus and FsCheck (8650e4a), closes #124 #124
  • blazor: type value objects into Blazor forms through their rules, with the refused rule's message under the field and its code on the EditContext (4674a9c), closes #167 #52499 #60498 #168
  • carry the code of the rule in every exception an integration throws, and in MVC's answer to a body (77fdcc5), closes #97 #102 #101 #114
  • commandline: read value objects from System.CommandLine options and arguments through their rules, with the refused rule's message on the terminal and its code on the parse error (c47f918), closes #183 #182
  • convert any number through the type converter, and read one written as text with Newtonsoft.Json (92c48c7), closes #103
  • csvhelper: map value objects as single CsvHelper columns, written as their own text and read through their rules, with the refused rule's code on CsvHelper's exception (362a418), closes #182 #183
  • dapper: declare the column a string value object maps to on its parameter (f265806)
  • declare a value object's pattern as a [GeneratedRegex] through IValueObjectPatternValidator (00e8b82)
  • declare bounds through IValueObjectMinimum and IValueObjectMaximum hooks (3e10539)
  • declare known values and the example as typed members (8115999)
  • deprecate the Pattern option in favour of IValueObjectPatternValidator (1a537f7)
  • efcore: generate value-object keys the provider's way and refuse an entity added without its Guid key (e5491c9), closes #97 #97 #129
  • efcore: map collections of value objects as primitive collections, each element converted, compared and sized (12801dd), closes #97 #128
  • efcore: translate .Value of a value object in LINQ queries to its column, with UseValueObjectQueries() (0eb9439), closes #128 #131 #129 #131 #97 #128 #130
  • efcore: write the minimum lengths, bounds and closed value sets value objects declare as opt-in CHECK constraints (d9f0a94), closes #130 #128 #131
  • efcore: write value objects' patterns as CHECK constraints on SQL Server 2025 and PostgreSQL, the dialect named (45e2fd1), closes #131 #131
  • generate value objects that are generic, nested in an interface, private or protected (8ea069c), closes #64
  • generator: implement IsDefault explicitly, so a tool reading public properties finds the value alone (01559fd), closes #97 #98
  • generator: report a known value declared on an entity identifier (01ce937)
  • generator: write and read value objects with XmlSerializer and DataContractSerializer, opted in per assembly (aa9ca85), closes #122 #124 #121
  • grpc: answer the values a contract-first gRPC service's value objects refuse with INVALID_ARGUMENT and their rule codes (bc66fab), closes #161
  • hand a descriptor's type arguments to a visitor, and declare Schema on the value object contract (89a21ae), closes #98 #117 #113
  • hold a value object's example and known values to its own rules, at build and in the contract kit (104c780), closes #104
  • hotchocolate,hotchocolate-data: filter on every value object in HotChocolate.Data through its scalar, normalized, refused with its rule code and translated by Entity Framework Core (82df428), closes #162
  • identifiers-mongodb: mint entity identifiers on insert, and carry the rules to MongoDB as a $jsonSchema validator (a9c4913), closes #pragma #pragma #122
  • identifiers: add AllowDefault to [EntityId] (6f1a0a0)
  • json: describe every value object in the JSON Schema System.Text.Json exports, for OpenAPI or a language model (c25fea8), closes #106 #118 #117 #117 #115 #105 #106 #104 #113 #116
  • keep a rejected value out of every message, and out of a classified type's exception (10cd350), closes #102
  • keep each known value's name and description in the schema, and name a closed set's values in OpenAPI (55da02e), closes #105 #113 #118 #116 #117
  • marten: query value objects in Marten's LINQ, duplicated fields and compiled queries as their underlying values, with projected values read through their rules (d09a5fe), closes #186 #184
  • messagepack: send value objects through MessagePack and SignalR as their bare values, read through their rules (6b0871e), closes #123
  • modelcontextprotocol: publish value objects' rules in MCP tool schemas, and answer a refused tool argument with its rule code (09cb225), closes csharp-sdk#1865 #116 #125 csharp-sdk#1865 #125 csharp-sdk#1865 #132 #126
  • mongodb: store value objects through MongoDB.Driver as their bare values, with .Value in LINQ and strict reads (b74fc52), closes #129 #122
  • newtonsoftjson: resolve each value object to a contract carrying the converter, for code that hands Newtonsoft.Json a contract resolver alone (ca64bce), closes #132 #172
  • njsonschema: describe value objects as their underlying type, with their rules, in NSwag documents and Confluent Schema Registry schemas (9a9f0c7), closes #160 #159
  • orleans: send value objects in Orleans grain calls as their underlying values, read through their rules, with the rule code back at the caller (fbcc5d4), closes #181
  • protobufnet: write value objects on the protobuf-net wire and in code-first gRPC services as their underlying values, read through their rules (8eb2331), closes #161
  • register every generated JSON converter with its value object's descriptor (e31d38e), closes #63
  • retire the Marten, Wolverine.Http, HotChocolate.Data, Orleans, CommandLine and CsvHelper packages (165c9c0)
  • serilog: log value objects through Serilog as the value they carry, a number as a number (149a18e), closes #119
  • swashbuckle: document value objects under Swashbuckle 10 as their underlying type, with their rules (3e6989d), closes #105 #118
  • testing-data: draw test values each value object accepts from the rules it declares (2374850), closes #124 #121 #124
  • testing: check in the contract kit that a type's known value details line up with its known values (db5c750), closes #117
  • wolverine-http: bind value objects from route, query, header and form values in Wolverine.Http endpoints through their rules, with a coded 400 for a refused or missing one (0bfef70), closes #if #185
  • write no value its type rejects, and store a refused optional one as NULL in EF Core (dd78e7b), closes #108 #97

Bug fixes

  • abstractions,generator,mongodb,efcore: accept µ for μ, and the spellings a culture takes, under the collection validator and CHECK constraints (8105d96)
  • abstractions: call a value object only what the registry can describe (e836dc8)
  • abstractions: check the default Sum for overflow, as the generated one does (cfa19f7)
  • abstractions: give no underlying type to what the registry does not call a value object (4f1f43b)
  • abstractions: let TryResolve answer false for a type it cannot describe (265bee9)
  • abstractions: publish the known values of an annotation as the type holds them (96ced55)
  • abstractions: reject a boxed null as required for a value-typed underlying (50880da)
  • analyzers: find the annotations when another assembly defines them too (594ccd7)
  • analyzers: report a rule an entity identifier writes without its interface as VO0011 (8295a6e)
  • analyzers: report an uninitialized entity identifier as VO0010 (51905df)
  • analyzers: report VO0010 on the default value of a lambda's or a local function's parameter (0c1b8c5), closes #147
  • analyzers: report VO0010 only where default or new is written (2c396f3), closes #pragma
  • analyzers: resolve the contracts VO0033 names as the compiler binds the generated code (a036766), closes #72 #107
  • aspnetcore: bind an MVC value object from the header or body its attribute names, never from the query string (5ab4bba)
  • aspnetcore: bind white-space text as absent, as empty text already was (17d5ced)
  • aspnetcore: decline a model type the value object binder cannot be closed over (4ca63af)
  • aspnetcore: keep the code of the first rule a member broke in errorCodes (457d867), closes #120 #139
  • aspnetcore: read a body with the framework formatter's own JSON options, and replace that formatter alone (fdc0287), closes #114
  • dapper: parse and validate text read into a non-string value object (43d0b2d)
  • dapper: read a Guid into a string value object as text, then validate it (05e9516)
  • dapper: read a SQL NULL as no value object, and refuse it for a required one (a6f359b)
  • dapper: read dates and times in the type the provider returns them (0ef027b)
  • dapper: read which value objects are handled from Dapper's own table (a00aa23)
  • dapper: refuse a value the handler cannot convert with a DataException naming both types (6f223a9)
  • dapper: validate a value read into a string value object as another type (41310cf)
  • deps: Bump bunit, FsCheck and Swashbuckle.AspNetCore.SwaggerGen (#239) (47b3806)
  • deps: Bump LateApexEarlySpeed.Json.Schema and 6 others (d5b2528)
  • deps: Bump the hotchocolate group to 16.6.9 (3c45d16)
  • deps: take .NET 10.0.13, whose SignalR MessagePack hub protocol fixes GHSA-86xp-94pg-8r6r and GHSA-334f-vvp4-7g6p (3b205ec), closes #166 #166 #145 #166 #167
  • deps: take FluentValidation 12.2.0 (d690c8e), closes #189
  • deps: take the xunit.v3 family at 4.0.2, with its runner at 4.0.1 (746d17b), closes #189
  • efcore: let a compiled model build, for native AOT and for an optional value object (856ca92), closes #97 #97 #97 #108
  • fluentvalidation: apply the options chained on MustParseAs and MustSatisfy (3659c7f)
  • fluentvalidation: let null pass MustParseAs and MustSatisfy, and leave it to NotEmpty (aa96cdb)
  • fluentvalidation: name the registration a value object written by hand needs under native AOT (f14e5f5)
  • generator: check a 128-bit bound against the range of its type (39f7fbe)
  • generator: compile a pattern before the named constants that go through it (b4fff46)
  • generator: construct a 128-bit bound from its halves instead of parsing it on every call (9133739)
  • generator: escape a bound for C# where its message quotes it (12ba20a)
  • generator: escape a lone surrogate in every literal the generator writes (1d42d55)
  • generator: escape a type or namespace named after a keyword wherever it is written (7b9f98d)
  • generator: escape the Unicode line terminators in generated literals (c6e81db)
  • generator: fold a multi-line known value description onto its summary line (b14f8fd)
  • generator: fold the characters XML cannot hold out of a known value's summary (8c1907b)
  • generator: follow JsonNumberHandling as the underlying number type does (4091a9d)
  • generator: format dates and times in their round-trip form by default (d2f7e61)
  • generator: format through a span hook without a copy of the value or a silent fallback (0ed74ff)
  • generator: give every value object a file name no other one can take (c7b21b2)
  • generator: keep a blank Pattern as the regular expression it is (82c210a)
  • generator: keep a span formatting hook's retry loop out of ToString (cf53b33), closes #63
  • generator: leave AutoMapper no constructor that skips the rules, so an unmapped conversion throws (4959852), closes #99
  • generator: let a string formatter answer span formatting and interpolation (3d4f788)
  • generator: let the string formatter answer span formatting when both hooks are declared (40de15f)
  • generator: make Parse throw with the code of the rule the text broke (19a08fb)
  • generator: make ToString() go through the formatting hook with the default format (282e5a5)
  • generator: name the type and the rule in a dictionary key the converter refuses (2368b47), closes #89
  • generator: name the type of every local the generated code declares (30dc824), closes #89
  • generator: parse a DateTime back with the kind its round-trip form names (eb39477)
  • generator: publish a summary as the plain text it reads as (90665fe)
  • generator: read a floating-point known value constant in its round-trip form (147a9ed)
  • generator: read a named argument written twice instead of throwing on it (cc26466), closes #136
  • generator: read date and time bounds without the build machine's time zone (1bd5c2e)
  • generator: read every bound and known value in one canonical form per type (2daf1a2)
  • generator: refuse a bound on a string, a Guid or a bool with VO0004 (6b20847)
  • generator: refuse a floating-point bound that is not a finite number (c850525)
  • generator: refuse a group separator in a real number read in the invariant culture (cb48607), closes #96
  • generator: refuse a known value given as a type or an enum member (7ccd933)
  • generator: refuse a known value named after a keyword or a name the type already has (bc112aa)
  • generator: refuse a known value named after an operator or a member the type declares, and say why (60f3923)
  • generator: refuse a known value named after the getter of a generated property (1bdfb08)
  • generator: refuse a known value whose getter takes the name of a member the type declares (be9566b)
  • generator: refuse a real bound too small for its type, and write every real so it reads back (2f14ab5)
  • generator: refuse a ref struct value object with VO0002 (8ee35f1)
  • generator: refuse with VO0019 a value object the generated code cannot reach or name (b8a557d)
  • generator: reject NaN at a declared floating-point bound (f503fa0)
  • generator: report a known value given as an array instead of failing (224af2e)
  • generator: report a value object that is generic or nested in a generic type or an interface (e773e99)
  • generator: report an integer bound or known value outside its type's range (7ffd4e6)
  • generator: report an option set to a value its enum does not define (8ab9250)
  • generator: write a dictionary key as the underlying value, not through a formatting hook (ba7ff0f)
  • identifiers: hold EntityIdFormat.Example to the prefix rules Create holds to (762dfdd)
  • identifiers: let the identifier convention validate what it reads (aeb81d4)
  • identifiers: refuse a JSON null for a non-nullable AnyEntityId (5abc622)
  • identifiers: refuse null in AnyEntityId's type converter, as a generated identifier's does (80f389d)
  • identifiers: report a bad AnyEntityId dictionary key as a JsonException (22cdbc4)
  • identifiers: take an AnyEntityId's text from the identifier's value, not from ToString() (541032b)
  • json: claim only what the converter factory can build, so an optional value object serializes (4c55c6e)
  • json: read a hand-written value object's dictionary key as its underlying value (d56580d)
  • json: refuse a value object nothing registered under native AOT, naming the registration it needs (7b66398)
  • json: serialize a value object written by hand under native AOT, closing its converter through the descriptor (e8db6e1), closes #138
  • json: write a hand-written value object's dictionary key as its underlying value (18526f0)
  • leave a 128-bit value object to a converter of the application's own (3b3d988), closes #79
  • newtonsoft: read numbers and booleans as System.Text.Json reads them (4155885)
  • newtonsoft: read text as text, and refuse a date Newtonsoft.Json already rebuilt (1b569b5)
  • newtonsoft: write every value object as System.Text.Json writes it (8c4a6a2)
  • openapi: describe a value object as a parameter and as the element of a collection (7a513c1), closes #109 #105
  • openapi: document a duration in the constant form it is written in, not as an ISO 8601 duration (22abbae), closes #106
  • openapi: document a hand-written value object nothing registered (b36b71c), closes #75
  • openapi: let a nullable closed set's enum hold null (d72b3aa), closes #118
  • openapi: list a known value that is not of the underlying type as its text (72a710c)
  • openapi: list the values of a closed set as the type writes them in JSON (e101a75)
  • openapi: publish a bound written with an exponent, as the number the type enforces (715d9a0)
  • openapi: publish a value object's example as the type writes it (dbab659)
  • openapi: publish no inert bound on a value object written as a string (650dd29), closes #81
  • publish times, numeric keys and characters as they are written, and leave a closed set's values to the enum (5d67fa0), closes #106 #116
  • publish with native AOT in CI, and stop MustParseAs and the EF Core comparers warning there (1317cb9), closes #108 #113 #116 #120 #123 #pragma #107 #pragma #115
  • read the declared schema in the contract kit's declaration checks, and name no value after details that cannot line up (7d91e42), closes #117 #116
  • sample: report one code per member when a validated payload fails twice (57bb491)
  • swashbuckle: answer the document request under Swashbuckle 10.3.0, the version the package now depends on (deb94c6), closes #156
  • testing: let the contract kit reject values plain JSON cannot write (1a1c4fa)
  • testing: report the length check skipped for a type that did not register itself (8d5216d)

Packaging

  • pack: bound every dependency on our own packages (73e8e62)
  • pack: use the ValueObjects tile as the package icon (6df0cb3)
  • pack: version every package from the v tags again, each asking for the others at its own version or later (8dbe7b7)

Documentation

  • abstractions: say that RegisterGenericDefinition's checks hold under native AOT (90349ea)
  • adr: accept ADRs 0012 and 0013 (f44396d)
  • adr: declare known values and examples as typed members (ffd20bd)
  • adr: propose a targeted pull-request CI, with the heavy jobs before a release (d87dd55)
  • adr: propose versioning the packages in two trains, independently of the frameworks (9bf11ae)
  • adr: record how previews are published, numbered and attested (0e714f7)
  • adr: record one version for every package, independent of .NET (82abc80)
  • adr: retire six satellites, with what each cost (ADR 0015) (35dfe59)
  • adr: return to one version for every package, withdrawing the release trains (ADR 0014) (964fd78)
  • adr: target the pull-request CI by package family, and run the contract kit's checks as one theory (be7fc93)
  • describe one version for every package again, with no satellites train or changelog (b76338f)
  • describe the targeted pull-request CI and record phase A as built in ADR 0013 (6368049)
  • describe the thirty-two packages, without the six ADR 0015 retires (e2d84de)
  • describe the two release trains to consumers (44598fc)
  • describe the unit suite as a test project per CI family (2fd91da)
  • describe the unit suite as it now is, and the commands that run one suite (fa08361)
  • describe weekly previews, the compat island and the versioning policy (5d141ad)
  • generator: say how the generated converter meets a JSON null (a413362)
  • give recipes for messaging, logging, Azure, object mappers, files and HTTP clients (090c3d5), closes #103 #99 #100 #105 #106 #98 #109 #125 #111
  • give the one form each type writes a bound or a known value in (3b33564)
  • json: say what the general-purpose converter asks of options when it is called directly (c1ecf7f)
  • link the date and time rule of a bound to its reason (b8d80c6)
  • list the four required checks, and say that native AOT (Marten) and compat (.NET 11) never become one (16a3711)
  • list where a value object no rule has checked can come from at run time (19226aa), closes #100 #99 #97 #98 #109 #110
  • move the changelog's title above its releases (63f11e7)
  • name no outcome per case for a mix of our versions (b7c9921)
  • name the native AOT job among the checks a pull request must pass (037bc58), closes #115 #115
  • name the tag that breaks a tag-derived pack, and the tags each train's MinVer reads (edfb0ed)
  • name VO0020 beside each option it guards (93a68d9)
  • place the satellites tag by hand when a release fails after tagging (9391a15)
  • point the RegisterGenericDefinition note at the native AOT guard #179 adds (3d1160f)
  • readme: bring four benchmark claims back in line with a rerun (78961a7), closes #63
  • readme: fill each package's README with its id and description (dfbf197)
  • readme: give the form a bound is written in, and what VO0002, VO0004, VO0013 and VO0019 report (505ea5a)
  • readme: give the packages a README of their own (8b33dd1)
  • readme: give the unit suite's commands per package family (d4c93d4)
  • readme: list the frameworks each package supports (2a5554b)
  • readme: list VO0019 and VO0020, and say which formatting hook answers (3f72149)
  • readme: open with the ValueObjects banner (4c86abc)
  • readme: run one test suite with --project (4fe1a29)
  • readme: say that compat (.NET 11) runs on main after each push and gates every stable release (66ad8a8)
  • readme: say that the MongoDB packages are tested on MongoDB 7.0 while MongoDB 8 cannot start on CI (0bf9485)
  • readme: say what a minimal API answers to a rejected value, and correct what probes disproved (4b41b56), closes #107 #105 #103 #97 #107 #105 #103 #109
  • readme: say what the integrations do with a rejected value (891fbe6)
  • readme: state that a 0.x minor may break or remove public API (53ccd8a)
  • record phase 1a of the release trains (448e029)
  • record phase 1b of the release trains (8dfb04d)
  • require the JSON package where value objects are declared, for a serializer context (8c50fb2)
  • run the suites with --project in the pull request checklist (a96d95f)
  • sample: return the country an account's IBAN names, through Iban.CountryCode (b8b6634)
  • say every type-driven integration closes over the visitor, and where Dapper stops under native AOT (29edbc8)
  • say in the API reference which names a known value takes and where VO0010 is reported (3f0b014)
  • say that a known value cannot take the name of a property's getter (44b2746)
  • say that a pull request of more than 100 commits cannot be rebased (cb570b5)
  • say that a unit-suite folder may serve several families, and what the trait guard follows (21649bb)
  • say that build and test, workflows and conventional commits are the required checks, native AOT blocking through build and test (75fffc1)
  • say that compat (.NET 11) and native AOT (Marten) never become required checks (3d5a837)
  • say that compat (.NET 11) gates every stable release in the support table's footnote on the site (1e1e805)
  • say that Dapper leaves a required member uninitialized for a NULL column (a6c647d)
  • say that SaveChanges throws for a row whose key a strict read normalized (79fad2a)
  • say that the heavy jobs run in heavy.yml after the merge and before a release, and how a pull request asks for them (d9afd96)
  • say that the integration flag carries forward, that the format job checks tests/Compat, and when Codecov reports (691c884)
  • say that the registry keeps what it describes by reflection, an identifier ConfigureEntityIds meets included (73ace22)
  • say that the string formatter answers when a type declares both hooks (b8d1f28)
  • say that VO0010 holds for entity identifiers and that [EntityId] takes AllowDefault (21d1064)
  • say what a string formatter costs TryFormat, and that no hook writes a key (af1fe57)
  • say what Dapper and Newtonsoft.Json read, and what a strict read does to a key (fc05620)
  • say what each integration throws for a rejected value, and which reads validate nothing (e946d2a)
  • say what holds back a Dependabot auto-merge now, how a repair preview's heavy failure is undone, and which jobs install the packed packages (64e4f45)
  • say what NuGet does with a mix of our versions, and record the README template (333e698)
  • say what Parse throws and that ToString() goes through a formatting hook (4e76e8d)
  • say what the Newtonsoft.Json converter refuses by default, and how it writes a whole real (ca77e81)
  • say what VO0006, VO0010 and VO0011 now report (0c185e1)
  • say what VO0019 and VO0006 now refuse, and that a real bound cannot underflow (8022f6a)
  • say where the EF Core conventions depart from the visitor and from TSelf.Schema (2a137bc)
  • say which bounds and known values VO0004 and VO0013 now refuse (37e8d64)
  • say which EntityIdFormat members refuse an undeclared granularity (ff3d3cf)
  • say which integrations validate a value, and list VO0019 for identifiers (e4e38ee)
  • say which reads skip validation and what each integration throws (0729b73)
  • say which sample value objects the contract kit cannot run on, and why (2137556)
  • security: verify a restored package through its assemblies (baa5571)
  • site: add local search (b6d89df)
  • site: apply the AdCodicem design system (bd0841e)
  • site: document supported frameworks, previews and the weekly deployment (18e89bd)
  • site: draw the GitHub link and the theme toggle as icon buttons (3094054)
  • site: index only the titles and member headings of the API reference (30c368a)
  • site: say that EF Core 10 on SQLite cannot order decimals under a culture whose separator is not a point (7078c04)
  • site: say what OpenAI, a local provider and MCP clients did with value objects, run live (10a9069)
  • site: search the guides and the API reference apart (da05285)
  • site: take the ValueObjects favicon pack and the NuGet icon (693838a)
  • split CLAUDE.md into a root file of what every change needs and a CLAUDE.md per package and suite (5525f49)
  • state that RegisterGenericDefinition's interface check holds under native AOT (a1e35a2)
  • state where the site, the patterns, the compiled model and the coverage run under the targeted plan (80c7659)
  • stop the sample's IBAN rules at the first failure, and say what empty text gives MustParseAs (c1e6b16)
  • write down what coverage a pull request owes, and what stays uncovered (78894c1)

Refactoring

  • aspnetcore: close the model binder over the descriptor's visitor instead of MakeGenericType (df849be), closes #113 #138
  • drop branches of the known value path that change nothing (1bc2057)
  • efcore: close the conventions' converters and comparers over the descriptor's visitor (976c77d)
  • generator: drop the summary field no emitter reads and a no-op replace (9251917)
  • generator: remove the members no input or caller reaches (8272950)
  • identifiers: map identifiers through the descriptor visitor instead of MakeGenericType (154d13b), closes #138
  • sample: set the identifier collation through ConfigureEntityIds (b87ecde)
  • testing: run the type's registration before the contract kit reads the registry (1fea383)

NuGet packages

Package Version
AdCodicem.ValueObjects 0.3.0
AdCodicem.ValueObjects.AI 0.3.0
AdCodicem.ValueObjects.Abstractions 0.3.0
AdCodicem.ValueObjects.AspNetCore 0.3.0
AdCodicem.ValueObjects.AspNetCore.Http 0.3.0
AdCodicem.ValueObjects.AspNetCore.NewtonsoftJson 0.3.0
AdCodicem.ValueObjects.AutoFixture 0.3.0
AdCodicem.ValueObjects.AzureFunctions 0.3.0
AdCodicem.ValueObjects.AzureFunctions.AspNetCore 0.3.0
AdCodicem.ValueObjects.Blazor 0.3.0
AdCodicem.ValueObjects.Bogus 0.3.0
AdCodicem.ValueObjects.Dapper 0.3.0
AdCodicem.ValueObjects.EntityFrameworkCore 0.3.0
AdCodicem.ValueObjects.FluentValidation 0.3.0
AdCodicem.ValueObjects.FsCheck 0.3.0
AdCodicem.ValueObjects.Grpc 0.3.0
AdCodicem.ValueObjects.HotChocolate 0.3.0
AdCodicem.ValueObjects.Identifiers 0.3.0
AdCodicem.ValueObjects.Identifiers.EntityFrameworkCore 0.3.0
AdCodicem.ValueObjects.Identifiers.MongoDB 0.3.0
AdCodicem.ValueObjects.Json 0.3.0
AdCodicem.ValueObjects.MessagePack 0.3.0
AdCodicem.ValueObjects.ModelContextProtocol 0.3.0
AdCodicem.ValueObjects.MongoDB 0.3.0
AdCodicem.ValueObjects.NJsonSchema 0.3.0
AdCodicem.ValueObjects.NewtonsoftJson 0.3.0
AdCodicem.ValueObjects.OpenApi 0.3.0
AdCodicem.ValueObjects.ProtobufNet 0.3.0
AdCodicem.ValueObjects.Serilog 0.3.0
AdCodicem.ValueObjects.Swashbuckle 0.3.0
AdCodicem.ValueObjects.Testing 0.3.0
AdCodicem.ValueObjects.Testing.Data 0.3.0

The .nupkg and .snupkg files attached to this release carry a signed build provenance attestation (AdCodicem.ValueObjects.0.3.0.sigstore.json). To check one:

gh attestation verify AdCodicem.ValueObjects.0.3.0.nupkg --repo AdCodicem/AdCodicem.ValueObjects

The assemblies inside the packages are attested too. nuget.org re-signs each .nupkg, which changes its digest, but leaves the assemblies as they were packed, so a package restored from nuget.org is checked through one of them:

gh attestation verify ~/.nuget/packages/adcodicem.valueobjects.json/0.3.0/lib/net10.0/AdCodicem.ValueObjects.Json.dll --repo AdCodicem/AdCodicem.ValueObjects --signer-workflow AdCodicem/AdCodicem.ValueObjects/.github/workflows/release.yml