Skip to content

Conversation

@app-token-modules
Copy link
Contributor

New managed modules references found. Please review.

@app-token-modules app-token-modules bot requested a review from a team December 9, 2025 12:06
@srikrsna-buf srikrsna-buf merged commit 0deb1fe into main Dec 9, 2025
4 checks passed
@srikrsna-buf srikrsna-buf deleted the fetch-modules branch December 9, 2025 17:42
},
{
"name": "v1.1.0",
"digest": "afa300ba05b84e201fe0bc66b0927254e8097afe00fdc4ef7587fcb112c3f76dcd7550c58e6f8d513b1231e2a67adfd31abb2fbcb13f8e99e42e78b541b6dd20"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cd modules/sync/bufbuild/protovalidate-testing
casdiff v1.0.0 v1.1.0 --format=markdown

7 files changed: 0 removed, 0 renamed, 3 added, 4 changed content

Files added:

+ shake256:2c390a46d42ec618a2c4abb9b29dfc3a4bad724292e74c671ade4b2d9962de16191e9a1ff3d0aeff6747e81b97b2870b5da311de3b0c818ef9c5a328309371b3  buf/validate/conformance/cases/groups_editions.proto
+ shake256:5c4aaa970ffa7c05fc8e4db1ff1faea198f8983a2c625011a8674c0f4520ced20d8eecedc4bf506ac349923964ac48f908aec65d3b0884d79f35c0454567a080  buf/validate/conformance/cases/groups_proto2.proto
+ shake256:5e40f1ec2dddc38d9d5f4bed541b668b840a0f93057e5207dae8223757b6852eb3a271129769e0ca2a1510d06ae61a3a0eef658693ef95775632c29b497d292d  buf/validate/conformance/cases/wkt_field_mask.proto

Files changed content:

buf/validate/conformance/cases/bytes.proto:

--- shake256:f94b2e10a25abb9e75fd29146550473c75a140c7f7c06d3019fe05fef75c1083b7eda27e43aa3b7ad34a63d173206f6ea1e8ff7820ea01179f2a6c3d73b06cc4  buf/validate/conformance/cases/bytes.proto
+++ shake256:8645472d0dae5237628233dbbbb5bba0c4aee6614b3dcfa98d29b425503c33575792237467fd642c32ba610e06575dc8f071293f28b9cf05121bc3d42b57d1da  buf/validate/conformance/cases/bytes.proto
@@ -97,6 +97,18 @@
     (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
   ];
 }
+message BytesUUID {
+  bytes val = 1 [(buf.validate.field).bytes.uuid = true];
+}
+message BytesNotUUID {
+  bytes val = 1 [(buf.validate.field).bytes.uuid = false];
+}
+message BytesUUIDIgnore {
+  bytes val = 1 [
+    (buf.validate.field).bytes.uuid = true,
+    (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
+  ];
+}
 message BytesExample {
   bytes val = 1 [(buf.validate.field).bytes.example = "\x99"];
 }

buf/validate/conformance/cases/custom_rules/custom_rules.proto:

--- shake256:eeb26627ec36877b1f1224459ee746541dc5241c47072d613bb68242b3fb70a1b74a197f933bbe2784b56b2703aecc85afc78165a77b662d6277d82f7dcc2388  buf/validate/conformance/cases/custom_rules/custom_rules.proto
+++ shake256:edebcab26a765c57805e042842e02056dae97435a3a25c92e29478b24fca15583c8aafaa75c851e55bf835e33a4ddfe85c17d208d6ddd9ea8634f1e00e9c9196  buf/validate/conformance/cases/custom_rules/custom_rules.proto
@@ -68,6 +68,12 @@
     int32 a = 1;
     int32 b = 2;
   }
+}
+
+message MessageExpressionOnly {
+  option (message).cel_expression = "this.a > 0";
+
+  int32 a = 1;
 }

 message MissingField {
@@ -108,6 +114,10 @@
   };
 }

+message FieldExpressionOnly {
+  int32 val = 1 [(field).cel_expression = "this > 42"];
+}
+
 message FieldExpressionMultipleScalar {
   int32 val = 1 [
     (field).cel = {

buf/validate/conformance/cases/required_field_proto3.proto:

--- shake256:a6619bed3fffd2786aeb27e8d0ae8a6c8d84e623d4e5a476d0d850a15d25a43b169ea2a3ca98e301720618fe09abcc749314eef0f465b8ab18c4e0eda0548a82  buf/validate/conformance/cases/required_field_proto3.proto
+++ shake256:18053b4961756923d217324b892f0cfb9ac41e35dba6b689cb2adcbdf58f2d4d59957ccb77941c8a5f23a9d31f1a24912902b47bd565c55b5d85d1190fa6b771  buf/validate/conformance/cases/required_field_proto3.proto
@@ -101,3 +101,25 @@
 message RequiredProto3RepeatedItem {
   repeated string val = 1 [(buf.validate.field).repeated.items.required = true];
 }
+
+message RequiredImplicitProto3Scalar {
+  string val = 1 [
+    (buf.validate.field).required = true,
+    (buf.validate.field).string.min_len = 1,
+    (buf.validate.field).string.max_len = 2
+  ];
+}
+message RequiredImplicitProto3Repeated {
+  repeated string val = 1 [
+    (buf.validate.field).required = true,
+    (buf.validate.field).repeated.min_items = 1,
+    (buf.validate.field).repeated.max_items = 2
+  ];
+}
+message RequiredImplicitProto3Map {
+  map<string, string> val = 1 [
+    (buf.validate.field).required = true,
+    (buf.validate.field).map.min_pairs = 1,
+    (buf.validate.field).map.max_pairs = 2
+  ];
+}

buf/validate/conformance/cases/strings.proto:

--- shake256:f0fabd56e4c9c8647560fe54b22320b81ed332e559f426752b54188a139ca62a3090df77f7c44d7205e185409a6f1bf9e20992c8a08bcdc573045e1a117481eb  buf/validate/conformance/cases/strings.proto
+++ shake256:f7585fc360f16b8b4be9c19b76386da260ba2458a9242e2d69c22082833cd5de7fd2255ed46d1649ae0fcd0362f22c3f9acb162d811206d9a5de83314b338cae  buf/validate/conformance/cases/strings.proto
@@ -196,6 +196,18 @@
 message StringNotTUUID {
   string val = 1 [(buf.validate.field).string.tuuid = false];
 }
+message StringULID {
+  string val = 1 [(buf.validate.field).string.ulid = true];
+}
+message StringNotULID {
+  string val = 1 [(buf.validate.field).string.ulid = false];
+}
+message StringULIDIgnore {
+  string val = 1 [
+    (buf.validate.field).string = {ulid: true},
+    (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
+  ];
+}
 message StringHttpHeaderName {
   string val = 1 [(buf.validate.field).string.well_known_regex = KNOWN_REGEX_HTTP_HEADER_NAME];
 }

},
{
"name": "v1.1.0",
"digest": "35b3d88f6b0fbf159d9eedfc2fbfa976490e6bca1d98914c1c71f29bfe2da6261fca56c057975b3e5c022b3234a0f2eea8e2d1b599a937c6c5d63d21201a9bc3"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cd modules/sync/bufbuild/protovalidate
casdiff v1.0.0 v1.1.0 --format=markdown

2 files changed: 0 removed, 0 renamed, 0 added, 2 changed content

Files changed content:

README.md:

--- shake256:413ef70a5630038ee90dc20755dd02da018ac52533f977a9d9e5061b94e0fa5e4e164430d4b9166e0570c24a6eb863c2f7e8b850286f2314cbf909da9a6865cb  README.md
+++ shake256:26622ee52e0fe9e7daa0bd4cdc14bef2dc25f8bfacc79d077db09aebb218bb34d9911e4f525ef8571efba1db405d1d2855b2213e8aa42c6db1724ac9179d15e0  README.md
@@ -88,4 +88,4 @@
 [grpc-go]: https://protovalidate.com/quickstart/grpc-go/
 [grpc-java]: https://protovalidate.com/quickstart/grpc-java/
 [grpc-python]: https://protovalidate.com/quickstart/grpc-python/
-[migration-guide]: https://buf.build/docs/migration-guides/migrate-from-protoc-gen-validate/
+[migration-guide]: https://protovalidate.com/migration-guides/migrate-from-protoc-gen-validate/

buf/validate/validate.proto:

--- shake256:6a5df233100ed85ab753479e45487b60e7a4b2f14ddde95dce98c72151a577b0b83576e26cbfebdb02ad2400725f4fc9b8d091704fe1e8b2f4890c7d13de9681  buf/validate/validate.proto
+++ shake256:64f9cf945094e1bec0406887f3d6b7704e051c750c3b2ef45d678232d25dc451f9f0304dd9161b853a5ec5b61c9df583f92180db3319d082ae5d0ff46c70c202  buf/validate/validate.proto
@@ -18,6 +18,7 @@

 import "google/protobuf/descriptor.proto";
 import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
 import "google/protobuf/timestamp.proto";

 option go_package = "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate";
@@ -109,6 +110,25 @@
 // MessageRules represents validation rules that are applied to the entire message.
 // It includes disabling options and a list of Rule messages representing Common Expression Language (CEL) validation rules.
 message MessageRules {
+  // `cel_expression` is a repeated field CEL expressions. Each expression specifies a validation
+  // rule to be applied to this message. These rules are written in Common Expression Language (CEL) syntax.
+  //
+  // This is a simplified form of the `cel` Rule field, where only `expression` is set. This allows for
+  // simpler syntax when defining CEL Rules where `id` and `message` derived from the `expression`. `id` will
+  // be same as the `expression`.
+  //
+  // For more information, [see our documentation](https://buf.build/docs/protovalidate/schemas/custom-rules/).
+  //
+  // ```proto
+  // message MyMessage {
+  //   // The field `foo` must be greater than 42.
+  //   option (buf.validate.message).cel_expression = "this.foo > 42";
+  //   // The field `foo` must be less than 84.
+  //   option (buf.validate.message).cel_expression = "this.foo < 84";
+  //   optional int32 foo = 1;
+  // }
+  // ```
+  repeated string cel_expression = 5;
   // `cel` is a repeated field of type Rule. Each Rule specifies a validation rule to be applied to this message.
   // These rules are written in Common Expression Language (CEL) syntax. For more information,
   // [see our documentation](https://buf.build/docs/protovalidate/schemas/custom-rules/).
@@ -201,6 +221,22 @@
 // FieldRules encapsulates the rules for each type of field. Depending on
 // the field, the correct set should be used to ensure proper validations.
 message FieldRules {
+  // `cel_expression` is a repeated field CEL expressions. Each expression specifies a validation
+  // rule to be applied to this message. These rules are written in Common Expression Language (CEL) syntax.
+  //
+  // This is a simplified form of the `cel` Rule field, where only `expression` is set. This allows for
+  // simpler syntax when defining CEL Rules where `id` and `message` derived from the `expression`. `id` will
+  // be same as the `expression`.
+  //
+  // For more information, [see our documentation](https://buf.build/docs/protovalidate/schemas/custom-rules/).
+  //
+  // ```proto
+  // message MyMessage {
+  //   // The field `value` must be greater than 42.
+  //   optional int32 value = 1 [(buf.validate.field).cel_expression = "this > 42"];
+  // }
+  // ```
+  repeated string cel_expression = 29;
   // `cel` is a repeated field used to represent a textual expression
   // in the Common Expression Language (CEL) syntax. For more information,
   // [see our documentation](https://buf.build/docs/protovalidate/schemas/custom-rules/).
@@ -313,6 +349,7 @@
     // Well-Known Field Types
     AnyRules any = 20;
     DurationRules duration = 21;
+    FieldMaskRules field_mask = 28;
     TimestampRules timestamp = 22;
   }

@@ -3728,6 +3765,29 @@
         id: "string.host_and_port_empty"
         message: "value is empty, which is not a valid host and port pair"
         expression: "!rules.host_and_port || this != ''"
+      }
+    ];
+
+    // `ulid` specifies that the field value must be a valid ULID (Universally Unique
+    // Lexicographically Sortable Identifier) as defined by the [ULID specification](https://github.com/ulid/spec).
+    // If the field value isn't a valid ULID, an error message will be generated.
+    //
+    // ```proto
+    // message MyString {
+    //   // value must be a valid ULID
+    //   string value = 1 [(buf.validate.field).string.ulid = true];
+    // }
+    // ```
+    bool ulid = 35 [
+      (predefined).cel = {
+        id: "string.ulid"
+        message: "value must be a valid ULID"
+        expression: "!rules.ulid || this == '' || this.matches('^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$')"
+      },
+      (predefined).cel = {
+        id: "string.ulid_empty"
+        message: "value is empty, which is not a valid ULID"
+        expression: "!rules.ulid || this != ''"
       }
     ];

@@ -3943,7 +4003,7 @@
   // the string.
   // If the field value doesn't meet the requirement, an error message is generated.
   //
-  // ```protobuf
+  // ```proto
   // message MyBytes {
   //   // value does not contain \x02\x03
   //   optional bytes value = 1 [(buf.validate.field).bytes.contains = "\x02\x03"];
@@ -3958,7 +4018,7 @@
   // values. If the field value doesn't match any of the specified values, an
   // error message is generated.
   //
-  // ```protobuf
+  // ```proto
   // message MyBytes {
   //   // value must in ["\x01\x02", "\x02\x03", "\x03\x04"]
   //   optional bytes value = 1 [(buf.validate.field).bytes.in = {"\x01\x02", "\x02\x03", "\x03\x04"}];
@@ -4050,6 +4110,31 @@
         id: "bytes.ipv6_empty"
         message: "value is empty, which is not a valid IPv6 address"
         expression: "!rules.ipv6 || this.size() != 0"
+      }
+    ];
+
+    // `uuid` ensures that the field `value` encodes the 128-bit UUID data as
+    // defined by [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.2).
+    // The field must contain exactly 16 bytes
+    // representing the UUID. If the field value isn't a valid UUID, an error
+    // message will be generated.
+    //
+    // ```proto
+    // message MyBytes {
+    //   // value must be a valid UUID
+    //   optional bytes value = 1 [(buf.validate.field).bytes.uuid = true];
+    // }
+    // ```
+    bool uuid = 15 [
+      (predefined).cel = {
+        id: "bytes.uuid"
+        message: "value must be a valid UUID"
+        expression: "!rules.uuid || this.size() == 0 || this.size() == 16"
+      },
+      (predefined).cel = {
+        id: "bytes.uuid_empty"
+        message: "value is empty, which is not a valid UUID"
+        expression: "!rules.uuid || this.size() != 0"
       }
     ];
   }
@@ -4605,6 +4690,93 @@
   extensions 1000 to max;
 }

+// FieldMaskRules describe rules applied exclusively to the `google.protobuf.FieldMask` well-known type.
+message FieldMaskRules {
+  // `const` dictates that the field must match the specified value of the `google.protobuf.FieldMask` type exactly.
+  // If the field's value deviates from the specified value, an error message
+  // will be generated.
+  //
+  // ```proto
+  // message MyFieldMask {
+  //   // value must equal ["a"]
+  //   google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask.const = {
+  //       paths: ["a"]
+  //   }];
+  // }
+  // ```
+  optional google.protobuf.FieldMask const = 1 [(predefined).cel = {
+    id: "field_mask.const"
+    expression: "this.paths != getField(rules, 'const').paths ? 'value must equal paths %s'.format([getField(rules, 'const').paths]) : ''"
+  }];
+
+  // `in` requires the field value to only contain paths matching specified
+  // values or their subpaths.
+  // If any of the field value's paths doesn't match the rule,
+  // an error message is generated.
+  // See: https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask
+  //
+  // ```proto
+  // message MyFieldMask {
+  //   //  The `value` FieldMask must only contain paths listed in `in`.
+  //   google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask = {
+  //       in: ["a", "b", "c.a"]
+  //   }];
+  // }
+  // ```
+  repeated string in = 2 [(predefined).cel = {
+    id: "field_mask.in"
+    expression: "!this.paths.all(p, p in getField(rules, 'in') || getField(rules, 'in').exists(f, p.startsWith(f+'.'))) ? 'value must only contain paths in %s'.format([getField(rules, 'in')]) : ''"
+  }];
+
+  // `not_in` requires the field value to not contain paths matching specified
+  // values or their subpaths.
+  // If any of the field value's paths matches the rule,
+  // an error message is generated.
+  // See: https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask
+  //
+  // ```proto
+  // message MyFieldMask {
+  //   //  The `value` FieldMask shall not contain paths listed in `not_in`.
+  //   google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask = {
+  //       not_in: ["forbidden", "immutable", "c.a"]
+  //   }];
+  // }
+  // ```
+  repeated string not_in = 3 [(predefined).cel = {
+    id: "field_mask.not_in"
+    expression: "!this.paths.all(p, !(p in getField(rules, 'not_in') || getField(rules, 'not_in').exists(f, p.startsWith(f+'.')))) ? 'value must not contain any paths in %s'.format([getField(rules, 'not_in')]) : ''"
+  }];
+
+  // `example` specifies values that the field may have. These values SHOULD
+  // conform to other rules. `example` values will not impact validation
+  // but may be used as helpful guidance on how to populate the given field.
+  //
+  // ```proto
+  // message MyFieldMask {
+  //   google.protobuf.FieldMask value = 1 [
+  //     (buf.validate.field).field_mask.example = { paths: ["a", "b"] },
+  //     (buf.validate.field).field_mask.example = { paths: ["c.a", "d"] },
+  //   ];
+  // }
+  // ```
+  repeated google.protobuf.FieldMask example = 4 [(predefined).cel = {
+    id: "field_mask.example"
+    expression: "true"
+  }];
+
+  // Extension fields in this range that have the (buf.validate.predefined)
+  // option set will be treated as predefined field rules that can then be
+  // set on the field options of other fields to apply field rules.
+  // Extension numbers 1000 to 99999 are reserved for extension numbers that are
+  // defined in the [Protobuf Global Extension Registry][1]. Extension numbers
+  // above this range are reserved for extension numbers that are not explicitly
+  // assigned. For rules defined in publicly-consumed schemas, use of extensions
+  // above 99999 is discouraged due to the risk of conflicts.
+  //
+  // [1]: https://github.com/protocolbuffers/protobuf/blob/main/docs/options.md
+  extensions 1000 to max;
+}
+
 // TimestampRules describe the rules applied exclusively to the `google.protobuf.Timestamp` well-known type.
 message TimestampRules {
   // `const` dictates that this field, of the `google.protobuf.Timestamp` type, must exactly match the specified value. If the field value doesn't correspond to the specified timestamp, an error message will be generated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants