diff --git a/go.mod b/go.mod
index c0a1eea9dc0966af54aea544b4d3c9027c37259b..ae3bc1f21114c63e2d805a1fc32bc817d0718d75 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ toolchain go1.22.1
 
 require (
 	git.autistici.org/ai3/go-common v0.0.0-20241017171051-880a2c5ae7f4
-	github.com/google/go-cmp v0.6.0
+	github.com/google/go-cmp v0.7.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 
diff --git a/go.sum b/go.sum
index dabe79224711a7cba99b17d0f7e23760f8d2dc32..06a572fd1d30a40c018ef4aced986e8ca63324f3 100644
--- a/go.sum
+++ b/go.sum
@@ -75,6 +75,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
index d127d436230d0c3a4f1ded858461bdb778bd1407..def01a6be30e32f4aece60e146f1c1be625351b8 100644
--- a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
+++ b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
@@ -19,6 +19,7 @@ const (
 
 	tbFunc  // func(T) bool
 	ttbFunc // func(T, T) bool
+	ttiFunc // func(T, T) int
 	trbFunc // func(T, R) bool
 	tibFunc // func(T, I) bool
 	trFunc  // func(T) R
@@ -28,11 +29,13 @@ const (
 	Transformer       = trFunc  // func(T) R
 	ValueFilter       = ttbFunc // func(T, T) bool
 	Less              = ttbFunc // func(T, T) bool
+	Compare           = ttiFunc // func(T, T) int
 	ValuePredicate    = tbFunc  // func(T) bool
 	KeyValuePredicate = trbFunc // func(T, R) bool
 )
 
 var boolType = reflect.TypeOf(true)
+var intType = reflect.TypeOf(0)
 
 // IsType reports whether the reflect.Type is of the specified function type.
 func IsType(t reflect.Type, ft funcType) bool {
@@ -49,6 +52,10 @@ func IsType(t reflect.Type, ft funcType) bool {
 		if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType {
 			return true
 		}
+	case ttiFunc: // func(T, T) int
+		if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == intType {
+			return true
+		}
 	case trbFunc: // func(T, R) bool
 		if ni == 2 && no == 1 && t.Out(0) == boolType {
 			return true
diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go
index 754496f3b3f845ccc2326ac98ce6999e79a27b83..ba3fce81ff13b1d1dc6ddc6b8fd547700276d727 100644
--- a/vendor/github.com/google/go-cmp/cmp/options.go
+++ b/vendor/github.com/google/go-cmp/cmp/options.go
@@ -232,7 +232,15 @@ func (validator) apply(s *state, vx, vy reflect.Value) {
 		if t := s.curPath.Index(-2).Type(); t.Name() != "" {
 			// Named type with unexported fields.
 			name = fmt.Sprintf("%q.%v", t.PkgPath(), t.Name()) // e.g., "path/to/package".MyType
-			if _, ok := reflect.New(t).Interface().(error); ok {
+			isProtoMessage := func(t reflect.Type) bool {
+				m, ok := reflect.PointerTo(t).MethodByName("ProtoReflect")
+				return ok && m.Type.NumIn() == 1 && m.Type.NumOut() == 1 &&
+					m.Type.Out(0).PkgPath() == "google.golang.org/protobuf/reflect/protoreflect" &&
+					m.Type.Out(0).Name() == "Message"
+			}
+			if isProtoMessage(t) {
+				help = `consider using "google.golang.org/protobuf/testing/protocmp".Transform to compare proto.Message types`
+			} else if _, ok := reflect.New(t).Interface().(error); ok {
 				help = "consider using cmpopts.EquateErrors to compare error values"
 			} else if t.Comparable() {
 				help = "consider using cmpopts.EquateComparable to compare comparable Go types"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 619bc1446eedf0a22093f1749919cb8397b00ce7..bcdd51f79afa48cd7ce3eecd7907a8c30c01a5a7 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -30,8 +30,8 @@ github.com/go-logr/logr/funcr
 # github.com/go-logr/stdr v1.2.2
 ## explicit; go 1.16
 github.com/go-logr/stdr
-# github.com/google/go-cmp v0.6.0
-## explicit; go 1.13
+# github.com/google/go-cmp v0.7.0
+## explicit; go 1.21
 github.com/google/go-cmp/cmp
 github.com/google/go-cmp/cmp/internal/diff
 github.com/google/go-cmp/cmp/internal/flags