IsUuidV7 - #73
Merged
Merged
Conversation
Check<Guid> offers only IsEmpty/IsNotEmpty, so a service accepting a client-generated identifier cannot state that it must be a UUIDv7. A v4 GUID from a misconfigured client is accepted and surfaces later as index fragmentation. Key decisions recorded in the plan: - Require both the version nibble (7) and the RFC 9562 variant bits (10). Guid.Version reports the version regardless of the variant, so a version-only test accepts values Guid.CreateVersion7 cannot produce. - Read both fields by reinterpreting the Guid over a field overlay with Unsafe.As, rather than through ToByteArray or TryWriteBytes. This is allocation-free on both target frameworks and, more importantly, removes a per-target byte index: Guid's default order is mixed-endian, which would put the version nibble at index 7 on netstandard2.0 and 6 in a big-endian span, an off-by-one the net10.0-only suite could not catch. - Mirror the identical GuidFields overlay already shipping in CanonicalTextFormatter, including its narrow CS0649 suppression, which TreatWarningsAsErrors makes mandatory. The layout assumption is already load-bearing in the core library rather than new to this change. - Treat Guid.Version and Guid.Variant as the test oracle, not the implementation. netstandard2.0 has neither, so using them would reintroduce the per-target split the overlay exists to avoid. - Verify with an exhaustive 16x16 version/variant nibble matrix against that oracle, asserting the accepted count of 4 of 256. This pins both offsets and both masks, and replaces hand-picked boundary values and a random sample. - Give the invariant one name on two receivers: public GuidExtensions.IsUuidV7(Guid) alongside Checks.IsUuidV7(Check<Guid>), keeping Checks the home of Check<T> extensions. - Move release notes in both Validation and Validation.OpenApi: the built-in contract registry's key set is public behavior even though that package's source barely changes. - Defer timestamp plausibility, Check<Guid?> overloads, and a generalized IsUuidVersion(int). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9QDDRWbDXTrE12S6ErBt4
Tighten the IsUuidV7 plan from 231 to 192 lines. All nine acceptance criteria and every normative instruction are preserved; the reduction is redundant prose, chiefly in the Predicate section, where the rejection of each alternative, the layout justification, and the endianness argument each restated points the others had already made. Also correct a stale count: the registration points list says six places rather than five, which is what it has enumerated since the shared BuiltInValidationErrorDefinitions.UuidV7 property was split out from the definition class. Restore one fact the condensation had dropped: Guid.Version arrived in .NET 9, which is why the oracle is available to the net10.0-only test project but not to the netstandard2.0 implementation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9QDDRWbDXTrE12S6ErBt4
Signed-off-by: Kenny Pflug <kenny.pflug@live.de>
Add IsUuidV7 to Check<Guid> in both the built-in-message and ErrorOverrides overloads, backed by the new UuidV7 error code, a customizable ValidationErrorTemplates.UuidV7 template, and a metadata-free OpenAPI contract registered for the code. Expose the invariant standalone as public GuidExtensions.IsUuidV7 so the bit manipulation lives in one place and callers can guard the same rule outside a check chain. The predicate reinterprets the Guid over a field overlay mirroring CanonicalTextFormatter's, which serves both target frameworks without conditional compilation and allocates nothing on the passing path (measured: 0 bytes over 1,000,000 calls). Check both RFC 9562 fields, not just the version: a version-7 value carrying a non-RFC variant cannot be produced by Guid.CreateVersion7 and must fail. An exhaustive 16x16 version-nibble by variant-nibble matrix pins both offsets and both masks against an oracle built from Guid.Version and Guid.Variant, and asserts that exactly the four version-7 by variant 8-b combinations are accepted. Closes #72 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9QDDRWbDXTrE12S6ErBt4
Add UuidV7 to the two registry-style suites that enumerate every built-in error definition: the stable-provider test, which contributes the BeSameAs assertion on ErrorTemplates.UuidV7 that UuidV7ValidationTests never made directly, and the ProvideMessage family. Those lists are what the next person adding a definition reads as the checklist, so leaving UuidV7 out of them was a consistency gap even though coverage was already complete. Rename the stable-provider test to name the Guid family. It is partitioned against ComparableDefinitions_ShouldExposeStableProviders, so the enumeration in its name has to stay honest. Record why the RFC-derived accepted set is not redundant with the version-by-variant matrix. Guid.Version and Guid.Variant compute the same two expressions the predicate evaluates, so the matrix pins the field overlay's offsets but cannot pin the masks; only the hardcoded accepted set does that. Both tests walk the same 256 inputs, which invites deleting one of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B9QDDRWbDXTrE12S6ErBt4
9 tasks
Minimum allowed line rate is |
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.
Closes #72