From 1ec69f39e3e0a9a65866af529754fafee2090185 Mon Sep 17 00:00:00 2001 From: Sebastian Spaink Date: Tue, 11 Aug 2026 18:18:41 -0500 Subject: [PATCH 1/2] fix(test): drop stale uuid entries from known-missing list uuid.parse and uuid.rfc4122 are registered in BuiltinRegistry as of #155, so no compliance case reports them missing anymore. The ratchet fails on entries that are no longer missing, which leaves ComplianceTest red on main: These builtins are listed in compliance/known-missing-builtins.txt but no compliance case reported them missing [...] [uuid.parse, uuid.rfc4122] The four upstream uuid fixtures (9 cases) pass once the lines are gone. Signed-off-by: Sebastian Spaink --- .../src/test/resources/compliance/known-missing-builtins.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/opa-evaluator/src/test/resources/compliance/known-missing-builtins.txt b/opa-evaluator/src/test/resources/compliance/known-missing-builtins.txt index 7979170..7362d8c 100644 --- a/opa-evaluator/src/test/resources/compliance/known-missing-builtins.txt +++ b/opa-evaluator/src/test/resources/compliance/known-missing-builtins.txt @@ -67,8 +67,5 @@ urlquery.decode_object urlquery.encode urlquery.encode_object -uuid.parse -uuid.rfc4122 - # Delete this line along with the walk implementation in #141. walk From 52b957bd6d9187b149569edb2daccdcbeee01112 Mon Sep 17 00:00:00 2001 From: Sebastian Spaink Date: Tue, 11 Aug 2026 18:18:50 -0500 Subject: [PATCH 2/2] fix(uuid): match google/uuid input format leniency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uuid.parse rejected two input forms that OPA accepts, both verified with opa eval against OPA 1.19.0 (the version pinned by the compliance test generator): uuid.parse("URN:UUID:000003e8-48b9-21ee-b200-325096b39f47") # defined uuid.parse("(000003e8-48b9-21ee-b200-325096b39f47)") # defined google/uuid compares the urn prefix with strings.EqualFold, so any casing parses; normalize() used a case-sensitive startsWith. For the 38-byte "Microsoft style" form, google/uuid only strips the first byte and then examines the middle 36 — indexes 0 and 37 are never checked, as its doc comment notes ("Only the middle 36 bytes are examined in the latter case"). normalize() required literal braces, making (uuid), Xuuid Y and {uuidX undefined here but defined upstream. The upstream uuid fixtures do not cover either case, so both get unit tests until the cases can be contributed to OPA and picked up by regenerate.sh. Signed-off-by: Sebastian Spaink --- .../opa/ast/builtin/impls/UUIDBuiltins.java | 11 +++--- .../ast/builtin/impls/UUIDBuiltinsTest.java | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/opa-evaluator/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltins.java b/opa-evaluator/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltins.java index 7e44e4d..44c9ab4 100644 --- a/opa-evaluator/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltins.java +++ b/opa-evaluator/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltins.java @@ -23,6 +23,7 @@ public class UUIDBuiltins { private static final long UUID_EPOCH_OFFSET_100NS = 122192928000000000L; private static final String RFC4122 = "uuid.rfc4122"; + private static final String URN_PREFIX = "urn:uuid:"; private static final SecureRandom RANDOM = new SecureRandom(); private static final Pattern CANONICAL_UUID_PATTERN = Pattern.compile( @@ -137,16 +138,16 @@ private String normalize(String input) { value = input; break; case 38: - if (!input.startsWith("{") || !input.endsWith("}")) { - return null; - } + // google/uuid only examines the middle 36 bytes of the "Microsoft style" + // form, so the surrounding bytes are not required to be braces. value = input.substring(1, input.length() - 1); break; case 45: - if (!input.startsWith("urn:uuid:")) { + // google/uuid compares the prefix with strings.EqualFold. + if (!input.regionMatches(true, 0, URN_PREFIX, 0, URN_PREFIX.length())) { return null; } - value = input.substring("urn:uuid:".length()); + value = input.substring(URN_PREFIX.length()); break; default: return null; diff --git a/opa-evaluator/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltinsTest.java b/opa-evaluator/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltinsTest.java index 9106e97..e45acb5 100644 --- a/opa-evaluator/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltinsTest.java +++ b/opa-evaluator/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/UUIDBuiltinsTest.java @@ -84,6 +84,44 @@ void parseReturnsUndefinedForInvalidUuid() { assertNull(builtins.parse(null, new RegoValue[] {new RegoString("123")})); } + /** + * google/uuid compares the urn prefix with {@code strings.EqualFold}, so any casing parses. Not + * covered by the upstream uuid fixtures; verified with {@code opa eval} against OPA 1.19.0. + */ + @Test + void parsesUrnPrefixCaseInsensitively() { + for (String prefix : new String[] {"urn:uuid:", "URN:UUID:", "Urn:Uuid:"}) { + RegoObject result = + (RegoObject) + builtins.parse( + null, + new RegoValue[] {new RegoString(prefix + "000003e8-48b9-21ee-b200-325096b39f47")}); + + assertEquals(RegoInt32.of(2), result.getProperty("version"), prefix); + assertEquals(new RegoString("RFC4122"), result.getProperty("variant"), prefix); + assertEquals(new RegoBigInt(1000L), result.getProperty("id"), prefix); + } + } + + /** + * google/uuid only examines the middle 36 bytes of the 38-byte "Microsoft style" form, so the + * surrounding bytes are not required to be braces — {@code opa eval} accepts all of these. + */ + @Test + void parsesThirtyEightByteFormWithoutRequiringBraces() { + for (String input : + new String[] { + "{000003e8-48b9-21ee-b200-325096b39f47}", + "(000003e8-48b9-21ee-b200-325096b39f47)", + "X000003e8-48b9-21ee-b200-325096b39f47Y", + "{000003e8-48b9-21ee-b200-325096b39f47X" + }) { + RegoObject result = (RegoObject) builtins.parse(null, new RegoValue[] {new RegoString(input)}); + + assertEquals(RegoInt32.of(2), result.getProperty("version"), input); + } + } + @Test void parseRejectsLenientJavaUuidFieldWidths() { assertNull(builtins.parse(null, new RegoValue[] {new RegoString("1-1-1-1-1")}));