From 4b12d1f7093e8ffd1dde6a17adb1d60ed075630d Mon Sep 17 00:00:00 2001 From: Kartikay Date: Tue, 10 Jun 2025 04:08:02 +0530 Subject: [PATCH 1/6] support relation deprecations Signed-off-by: Kartikay --- internal/services/shared/errors.go | 13 + internal/services/v1/relationships.go | 32 + internal/services/v1/schema_test.go | 72 ++ pkg/diff/namespace/diff.go | 11 + pkg/diff/namespace/diff_test.go | 28 + pkg/namespace/builder.go | 27 + pkg/proto/core/v1/core.pb.go | 1066 +++++++++-------- pkg/proto/core/v1/core.pb.validate.go | 4 + pkg/proto/core/v1/core_vtproto.pb.go | 62 + pkg/schemadsl/compiler/translator.go | 40 +- pkg/schemadsl/dslshape/dslshape.go | 6 + .../dslshape/zz_generated.nodetype_string.go | 27 +- pkg/schemadsl/lexer/lex_def.go | 8 + pkg/schemadsl/lexer/lex_test.go | 13 + pkg/schemadsl/lexer/tokentype_string.go | 37 +- pkg/schemadsl/parser/parser.go | 30 + pkg/schemadsl/parser/parser_test.go | 14 + pkg/schemadsl/parser/tests/deprecation.zed | 10 + .../parser/tests/deprecation.zed.expected | 58 + .../parser/tests/invalid-deprecation.zed | 6 + .../tests/invalid-deprecation.zed.expected | 34 + proto/internal/core/v1/core.proto | 17 + 22 files changed, 1088 insertions(+), 527 deletions(-) create mode 100644 pkg/schemadsl/parser/tests/deprecation.zed create mode 100644 pkg/schemadsl/parser/tests/deprecation.zed.expected create mode 100644 pkg/schemadsl/parser/tests/invalid-deprecation.zed create mode 100644 pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected diff --git a/internal/services/shared/errors.go b/internal/services/shared/errors.go index 05b3907239..26bbfa80c7 100644 --- a/internal/services/shared/errors.go +++ b/internal/services/shared/errors.go @@ -52,6 +52,16 @@ type SchemaWriteDataValidationError struct { error } +type DeprecationError struct { + error +} + +func NewDeprecationError(namespace string, relation string) DeprecationError { + return DeprecationError{ + error: fmt.Errorf("relation %s#%s is deprecated", namespace, relation), + } +} + // MarshalZerologObject implements zerolog object marshalling. func (err SchemaWriteDataValidationError) MarshalZerologObject(e *zerolog.Event) { e.Err(err.error) @@ -201,6 +211,9 @@ func rewriteError(ctx context.Context, err error, config *ConfigForErrors) error } return status.Errorf(codes.Canceled, "%s", err) + case errors.As(err, &DeprecationError{}): + log.Ctx(ctx).Err(err).Msg("using deprecated relation") + return status.Errorf(codes.Aborted, "%s", err) default: log.Ctx(ctx).Err(err).Msg("received unexpected error") return err diff --git a/internal/services/v1/relationships.go b/internal/services/v1/relationships.go index 47b5cea8c3..f6d175cb70 100644 --- a/internal/services/v1/relationships.go +++ b/internal/services/v1/relationships.go @@ -16,6 +16,7 @@ import ( v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/internal/dispatch" + log "github.com/authzed/spicedb/internal/logging" "github.com/authzed/spicedb/internal/middleware" datastoremw "github.com/authzed/spicedb/internal/middleware/datastore" "github.com/authzed/spicedb/internal/middleware/handwrittenvalidation" @@ -34,6 +35,7 @@ import ( "github.com/authzed/spicedb/pkg/genutil" "github.com/authzed/spicedb/pkg/genutil/mapz" "github.com/authzed/spicedb/pkg/middleware/consistency" + corev1 "github.com/authzed/spicedb/pkg/proto/core/v1" dispatchv1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" "github.com/authzed/spicedb/pkg/tuple" "github.com/authzed/spicedb/pkg/zedtoken" @@ -324,6 +326,10 @@ func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.Writ updateRelationshipSet := mapz.NewSet[string]() for _, update := range req.Updates { // TODO(jschorr): Change to struct-based keys. + if err := checkForDeprecatedRelationships(ctx, update, ds); err != nil { + return nil, ps.rewriteError(ctx, err) + } + tupleStr := tuple.V1StringRelationshipWithoutCaveatOrExpiration(update.Relationship) if !updateRelationshipSet.Add(tupleStr) { return nil, ps.rewriteError( @@ -620,3 +626,29 @@ func labelsForFilter(filter *v1.RelationshipFilter) perfinsights.APIShapeLabels perfinsights.SubjectRelationLabel: filter.OptionalSubjectFilter.OptionalRelation.Relation, } } + +func checkForDeprecatedRelationships(ctx context.Context, update *v1.RelationshipUpdate, ds datastore.Datastore) error { + resource := update.Relationship.Resource + headRevision, err := ds.HeadRevision(ctx) + if err != nil { + return err + } + reader := ds.SnapshotReader(headRevision) + _, relDef, err := namespace.ReadNamespaceAndRelation(ctx, resource.ObjectType, update.Relationship.Relation, reader) + if err != nil { + return err + } + + switch relDef.DeprecationType { + case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: + log.Warn(). + Str("namespace", update.Relationship.Resource.ObjectType). + Str("relation", update.Relationship.Relation). + Msg("write to deprecated relation") + + case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: + return shared.NewDeprecationError(update.Relationship.Resource.ObjectType, update.Relationship.Relation) + } + + return nil +} diff --git a/internal/services/v1/schema_test.go b/internal/services/v1/schema_test.go index 3eddbbb940..e713e5abd9 100644 --- a/internal/services/v1/schema_test.go +++ b/internal/services/v1/schema_test.go @@ -1642,3 +1642,75 @@ func TestComputablePermissions(t *testing.T) { }) } } + +func TestSchemaChangeRelationDeprecation(t *testing.T) { + conn, cleanup, _, _ := testserver.NewTestServer(require.New(t), 0, memdb.DisableGC, true, tf.EmptyDatastore) + t.Cleanup(cleanup) + client := v1.NewSchemaServiceClient(conn) + v1client := v1.NewPermissionsServiceClient(conn) + + // Write a basic schema with deprecation type warning. + originalSchema := ` + definition user {} + + definition document { + @deprecated(warn) + relation somerelation: user + }` + _, err := client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ + Schema: originalSchema, + }) + require.NoError(t, err) + + // Write the relationship referencing the relation. + toWrite := tuple.MustParse("document:somedoc#somerelation@user:tom") + _, err = v1client.WriteRelationships(t.Context(), &v1.WriteRelationshipsRequest{ + Updates: []*v1.RelationshipUpdate{tuple.MustUpdateToV1RelationshipUpdate(tuple.Create( + toWrite, + ))}, + }) + require.Nil(t, err) + + deprecatedErrSchema := ` + definition user {} + + definition document { + @deprecated(error) + relation somerelation: user + }` + + // Enforce deprecation over the relation in the new schema. + _, err = client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ + Schema: deprecatedErrSchema, + }) + require.NoError(t, err) + + // Attempt to write to a deprecated relation which should fail. + toWrite = tuple.MustParse("document:somedoc#somerelation@user:jerry") + _, err = v1client.WriteRelationships(t.Context(), &v1.WriteRelationshipsRequest{ + Updates: []*v1.RelationshipUpdate{tuple.MustUpdateToV1RelationshipUpdate(tuple.Create( + toWrite, + ))}, + }) + require.Equal(t, "rpc error: code = Aborted desc = relation document#somerelation is deprecated", err.Error()) + + // Change the schema to remove the deprecation type. + newSchema := ` + definition user {} + + definition document { + relation somerelation: user + }` + _, err = client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ + Schema: newSchema, + }) + require.NoError(t, err) + + // Again attempt to write to the relation, which should now succeed. + _, err = v1client.WriteRelationships(t.Context(), &v1.WriteRelationshipsRequest{ + Updates: []*v1.RelationshipUpdate{tuple.MustUpdateToV1RelationshipUpdate(tuple.Create( + toWrite, + ))}, + }) + require.NoError(t, err) +} diff --git a/pkg/diff/namespace/diff.go b/pkg/diff/namespace/diff.go index af50f0fb51..41b38c5206 100644 --- a/pkg/diff/namespace/diff.go +++ b/pkg/diff/namespace/diff.go @@ -60,6 +60,9 @@ const ( // ChangedRelationComment indicates that the comment of the relation has changed in some way. ChangedRelationComment DeltaType = "changed-relation-comment" + + // ChangedDeprecation indicates that the deprecation status of the relation has changed. + ChangedDeprecation DeltaType = "changed-deprecation" ) // Diff holds the diff between two namespaces. @@ -240,6 +243,14 @@ func DiffNamespaces(existing *core.NamespaceDefinition, updated *core.NamespaceD }) } + // Compare deprecation status + if existingRel.DeprecationType != updatedRel.DeprecationType { + deltas = append(deltas, Delta{ + Type: ChangedDeprecation, + RelationName: shared, + }) + } + // Compare comments. existingComments := nspkg.GetComments(existingRel.Metadata) updatedComments := nspkg.GetComments(updatedRel.Metadata) diff --git a/pkg/diff/namespace/diff_test.go b/pkg/diff/namespace/diff_test.go index 301a7d5c19..429d65780c 100644 --- a/pkg/diff/namespace/diff_test.go +++ b/pkg/diff/namespace/diff_test.go @@ -571,6 +571,34 @@ func TestNamespaceDiff(t *testing.T) { ), []Delta{}, }, + { + "deprecate relation with an error type", + ns.Namespace( + "document", + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED)), + ), + ns.Namespace( + "document", + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_ERROR)), + ), + []Delta{ + {Type: ChangedDeprecation, RelationName: "somerel"}, + }, + }, + { + "remove deprecation", + ns.Namespace( + "document", + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_ERROR)), + ), + ns.Namespace( + "document", + ns.MustRelation("somerel", nil, ns.AllowedRelation("foo", "bar")), + ), + []Delta{ + {Type: ChangedDeprecation, RelationName: "somerel"}, + }, + }, } for _, tc := range testCases { diff --git a/pkg/namespace/builder.go b/pkg/namespace/builder.go index cf4c745b4f..2d551c40aa 100644 --- a/pkg/namespace/builder.go +++ b/pkg/namespace/builder.go @@ -46,6 +46,10 @@ func Relation(name string, rewrite *core.UsersetRewrite, allowedDirectRelations TypeInformation: typeInfo, } + if err := setRelationDeprecationType(rel, allowedDirectRelations...); err != nil { + return nil, spiceerrors.MustBugf("failed to set deprecation type: %s", err.Error()) + } + switch { case rewrite != nil && len(allowedDirectRelations) == 0: if err := SetRelationKind(rel, iv1.RelationMetadata_PERMISSION); err != nil { @@ -94,6 +98,17 @@ func AllowedRelationWithCaveat(namespaceName string, relationName string, withCa } } +// AllowedDeprecatedRelation creates a relation reference to an allowed relation that is deprecated. +func AllowedDeprecatedRelation(namespaceName string, relationName string, deprecationType core.DeprecationType) *core.AllowedRelation { + return &core.AllowedRelation{ + Namespace: namespaceName, + RelationOrWildcard: &core.AllowedRelation_Relation{ + Relation: relationName, + }, + DeprecationType: deprecationType, + } +} + // WithExpiration adds the expiration trait to the allowed relation. func WithExpiration(allowedRelation *core.AllowedRelation) *core.AllowedRelation { return &core.AllowedRelation{ @@ -243,6 +258,18 @@ func setOperation(firstChild *core.SetOperation_Child, rest []*core.SetOperation } } +// setRelationDeprecationType sets the deprecation type of a relation based on all of the deprecations of allowed direct relations. +func setRelationDeprecationType(relation *core.Relation, allowedDirectRelations ...*core.AllowedRelation) error { + if len(allowedDirectRelations) > 0 { + for _, allowedRelation := range allowedDirectRelations { + if allowedRelation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + relation.DeprecationType = allowedRelation.DeprecationType + } + } + } + return nil +} + // Nil creates a child for a set operation that references the empty set. func Nil() *core.SetOperation_Child { return &core.SetOperation_Child{ diff --git a/pkg/proto/core/v1/core.pb.go b/pkg/proto/core/v1/core.pb.go index 56ce0f7b95..f1aaf57a27 100644 --- a/pkg/proto/core/v1/core.pb.go +++ b/pkg/proto/core/v1/core.pb.go @@ -24,6 +24,57 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// * +// DeprecationType is the type of deprecation for a relation. +type DeprecationType int32 + +const ( + DeprecationType_DEPRECATED_TYPE_UNSPECIFIED DeprecationType = 0 + DeprecationType_DEPRECATED_TYPE_WARNING DeprecationType = 1 + DeprecationType_DEPRECATED_TYPE_ERROR DeprecationType = 2 +) + +// Enum value maps for DeprecationType. +var ( + DeprecationType_name = map[int32]string{ + 0: "DEPRECATED_TYPE_UNSPECIFIED", + 1: "DEPRECATED_TYPE_WARNING", + 2: "DEPRECATED_TYPE_ERROR", + } + DeprecationType_value = map[string]int32{ + "DEPRECATED_TYPE_UNSPECIFIED": 0, + "DEPRECATED_TYPE_WARNING": 1, + "DEPRECATED_TYPE_ERROR": 2, + } +) + +func (x DeprecationType) Enum() *DeprecationType { + p := new(DeprecationType) + *p = x + return p +} + +func (x DeprecationType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DeprecationType) Descriptor() protoreflect.EnumDescriptor { + return file_core_v1_core_proto_enumTypes[0].Descriptor() +} + +func (DeprecationType) Type() protoreflect.EnumType { + return &file_core_v1_core_proto_enumTypes[0] +} + +func (x DeprecationType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DeprecationType.Descriptor instead. +func (DeprecationType) EnumDescriptor() ([]byte, []int) { + return file_core_v1_core_proto_rawDescGZIP(), []int{0} +} + type RelationTupleUpdate_Operation int32 const ( @@ -60,11 +111,11 @@ func (x RelationTupleUpdate_Operation) String() string { } func (RelationTupleUpdate_Operation) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[0].Descriptor() + return file_core_v1_core_proto_enumTypes[1].Descriptor() } func (RelationTupleUpdate_Operation) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[0] + return &file_core_v1_core_proto_enumTypes[1] } func (x RelationTupleUpdate_Operation) Number() protoreflect.EnumNumber { @@ -112,11 +163,11 @@ func (x SetOperationUserset_Operation) String() string { } func (SetOperationUserset_Operation) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[1].Descriptor() + return file_core_v1_core_proto_enumTypes[2].Descriptor() } func (SetOperationUserset_Operation) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[1] + return &file_core_v1_core_proto_enumTypes[2] } func (x SetOperationUserset_Operation) Number() protoreflect.EnumNumber { @@ -170,11 +221,11 @@ func (x ReachabilityEntrypoint_ReachabilityEntrypointKind) String() string { } func (ReachabilityEntrypoint_ReachabilityEntrypointKind) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[2].Descriptor() + return file_core_v1_core_proto_enumTypes[3].Descriptor() } func (ReachabilityEntrypoint_ReachabilityEntrypointKind) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[2] + return &file_core_v1_core_proto_enumTypes[3] } func (x ReachabilityEntrypoint_ReachabilityEntrypointKind) Number() protoreflect.EnumNumber { @@ -223,11 +274,11 @@ func (x ReachabilityEntrypoint_EntrypointResultStatus) String() string { } func (ReachabilityEntrypoint_EntrypointResultStatus) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[3].Descriptor() + return file_core_v1_core_proto_enumTypes[4].Descriptor() } func (ReachabilityEntrypoint_EntrypointResultStatus) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[3] + return &file_core_v1_core_proto_enumTypes[4] } func (x ReachabilityEntrypoint_EntrypointResultStatus) Number() protoreflect.EnumNumber { @@ -272,11 +323,11 @@ func (x FunctionedTupleToUserset_Function) String() string { } func (FunctionedTupleToUserset_Function) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[4].Descriptor() + return file_core_v1_core_proto_enumTypes[5].Descriptor() } func (FunctionedTupleToUserset_Function) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[4] + return &file_core_v1_core_proto_enumTypes[5] } func (x FunctionedTupleToUserset_Function) Number() protoreflect.EnumNumber { @@ -318,11 +369,11 @@ func (x ComputedUserset_Object) String() string { } func (ComputedUserset_Object) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[5].Descriptor() + return file_core_v1_core_proto_enumTypes[6].Descriptor() } func (ComputedUserset_Object) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[5] + return &file_core_v1_core_proto_enumTypes[6] } func (x ComputedUserset_Object) Number() protoreflect.EnumNumber { @@ -370,11 +421,11 @@ func (x CaveatOperation_Operation) String() string { } func (CaveatOperation_Operation) Descriptor() protoreflect.EnumDescriptor { - return file_core_v1_core_proto_enumTypes[6].Descriptor() + return file_core_v1_core_proto_enumTypes[7].Descriptor() } func (CaveatOperation_Operation) Type() protoreflect.EnumType { - return &file_core_v1_core_proto_enumTypes[6] + return &file_core_v1_core_proto_enumTypes[7] } func (x CaveatOperation_Operation) Number() protoreflect.EnumNumber { @@ -1362,6 +1413,8 @@ type Relation struct { SourcePosition *SourcePosition `protobuf:"bytes,5,opt,name=source_position,json=sourcePosition,proto3" json:"source_position,omitempty"` AliasingRelation string `protobuf:"bytes,6,opt,name=aliasing_relation,json=aliasingRelation,proto3" json:"aliasing_relation,omitempty"` CanonicalCacheKey string `protobuf:"bytes,7,opt,name=canonical_cache_key,json=canonicalCacheKey,proto3" json:"canonical_cache_key,omitempty"` + // * deprecation_type is the type of deprecation for the relation + DeprecationType DeprecationType `protobuf:"varint,8,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` } func (x *Relation) Reset() { @@ -1445,6 +1498,13 @@ func (x *Relation) GetCanonicalCacheKey() string { return "" } +func (x *Relation) GetDeprecationType() DeprecationType { + if x != nil { + return x.DeprecationType + } + return DeprecationType_DEPRECATED_TYPE_UNSPECIFIED +} + // * // ReachabilityGraph is a serialized form of a reachability graph, representing how a relation can // be reached from one or more subject types. @@ -1784,6 +1844,9 @@ type AllowedRelation struct { // * // required_expiration defines the required expiration on this relation. RequiredExpiration *ExpirationTrait `protobuf:"bytes,7,opt,name=required_expiration,json=requiredExpiration,proto3" json:"required_expiration,omitempty"` + // * + // deprecation_type defines the type of deprecation for this relation. + DeprecationType DeprecationType `protobuf:"varint,8,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` } func (x *AllowedRelation) Reset() { @@ -1867,6 +1930,13 @@ func (x *AllowedRelation) GetRequiredExpiration() *ExpirationTrait { return nil } +func (x *AllowedRelation) GetDeprecationType() DeprecationType { + if x != nil { + return x.DeprecationType + } + return DeprecationType_DEPRECATED_TYPE_UNSPECIFIED +} + type isAllowedRelation_RelationOrWildcard interface { isAllowedRelation_RelationOrWildcard() } @@ -3293,7 +3363,7 @@ var file_core_v1_core_proto_rawDesc = []byte{ 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x03, 0x0a, 0x08, 0x52, + 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe1, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, @@ -3319,358 +3389,373 @@ var file_core_v1_core_proto_rawDesc = []byte{ 0x67, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, - 0x6c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4b, 0x65, 0x79, 0x22, 0xf4, 0x03, 0x0a, 0x11, 0x52, 0x65, - 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, - 0x77, 0x0a, 0x1b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x62, - 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, - 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x1f, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, - 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x1c, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, - 0x0a, 0x1d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x71, 0x0a, - 0x21, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xc6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0b, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, - 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, - 0x21, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xce, 0x04, 0x0a, 0x16, 0x52, 0x65, - 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x4e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, - 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x7a, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x17, 0x0a, - 0x13, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, - 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, - 0x45, 0x44, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, - 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x54, 0x55, 0x50, 0x4c, 0x45, - 0x53, 0x45, 0x54, 0x5f, 0x54, 0x4f, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x45, - 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x22, 0x57, 0x0a, 0x16, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x41, 0x43, 0x48, 0x41, 0x42, - 0x4c, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x52, - 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x52, 0x45, 0x43, - 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x55, - 0x4c, 0x54, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x65, 0x0a, 0x0f, 0x54, 0x79, - 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, - 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x22, 0x95, 0x04, 0x0a, 0x0f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, - 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, - 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, - 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, - 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, - 0x5d, 0x24, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x4e, 0x0a, - 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x30, 0xfa, 0x42, 0x2d, 0x72, 0x2b, 0x28, 0x40, 0x32, 0x27, 0x5e, 0x28, 0x5c, 0x2e, 0x5c, 0x2e, - 0x5c, 0x2e, 0x7c, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, - 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, - 0x24, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, - 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x48, - 0x00, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, - 0x64, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, - 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x43, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x43, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x52, 0x12, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, - 0x10, 0x0a, 0x0e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, - 0x64, 0x42, 0x16, 0x0a, 0x14, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x72, - 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x22, 0x30, 0x0a, 0x0d, - 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xad, - 0x02, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x12, 0x37, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, - 0x01, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0c, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, - 0x01, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, - 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, 0x0a, 0x11, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xb2, - 0x05, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x42, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, + 0x6c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x64, 0x65, 0x70, + 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x64, + 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xf4, + 0x03, 0x0a, 0x11, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x12, 0x77, 0x0a, 0x1b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x18, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x83, 0x01, + 0x0a, 0x1f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, + 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, + 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1c, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x1d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x71, 0x0a, 0x21, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xce, + 0x04, 0x0a, 0x16, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x4e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, + 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, + 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, + 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, + 0x6e, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, + 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x43, + 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, + 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, + 0x54, 0x55, 0x50, 0x4c, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x54, 0x4f, 0x5f, 0x55, 0x53, 0x45, 0x52, + 0x53, 0x45, 0x54, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x02, + 0x22, 0x57, 0x0a, 0x16, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, + 0x41, 0x43, 0x48, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, + 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, + 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, + 0x65, 0x0a, 0x0f, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xda, 0x04, 0x0a, 0x0f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, + 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, + 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xfa, 0x42, 0x2d, 0x72, 0x2b, 0x28, 0x40, 0x32, 0x27, 0x5e, + 0x28, 0x5c, 0x2e, 0x5c, 0x2e, 0x5c, 0x2e, 0x7c, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, + 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, + 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x24, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x77, 0x69, 0x6c, + 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, + 0x63, 0x61, 0x72, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, + 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x13, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, + 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x42, 0x16, 0x0a, 0x14, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x72, 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, + 0x61, 0x72, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x22, 0x30, 0x0a, 0x0d, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x76, 0x65, 0x61, + 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, + 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xad, 0x02, 0x0a, 0x0e, 0x55, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x75, + 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x05, 0x75, + 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0c, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x65, + 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x42, 0x0f, 0xfa, 0x42, 0x0c, - 0x92, 0x01, 0x09, 0x08, 0x01, 0x22, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x05, 0x63, 0x68, - 0x69, 0x6c, 0x64, 0x1a, 0xdd, 0x04, 0x0a, 0x05, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x37, 0x0a, - 0x05, 0x5f, 0x74, 0x68, 0x69, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x54, 0x68, 0x69, 0x73, 0x48, 0x00, - 0x52, 0x04, 0x54, 0x68, 0x69, 0x73, 0x12, 0x4f, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, - 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, - 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, 0x6c, - 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, - 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, - 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, - 0x72, 0x69, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x1b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x65, 0x64, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, - 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, - 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x18, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x65, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x5f, 0x6e, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x4e, 0x69, - 0x6c, 0x48, 0x00, 0x52, 0x03, 0x4e, 0x69, 0x6c, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, - 0x68, 0x1a, 0x06, 0x0a, 0x04, 0x54, 0x68, 0x69, 0x73, 0x1a, 0x05, 0x0a, 0x03, 0x4e, 0x69, 0x6c, - 0x42, 0x11, 0x0a, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, - 0xf8, 0x42, 0x01, 0x22, 0xba, 0x02, 0x0a, 0x0e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, - 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, - 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, - 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, - 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, - 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, - 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, - 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0xec, 0x03, 0x0a, 0x18, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, - 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x52, 0x0a, - 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x65, 0x74, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0xfa, 0x42, 0x07, - 0x82, 0x01, 0x04, 0x10, 0x01, 0x20, 0x00, 0x52, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, + 0x00, 0x52, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, + 0x0a, 0x11, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xb2, 0x05, 0x0a, 0x0c, 0x53, 0x65, 0x74, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x05, 0x63, 0x68, 0x69, + 0x6c, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x43, 0x68, 0x69, 0x6c, 0x64, 0x42, 0x0f, 0xfa, 0x42, 0x0c, 0x92, 0x01, 0x09, 0x08, 0x01, 0x22, + 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x1a, 0xdd, 0x04, + 0x0a, 0x05, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x37, 0x0a, 0x05, 0x5f, 0x74, 0x68, 0x69, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, + 0x69, 0x6c, 0x64, 0x2e, 0x54, 0x68, 0x69, 0x73, 0x48, 0x00, 0x52, 0x04, 0x54, 0x68, 0x69, 0x73, + 0x12, 0x4f, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, + 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, + 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, + 0x52, 0x0e, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, + 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, + 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x6c, + 0x0a, 0x1b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x75, 0x70, + 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x42, - 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, - 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, - 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, + 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, + 0x48, 0x00, 0x52, 0x18, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, + 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x34, 0x0a, 0x04, + 0x5f, 0x6e, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x4e, 0x69, 0x6c, 0x48, 0x00, 0x52, 0x03, 0x4e, + 0x69, 0x6c, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, - 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x06, 0x0a, 0x04, 0x54, + 0x68, 0x69, 0x73, 0x1a, 0x05, 0x0a, 0x03, 0x4e, 0x69, 0x6c, 0x42, 0x11, 0x0a, 0x0a, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xba, 0x02, + 0x0a, 0x0e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x12, 0x46, 0x0a, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, + 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, + 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, + 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, + 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, + 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, + 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xec, 0x03, 0x0a, 0x18, 0x46, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, + 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x52, 0x0a, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, + 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x46, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x82, 0x01, 0x04, 0x10, 0x01, 0x20, + 0x00, 0x52, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x74, + 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, + 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, + 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, + 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, + 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, + 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, + 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, + 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x48, 0x0a, 0x08, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x14, 0x46, + 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x02, 0x22, 0x91, 0x02, 0x0a, 0x0f, 0x43, 0x6f, + 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x41, 0x0a, + 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, + 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x08, + 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x08, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x46, - 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, - 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x02, 0x22, - 0x91, 0x02, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, - 0x73, 0x65, 0x74, 0x12, 0x41, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, - 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, - 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, - 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x34, 0x0a, - 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x55, 0x50, 0x4c, 0x45, - 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x55, 0x50, - 0x4c, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, - 0x54, 0x10, 0x01, 0x22, 0x8a, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x18, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x65, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x3f, 0x0a, 0x1c, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, - 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x9c, 0x01, 0x0a, 0x10, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x37, 0x0a, 0x06, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x75, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x48, 0x00, - 0x52, 0x06, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x42, 0x15, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x72, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x22, - 0xb0, 0x01, 0x0a, 0x0f, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x22, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x35, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, - 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x32, - 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x4e, 0x4f, 0x54, - 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, 0x12, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x68, 0x69, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x4b, 0xfa, 0x42, 0x48, 0x72, 0x46, 0x28, 0x80, 0x01, 0x32, 0x41, 0x5e, 0x28, 0x28, 0x5b, - 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, - 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, - 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, - 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, - 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, - 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, - 0x52, 0x12, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x64, 0x0a, 0x1b, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, - 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, - 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, - 0x52, 0x18, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x49, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x11, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, 0x21, - 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, - 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, - 0x24, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, - 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x15, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x22, 0x86, 0x03, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x6b, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, - 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, + 0x54, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x5f, 0x55, 0x53, 0x45, + 0x52, 0x53, 0x45, 0x54, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x01, 0x22, 0x8a, 0x01, + 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x37, 0x0a, 0x18, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, + 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x15, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x4c, + 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x1c, 0x7a, 0x65, 0x72, + 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, + 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x19, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x01, 0x0a, 0x10, 0x43, + 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, + 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x09, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x76, + 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x76, 0x65, + 0x61, 0x74, 0x42, 0x15, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6f, 0x72, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x22, 0xb0, 0x01, 0x0a, 0x0f, 0x43, 0x61, + 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, + 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, + 0x70, 0x12, 0x35, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, + 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, + 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x32, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, + 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x4e, 0x4f, 0x54, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, + 0x12, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0xfa, 0x42, 0x48, 0x72, + 0x46, 0x28, 0x80, 0x01, 0x32, 0x41, 0x5e, 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x13, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x80, 0x08, 0x32, 0x20, 0x5e, 0x28, 0x28, 0x5b, 0x61, - 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, - 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x7c, 0x5c, 0x2a, 0x29, 0x3f, 0x24, 0x52, 0x11, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x52, - 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x58, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, - 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, - 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, - 0x3f, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x8a, 0x01, 0x0a, - 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x43, 0x6f, - 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, - 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, - 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x07, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x13, 0x43, 0x6f, 0x72, 0x65, 0x5c, - 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x08, 0x43, 0x6f, 0x72, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, + 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, + 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, 0x52, 0x12, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x64, + 0x0a, 0x1b, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, + 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, + 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, 0x52, 0x18, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, + 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x10, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, + 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x86, 0x03, + 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, + 0x6b, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, + 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, + 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, + 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, + 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, + 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x13, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, + 0x28, 0x80, 0x08, 0x32, 0x20, 0x5e, 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, + 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x7c, + 0x5c, 0x2a, 0x29, 0x3f, 0x24, 0x52, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x58, 0x0a, 0x0e, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x46, + 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, + 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, + 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x08, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x6a, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x45, 0x50, + 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, + 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x41, + 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x50, 0x52, 0x45, + 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x02, 0x42, 0x8a, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x76, 0x31, 0x42, 0x09, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, + 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, + 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x43, 0x6f, 0x72, + 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, + 0x13, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x43, 0x6f, 0x72, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3685,141 +3770,144 @@ func file_core_v1_core_proto_rawDescGZIP() []byte { return file_core_v1_core_proto_rawDescData } -var file_core_v1_core_proto_enumTypes = make([]protoimpl.EnumInfo, 7) +var file_core_v1_core_proto_enumTypes = make([]protoimpl.EnumInfo, 8) var file_core_v1_core_proto_msgTypes = make([]protoimpl.MessageInfo, 43) var file_core_v1_core_proto_goTypes = []any{ - (RelationTupleUpdate_Operation)(0), // 0: core.v1.RelationTupleUpdate.Operation - (SetOperationUserset_Operation)(0), // 1: core.v1.SetOperationUserset.Operation - (ReachabilityEntrypoint_ReachabilityEntrypointKind)(0), // 2: core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind - (ReachabilityEntrypoint_EntrypointResultStatus)(0), // 3: core.v1.ReachabilityEntrypoint.EntrypointResultStatus - (FunctionedTupleToUserset_Function)(0), // 4: core.v1.FunctionedTupleToUserset.Function - (ComputedUserset_Object)(0), // 5: core.v1.ComputedUserset.Object - (CaveatOperation_Operation)(0), // 6: core.v1.CaveatOperation.Operation - (*RelationTuple)(nil), // 7: core.v1.RelationTuple - (*RelationshipIntegrity)(nil), // 8: core.v1.RelationshipIntegrity - (*ContextualizedCaveat)(nil), // 9: core.v1.ContextualizedCaveat - (*CaveatDefinition)(nil), // 10: core.v1.CaveatDefinition - (*CaveatTypeReference)(nil), // 11: core.v1.CaveatTypeReference - (*ObjectAndRelation)(nil), // 12: core.v1.ObjectAndRelation - (*RelationReference)(nil), // 13: core.v1.RelationReference - (*Zookie)(nil), // 14: core.v1.Zookie - (*RelationTupleUpdate)(nil), // 15: core.v1.RelationTupleUpdate - (*RelationTupleTreeNode)(nil), // 16: core.v1.RelationTupleTreeNode - (*SetOperationUserset)(nil), // 17: core.v1.SetOperationUserset - (*DirectSubject)(nil), // 18: core.v1.DirectSubject - (*DirectSubjects)(nil), // 19: core.v1.DirectSubjects - (*Metadata)(nil), // 20: core.v1.Metadata - (*NamespaceDefinition)(nil), // 21: core.v1.NamespaceDefinition - (*Relation)(nil), // 22: core.v1.Relation - (*ReachabilityGraph)(nil), // 23: core.v1.ReachabilityGraph - (*ReachabilityEntrypoints)(nil), // 24: core.v1.ReachabilityEntrypoints - (*ReachabilityEntrypoint)(nil), // 25: core.v1.ReachabilityEntrypoint - (*TypeInformation)(nil), // 26: core.v1.TypeInformation - (*AllowedRelation)(nil), // 27: core.v1.AllowedRelation - (*ExpirationTrait)(nil), // 28: core.v1.ExpirationTrait - (*AllowedCaveat)(nil), // 29: core.v1.AllowedCaveat - (*UsersetRewrite)(nil), // 30: core.v1.UsersetRewrite - (*SetOperation)(nil), // 31: core.v1.SetOperation - (*TupleToUserset)(nil), // 32: core.v1.TupleToUserset - (*FunctionedTupleToUserset)(nil), // 33: core.v1.FunctionedTupleToUserset - (*ComputedUserset)(nil), // 34: core.v1.ComputedUserset - (*SourcePosition)(nil), // 35: core.v1.SourcePosition - (*CaveatExpression)(nil), // 36: core.v1.CaveatExpression - (*CaveatOperation)(nil), // 37: core.v1.CaveatOperation - (*RelationshipFilter)(nil), // 38: core.v1.RelationshipFilter - (*SubjectFilter)(nil), // 39: core.v1.SubjectFilter - nil, // 40: core.v1.CaveatDefinition.ParameterTypesEntry - nil, // 41: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry - nil, // 42: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry - (*AllowedRelation_PublicWildcard)(nil), // 43: core.v1.AllowedRelation.PublicWildcard - (*SetOperation_Child)(nil), // 44: core.v1.SetOperation.Child - (*SetOperation_Child_This)(nil), // 45: core.v1.SetOperation.Child.This - (*SetOperation_Child_Nil)(nil), // 46: core.v1.SetOperation.Child.Nil - (*TupleToUserset_Tupleset)(nil), // 47: core.v1.TupleToUserset.Tupleset - (*FunctionedTupleToUserset_Tupleset)(nil), // 48: core.v1.FunctionedTupleToUserset.Tupleset - (*SubjectFilter_RelationFilter)(nil), // 49: core.v1.SubjectFilter.RelationFilter - (*timestamppb.Timestamp)(nil), // 50: google.protobuf.Timestamp - (*structpb.Struct)(nil), // 51: google.protobuf.Struct - (*anypb.Any)(nil), // 52: google.protobuf.Any + (DeprecationType)(0), // 0: core.v1.DeprecationType + (RelationTupleUpdate_Operation)(0), // 1: core.v1.RelationTupleUpdate.Operation + (SetOperationUserset_Operation)(0), // 2: core.v1.SetOperationUserset.Operation + (ReachabilityEntrypoint_ReachabilityEntrypointKind)(0), // 3: core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind + (ReachabilityEntrypoint_EntrypointResultStatus)(0), // 4: core.v1.ReachabilityEntrypoint.EntrypointResultStatus + (FunctionedTupleToUserset_Function)(0), // 5: core.v1.FunctionedTupleToUserset.Function + (ComputedUserset_Object)(0), // 6: core.v1.ComputedUserset.Object + (CaveatOperation_Operation)(0), // 7: core.v1.CaveatOperation.Operation + (*RelationTuple)(nil), // 8: core.v1.RelationTuple + (*RelationshipIntegrity)(nil), // 9: core.v1.RelationshipIntegrity + (*ContextualizedCaveat)(nil), // 10: core.v1.ContextualizedCaveat + (*CaveatDefinition)(nil), // 11: core.v1.CaveatDefinition + (*CaveatTypeReference)(nil), // 12: core.v1.CaveatTypeReference + (*ObjectAndRelation)(nil), // 13: core.v1.ObjectAndRelation + (*RelationReference)(nil), // 14: core.v1.RelationReference + (*Zookie)(nil), // 15: core.v1.Zookie + (*RelationTupleUpdate)(nil), // 16: core.v1.RelationTupleUpdate + (*RelationTupleTreeNode)(nil), // 17: core.v1.RelationTupleTreeNode + (*SetOperationUserset)(nil), // 18: core.v1.SetOperationUserset + (*DirectSubject)(nil), // 19: core.v1.DirectSubject + (*DirectSubjects)(nil), // 20: core.v1.DirectSubjects + (*Metadata)(nil), // 21: core.v1.Metadata + (*NamespaceDefinition)(nil), // 22: core.v1.NamespaceDefinition + (*Relation)(nil), // 23: core.v1.Relation + (*ReachabilityGraph)(nil), // 24: core.v1.ReachabilityGraph + (*ReachabilityEntrypoints)(nil), // 25: core.v1.ReachabilityEntrypoints + (*ReachabilityEntrypoint)(nil), // 26: core.v1.ReachabilityEntrypoint + (*TypeInformation)(nil), // 27: core.v1.TypeInformation + (*AllowedRelation)(nil), // 28: core.v1.AllowedRelation + (*ExpirationTrait)(nil), // 29: core.v1.ExpirationTrait + (*AllowedCaveat)(nil), // 30: core.v1.AllowedCaveat + (*UsersetRewrite)(nil), // 31: core.v1.UsersetRewrite + (*SetOperation)(nil), // 32: core.v1.SetOperation + (*TupleToUserset)(nil), // 33: core.v1.TupleToUserset + (*FunctionedTupleToUserset)(nil), // 34: core.v1.FunctionedTupleToUserset + (*ComputedUserset)(nil), // 35: core.v1.ComputedUserset + (*SourcePosition)(nil), // 36: core.v1.SourcePosition + (*CaveatExpression)(nil), // 37: core.v1.CaveatExpression + (*CaveatOperation)(nil), // 38: core.v1.CaveatOperation + (*RelationshipFilter)(nil), // 39: core.v1.RelationshipFilter + (*SubjectFilter)(nil), // 40: core.v1.SubjectFilter + nil, // 41: core.v1.CaveatDefinition.ParameterTypesEntry + nil, // 42: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry + nil, // 43: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry + (*AllowedRelation_PublicWildcard)(nil), // 44: core.v1.AllowedRelation.PublicWildcard + (*SetOperation_Child)(nil), // 45: core.v1.SetOperation.Child + (*SetOperation_Child_This)(nil), // 46: core.v1.SetOperation.Child.This + (*SetOperation_Child_Nil)(nil), // 47: core.v1.SetOperation.Child.Nil + (*TupleToUserset_Tupleset)(nil), // 48: core.v1.TupleToUserset.Tupleset + (*FunctionedTupleToUserset_Tupleset)(nil), // 49: core.v1.FunctionedTupleToUserset.Tupleset + (*SubjectFilter_RelationFilter)(nil), // 50: core.v1.SubjectFilter.RelationFilter + (*timestamppb.Timestamp)(nil), // 51: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 52: google.protobuf.Struct + (*anypb.Any)(nil), // 53: google.protobuf.Any } var file_core_v1_core_proto_depIdxs = []int32{ - 12, // 0: core.v1.RelationTuple.resource_and_relation:type_name -> core.v1.ObjectAndRelation - 12, // 1: core.v1.RelationTuple.subject:type_name -> core.v1.ObjectAndRelation - 9, // 2: core.v1.RelationTuple.caveat:type_name -> core.v1.ContextualizedCaveat - 8, // 3: core.v1.RelationTuple.integrity:type_name -> core.v1.RelationshipIntegrity - 50, // 4: core.v1.RelationTuple.optional_expiration_time:type_name -> google.protobuf.Timestamp - 50, // 5: core.v1.RelationshipIntegrity.hashed_at:type_name -> google.protobuf.Timestamp - 51, // 6: core.v1.ContextualizedCaveat.context:type_name -> google.protobuf.Struct - 40, // 7: core.v1.CaveatDefinition.parameter_types:type_name -> core.v1.CaveatDefinition.ParameterTypesEntry - 20, // 8: core.v1.CaveatDefinition.metadata:type_name -> core.v1.Metadata - 35, // 9: core.v1.CaveatDefinition.source_position:type_name -> core.v1.SourcePosition - 11, // 10: core.v1.CaveatTypeReference.child_types:type_name -> core.v1.CaveatTypeReference - 0, // 11: core.v1.RelationTupleUpdate.operation:type_name -> core.v1.RelationTupleUpdate.Operation - 7, // 12: core.v1.RelationTupleUpdate.tuple:type_name -> core.v1.RelationTuple - 17, // 13: core.v1.RelationTupleTreeNode.intermediate_node:type_name -> core.v1.SetOperationUserset - 19, // 14: core.v1.RelationTupleTreeNode.leaf_node:type_name -> core.v1.DirectSubjects - 12, // 15: core.v1.RelationTupleTreeNode.expanded:type_name -> core.v1.ObjectAndRelation - 36, // 16: core.v1.RelationTupleTreeNode.caveat_expression:type_name -> core.v1.CaveatExpression - 1, // 17: core.v1.SetOperationUserset.operation:type_name -> core.v1.SetOperationUserset.Operation - 16, // 18: core.v1.SetOperationUserset.child_nodes:type_name -> core.v1.RelationTupleTreeNode - 12, // 19: core.v1.DirectSubject.subject:type_name -> core.v1.ObjectAndRelation - 36, // 20: core.v1.DirectSubject.caveat_expression:type_name -> core.v1.CaveatExpression - 18, // 21: core.v1.DirectSubjects.subjects:type_name -> core.v1.DirectSubject - 52, // 22: core.v1.Metadata.metadata_message:type_name -> google.protobuf.Any - 22, // 23: core.v1.NamespaceDefinition.relation:type_name -> core.v1.Relation - 20, // 24: core.v1.NamespaceDefinition.metadata:type_name -> core.v1.Metadata - 35, // 25: core.v1.NamespaceDefinition.source_position:type_name -> core.v1.SourcePosition - 30, // 26: core.v1.Relation.userset_rewrite:type_name -> core.v1.UsersetRewrite - 26, // 27: core.v1.Relation.type_information:type_name -> core.v1.TypeInformation - 20, // 28: core.v1.Relation.metadata:type_name -> core.v1.Metadata - 35, // 29: core.v1.Relation.source_position:type_name -> core.v1.SourcePosition - 41, // 30: core.v1.ReachabilityGraph.entrypoints_by_subject_type:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry - 42, // 31: core.v1.ReachabilityGraph.entrypoints_by_subject_relation:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry - 25, // 32: core.v1.ReachabilityEntrypoints.entrypoints:type_name -> core.v1.ReachabilityEntrypoint - 13, // 33: core.v1.ReachabilityEntrypoints.subject_relation:type_name -> core.v1.RelationReference - 2, // 34: core.v1.ReachabilityEntrypoint.kind:type_name -> core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind - 13, // 35: core.v1.ReachabilityEntrypoint.target_relation:type_name -> core.v1.RelationReference - 3, // 36: core.v1.ReachabilityEntrypoint.result_status:type_name -> core.v1.ReachabilityEntrypoint.EntrypointResultStatus - 27, // 37: core.v1.TypeInformation.allowed_direct_relations:type_name -> core.v1.AllowedRelation - 43, // 38: core.v1.AllowedRelation.public_wildcard:type_name -> core.v1.AllowedRelation.PublicWildcard - 35, // 39: core.v1.AllowedRelation.source_position:type_name -> core.v1.SourcePosition - 29, // 40: core.v1.AllowedRelation.required_caveat:type_name -> core.v1.AllowedCaveat - 28, // 41: core.v1.AllowedRelation.required_expiration:type_name -> core.v1.ExpirationTrait - 31, // 42: core.v1.UsersetRewrite.union:type_name -> core.v1.SetOperation - 31, // 43: core.v1.UsersetRewrite.intersection:type_name -> core.v1.SetOperation - 31, // 44: core.v1.UsersetRewrite.exclusion:type_name -> core.v1.SetOperation - 35, // 45: core.v1.UsersetRewrite.source_position:type_name -> core.v1.SourcePosition - 44, // 46: core.v1.SetOperation.child:type_name -> core.v1.SetOperation.Child - 47, // 47: core.v1.TupleToUserset.tupleset:type_name -> core.v1.TupleToUserset.Tupleset - 34, // 48: core.v1.TupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset - 35, // 49: core.v1.TupleToUserset.source_position:type_name -> core.v1.SourcePosition - 4, // 50: core.v1.FunctionedTupleToUserset.function:type_name -> core.v1.FunctionedTupleToUserset.Function - 48, // 51: core.v1.FunctionedTupleToUserset.tupleset:type_name -> core.v1.FunctionedTupleToUserset.Tupleset - 34, // 52: core.v1.FunctionedTupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset - 35, // 53: core.v1.FunctionedTupleToUserset.source_position:type_name -> core.v1.SourcePosition - 5, // 54: core.v1.ComputedUserset.object:type_name -> core.v1.ComputedUserset.Object - 35, // 55: core.v1.ComputedUserset.source_position:type_name -> core.v1.SourcePosition - 37, // 56: core.v1.CaveatExpression.operation:type_name -> core.v1.CaveatOperation - 9, // 57: core.v1.CaveatExpression.caveat:type_name -> core.v1.ContextualizedCaveat - 6, // 58: core.v1.CaveatOperation.op:type_name -> core.v1.CaveatOperation.Operation - 36, // 59: core.v1.CaveatOperation.children:type_name -> core.v1.CaveatExpression - 39, // 60: core.v1.RelationshipFilter.optional_subject_filter:type_name -> core.v1.SubjectFilter - 49, // 61: core.v1.SubjectFilter.optional_relation:type_name -> core.v1.SubjectFilter.RelationFilter - 11, // 62: core.v1.CaveatDefinition.ParameterTypesEntry.value:type_name -> core.v1.CaveatTypeReference - 24, // 63: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry.value:type_name -> core.v1.ReachabilityEntrypoints - 24, // 64: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry.value:type_name -> core.v1.ReachabilityEntrypoints - 45, // 65: core.v1.SetOperation.Child._this:type_name -> core.v1.SetOperation.Child.This - 34, // 66: core.v1.SetOperation.Child.computed_userset:type_name -> core.v1.ComputedUserset - 32, // 67: core.v1.SetOperation.Child.tuple_to_userset:type_name -> core.v1.TupleToUserset - 30, // 68: core.v1.SetOperation.Child.userset_rewrite:type_name -> core.v1.UsersetRewrite - 33, // 69: core.v1.SetOperation.Child.functioned_tuple_to_userset:type_name -> core.v1.FunctionedTupleToUserset - 46, // 70: core.v1.SetOperation.Child._nil:type_name -> core.v1.SetOperation.Child.Nil - 35, // 71: core.v1.SetOperation.Child.source_position:type_name -> core.v1.SourcePosition - 72, // [72:72] is the sub-list for method output_type - 72, // [72:72] is the sub-list for method input_type - 72, // [72:72] is the sub-list for extension type_name - 72, // [72:72] is the sub-list for extension extendee - 0, // [0:72] is the sub-list for field type_name + 13, // 0: core.v1.RelationTuple.resource_and_relation:type_name -> core.v1.ObjectAndRelation + 13, // 1: core.v1.RelationTuple.subject:type_name -> core.v1.ObjectAndRelation + 10, // 2: core.v1.RelationTuple.caveat:type_name -> core.v1.ContextualizedCaveat + 9, // 3: core.v1.RelationTuple.integrity:type_name -> core.v1.RelationshipIntegrity + 51, // 4: core.v1.RelationTuple.optional_expiration_time:type_name -> google.protobuf.Timestamp + 51, // 5: core.v1.RelationshipIntegrity.hashed_at:type_name -> google.protobuf.Timestamp + 52, // 6: core.v1.ContextualizedCaveat.context:type_name -> google.protobuf.Struct + 41, // 7: core.v1.CaveatDefinition.parameter_types:type_name -> core.v1.CaveatDefinition.ParameterTypesEntry + 21, // 8: core.v1.CaveatDefinition.metadata:type_name -> core.v1.Metadata + 36, // 9: core.v1.CaveatDefinition.source_position:type_name -> core.v1.SourcePosition + 12, // 10: core.v1.CaveatTypeReference.child_types:type_name -> core.v1.CaveatTypeReference + 1, // 11: core.v1.RelationTupleUpdate.operation:type_name -> core.v1.RelationTupleUpdate.Operation + 8, // 12: core.v1.RelationTupleUpdate.tuple:type_name -> core.v1.RelationTuple + 18, // 13: core.v1.RelationTupleTreeNode.intermediate_node:type_name -> core.v1.SetOperationUserset + 20, // 14: core.v1.RelationTupleTreeNode.leaf_node:type_name -> core.v1.DirectSubjects + 13, // 15: core.v1.RelationTupleTreeNode.expanded:type_name -> core.v1.ObjectAndRelation + 37, // 16: core.v1.RelationTupleTreeNode.caveat_expression:type_name -> core.v1.CaveatExpression + 2, // 17: core.v1.SetOperationUserset.operation:type_name -> core.v1.SetOperationUserset.Operation + 17, // 18: core.v1.SetOperationUserset.child_nodes:type_name -> core.v1.RelationTupleTreeNode + 13, // 19: core.v1.DirectSubject.subject:type_name -> core.v1.ObjectAndRelation + 37, // 20: core.v1.DirectSubject.caveat_expression:type_name -> core.v1.CaveatExpression + 19, // 21: core.v1.DirectSubjects.subjects:type_name -> core.v1.DirectSubject + 53, // 22: core.v1.Metadata.metadata_message:type_name -> google.protobuf.Any + 23, // 23: core.v1.NamespaceDefinition.relation:type_name -> core.v1.Relation + 21, // 24: core.v1.NamespaceDefinition.metadata:type_name -> core.v1.Metadata + 36, // 25: core.v1.NamespaceDefinition.source_position:type_name -> core.v1.SourcePosition + 31, // 26: core.v1.Relation.userset_rewrite:type_name -> core.v1.UsersetRewrite + 27, // 27: core.v1.Relation.type_information:type_name -> core.v1.TypeInformation + 21, // 28: core.v1.Relation.metadata:type_name -> core.v1.Metadata + 36, // 29: core.v1.Relation.source_position:type_name -> core.v1.SourcePosition + 0, // 30: core.v1.Relation.deprecation_type:type_name -> core.v1.DeprecationType + 42, // 31: core.v1.ReachabilityGraph.entrypoints_by_subject_type:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry + 43, // 32: core.v1.ReachabilityGraph.entrypoints_by_subject_relation:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry + 26, // 33: core.v1.ReachabilityEntrypoints.entrypoints:type_name -> core.v1.ReachabilityEntrypoint + 14, // 34: core.v1.ReachabilityEntrypoints.subject_relation:type_name -> core.v1.RelationReference + 3, // 35: core.v1.ReachabilityEntrypoint.kind:type_name -> core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind + 14, // 36: core.v1.ReachabilityEntrypoint.target_relation:type_name -> core.v1.RelationReference + 4, // 37: core.v1.ReachabilityEntrypoint.result_status:type_name -> core.v1.ReachabilityEntrypoint.EntrypointResultStatus + 28, // 38: core.v1.TypeInformation.allowed_direct_relations:type_name -> core.v1.AllowedRelation + 44, // 39: core.v1.AllowedRelation.public_wildcard:type_name -> core.v1.AllowedRelation.PublicWildcard + 36, // 40: core.v1.AllowedRelation.source_position:type_name -> core.v1.SourcePosition + 30, // 41: core.v1.AllowedRelation.required_caveat:type_name -> core.v1.AllowedCaveat + 29, // 42: core.v1.AllowedRelation.required_expiration:type_name -> core.v1.ExpirationTrait + 0, // 43: core.v1.AllowedRelation.deprecation_type:type_name -> core.v1.DeprecationType + 32, // 44: core.v1.UsersetRewrite.union:type_name -> core.v1.SetOperation + 32, // 45: core.v1.UsersetRewrite.intersection:type_name -> core.v1.SetOperation + 32, // 46: core.v1.UsersetRewrite.exclusion:type_name -> core.v1.SetOperation + 36, // 47: core.v1.UsersetRewrite.source_position:type_name -> core.v1.SourcePosition + 45, // 48: core.v1.SetOperation.child:type_name -> core.v1.SetOperation.Child + 48, // 49: core.v1.TupleToUserset.tupleset:type_name -> core.v1.TupleToUserset.Tupleset + 35, // 50: core.v1.TupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset + 36, // 51: core.v1.TupleToUserset.source_position:type_name -> core.v1.SourcePosition + 5, // 52: core.v1.FunctionedTupleToUserset.function:type_name -> core.v1.FunctionedTupleToUserset.Function + 49, // 53: core.v1.FunctionedTupleToUserset.tupleset:type_name -> core.v1.FunctionedTupleToUserset.Tupleset + 35, // 54: core.v1.FunctionedTupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset + 36, // 55: core.v1.FunctionedTupleToUserset.source_position:type_name -> core.v1.SourcePosition + 6, // 56: core.v1.ComputedUserset.object:type_name -> core.v1.ComputedUserset.Object + 36, // 57: core.v1.ComputedUserset.source_position:type_name -> core.v1.SourcePosition + 38, // 58: core.v1.CaveatExpression.operation:type_name -> core.v1.CaveatOperation + 10, // 59: core.v1.CaveatExpression.caveat:type_name -> core.v1.ContextualizedCaveat + 7, // 60: core.v1.CaveatOperation.op:type_name -> core.v1.CaveatOperation.Operation + 37, // 61: core.v1.CaveatOperation.children:type_name -> core.v1.CaveatExpression + 40, // 62: core.v1.RelationshipFilter.optional_subject_filter:type_name -> core.v1.SubjectFilter + 50, // 63: core.v1.SubjectFilter.optional_relation:type_name -> core.v1.SubjectFilter.RelationFilter + 12, // 64: core.v1.CaveatDefinition.ParameterTypesEntry.value:type_name -> core.v1.CaveatTypeReference + 25, // 65: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry.value:type_name -> core.v1.ReachabilityEntrypoints + 25, // 66: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry.value:type_name -> core.v1.ReachabilityEntrypoints + 46, // 67: core.v1.SetOperation.Child._this:type_name -> core.v1.SetOperation.Child.This + 35, // 68: core.v1.SetOperation.Child.computed_userset:type_name -> core.v1.ComputedUserset + 33, // 69: core.v1.SetOperation.Child.tuple_to_userset:type_name -> core.v1.TupleToUserset + 31, // 70: core.v1.SetOperation.Child.userset_rewrite:type_name -> core.v1.UsersetRewrite + 34, // 71: core.v1.SetOperation.Child.functioned_tuple_to_userset:type_name -> core.v1.FunctionedTupleToUserset + 47, // 72: core.v1.SetOperation.Child._nil:type_name -> core.v1.SetOperation.Child.Nil + 36, // 73: core.v1.SetOperation.Child.source_position:type_name -> core.v1.SourcePosition + 74, // [74:74] is the sub-list for method output_type + 74, // [74:74] is the sub-list for method input_type + 74, // [74:74] is the sub-list for extension type_name + 74, // [74:74] is the sub-list for extension extendee + 0, // [0:74] is the sub-list for field type_name } func init() { file_core_v1_core_proto_init() } @@ -4339,7 +4427,7 @@ func file_core_v1_core_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_core_v1_core_proto_rawDesc, - NumEnums: 7, + NumEnums: 8, NumMessages: 43, NumExtensions: 0, NumServices: 0, diff --git a/pkg/proto/core/v1/core.pb.validate.go b/pkg/proto/core/v1/core.pb.validate.go index f8a01af22e..8cd4ed538b 100644 --- a/pkg/proto/core/v1/core.pb.validate.go +++ b/pkg/proto/core/v1/core.pb.validate.go @@ -2782,6 +2782,8 @@ func (m *Relation) validate(all bool) error { // no validation rules for CanonicalCacheKey + // no validation rules for DeprecationType + if len(errors) > 0 { return RelationMultiError(errors) } @@ -3626,6 +3628,8 @@ func (m *AllowedRelation) validate(all bool) error { } } + // no validation rules for DeprecationType + switch v := m.RelationOrWildcard.(type) { case *AllowedRelation_Relation: if v == nil { diff --git a/pkg/proto/core/v1/core_vtproto.pb.go b/pkg/proto/core/v1/core_vtproto.pb.go index 160a1d9339..9807016358 100644 --- a/pkg/proto/core/v1/core_vtproto.pb.go +++ b/pkg/proto/core/v1/core_vtproto.pb.go @@ -381,6 +381,7 @@ func (m *Relation) CloneVT() *Relation { r.SourcePosition = m.SourcePosition.CloneVT() r.AliasingRelation = m.AliasingRelation r.CanonicalCacheKey = m.CanonicalCacheKey + r.DeprecationType = m.DeprecationType if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -516,6 +517,7 @@ func (m *AllowedRelation) CloneVT() *AllowedRelation { r.SourcePosition = m.SourcePosition.CloneVT() r.RequiredCaveat = m.RequiredCaveat.CloneVT() r.RequiredExpiration = m.RequiredExpiration.CloneVT() + r.DeprecationType = m.DeprecationType if m.RelationOrWildcard != nil { r.RelationOrWildcard = m.RelationOrWildcard.(interface { CloneVT() isAllowedRelation_RelationOrWildcard @@ -1525,6 +1527,9 @@ func (this *Relation) EqualVT(that *Relation) bool { if this.CanonicalCacheKey != that.CanonicalCacheKey { return false } + if this.DeprecationType != that.DeprecationType { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1740,6 +1745,9 @@ func (this *AllowedRelation) EqualVT(that *AllowedRelation) bool { if !this.RequiredExpiration.EqualVT(that.RequiredExpiration) { return false } + if this.DeprecationType != that.DeprecationType { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -3438,6 +3446,11 @@ func (m *Relation) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.DeprecationType != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DeprecationType)) + i-- + dAtA[i] = 0x40 + } if len(m.CanonicalCacheKey) > 0 { i -= len(m.CanonicalCacheKey) copy(dAtA[i:], m.CanonicalCacheKey) @@ -3825,6 +3838,11 @@ func (m *AllowedRelation) MarshalToSizedBufferVT(dAtA []byte) (int, error) { } i -= size } + if m.DeprecationType != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DeprecationType)) + i-- + dAtA[i] = 0x40 + } if m.RequiredExpiration != nil { size, err := m.RequiredExpiration.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -5412,6 +5430,9 @@ func (m *Relation) SizeVT() (n int) { if l > 0 { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.DeprecationType != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DeprecationType)) + } n += len(m.unknownFields) return n } @@ -5555,6 +5576,9 @@ func (m *AllowedRelation) SizeVT() (n int) { l = m.RequiredExpiration.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.DeprecationType != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DeprecationType)) + } n += len(m.unknownFields) return n } @@ -8497,6 +8521,25 @@ func (m *Relation) UnmarshalVT(dAtA []byte) error { } m.CanonicalCacheKey = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DeprecationType", wireType) + } + m.DeprecationType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DeprecationType |= DeprecationType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -9548,6 +9591,25 @@ func (m *AllowedRelation) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DeprecationType", wireType) + } + m.DeprecationType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DeprecationType |= DeprecationType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/schemadsl/compiler/translator.go b/pkg/schemadsl/compiler/translator.go index 2e8291b9c0..9f5ab01f23 100644 --- a/pkg/schemadsl/compiler/translator.go +++ b/pkg/schemadsl/compiler/translator.go @@ -19,13 +19,15 @@ import ( ) type translationContext struct { - objectTypePrefix *string - mapper input.PositionMapper - schemaString string - skipValidate bool - allowedFlags []string - enabledFlags []string - caveatTypeSet *caveattypes.TypeSet + objectTypePrefix *string + mapper input.PositionMapper + schemaString string + skipValidate bool + allowedFlags []string + enabledFlags []string + caveatTypeSet *caveattypes.TypeSet + deprecatedRelation bool + deprecatedType string } func (tctx *translationContext) prefixedPath(definitionName string) (string, error) { @@ -218,6 +220,15 @@ func translateObjectDefinition(tctx *translationContext, defNode *dslNode) (*cor continue } + if relationOrPermissionNode.GetType() == dslshape.NodeTypeDeprecated { + tctx.deprecatedRelation = true + tctx.deprecatedType, err = relationOrPermissionNode.GetString(dslshape.NodeDeprecatedPredicateName) + if err != nil { + return nil, relationOrPermissionNode.WithSourceErrorf(tctx.deprecatedType, "invalid deprecation type: %w", err) + } + continue + } + relationOrPermission, err := translateRelationOrPermission(tctx, relationOrPermissionNode) if err != nil { return nil, err @@ -305,6 +316,17 @@ func normalizeComment(value string) string { return strings.Join(lines, "\n") } +func deprecationTypeFromString(s string) core.DeprecationType { + switch strings.ToLower(s) { + case "warn": + return core.DeprecationType_DEPRECATED_TYPE_WARNING + case "error": + return core.DeprecationType_DEPRECATED_TYPE_ERROR + default: + return core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED + } +} + func translateRelationOrPermission(tctx *translationContext, relOrPermNode *dslNode) (*core.Relation, error) { switch relOrPermNode.GetType() { case dslshape.NodeTypeRelation: @@ -314,6 +336,10 @@ func translateRelationOrPermission(tctx *translationContext, relOrPermNode *dslN } rel.Metadata = addComments(rel.Metadata, relOrPermNode) rel.SourcePosition = getSourcePosition(relOrPermNode, tctx.mapper) + if tctx.deprecatedRelation { + rel.DeprecationType = deprecationTypeFromString(tctx.deprecatedType) + tctx.deprecatedRelation = false + } return rel, err case dslshape.NodeTypePermission: diff --git a/pkg/schemadsl/dslshape/dslshape.go b/pkg/schemadsl/dslshape/dslshape.go index c3a599fe84..ff9f85137b 100644 --- a/pkg/schemadsl/dslshape/dslshape.go +++ b/pkg/schemadsl/dslshape/dslshape.go @@ -21,6 +21,7 @@ const ( NodeTypeRelation // A relation NodeTypePermission // A permission + NodeTypeDeprecated // A deprecated relation. NodeTypeTypeReference // A type reference NodeTypeSpecificTypeReference // A reference to a specific type. NodeTypeCaveatReference // A caveat reference under a type. @@ -206,4 +207,9 @@ const ( // NodeExpressionPredicateLeftExpr = "left-expr" NodeExpressionPredicateRightExpr = "right-expr" + + // + // NodeTypeDeprecated + // + NodeDeprecatedPredicateName = "deprecated-relation" ) diff --git a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go index 4ef1e067e7..7b4b32021f 100644 --- a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go +++ b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go @@ -18,22 +18,23 @@ func _() { _ = x[NodeTypeCaveatExpression-7] _ = x[NodeTypeRelation-8] _ = x[NodeTypePermission-9] - _ = x[NodeTypeTypeReference-10] - _ = x[NodeTypeSpecificTypeReference-11] - _ = x[NodeTypeCaveatReference-12] - _ = x[NodeTypeTraitReference-13] - _ = x[NodeTypeUnionExpression-14] - _ = x[NodeTypeIntersectExpression-15] - _ = x[NodeTypeExclusionExpression-16] - _ = x[NodeTypeArrowExpression-17] - _ = x[NodeTypeIdentifier-18] - _ = x[NodeTypeNilExpression-19] - _ = x[NodeTypeCaveatTypeReference-20] + _ = x[NodeTypeDeprecated-10] + _ = x[NodeTypeTypeReference-11] + _ = x[NodeTypeSpecificTypeReference-12] + _ = x[NodeTypeCaveatReference-13] + _ = x[NodeTypeTraitReference-14] + _ = x[NodeTypeUnionExpression-15] + _ = x[NodeTypeIntersectExpression-16] + _ = x[NodeTypeExclusionExpression-17] + _ = x[NodeTypeArrowExpression-18] + _ = x[NodeTypeIdentifier-19] + _ = x[NodeTypeNilExpression-20] + _ = x[NodeTypeCaveatTypeReference-21] } -const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" +const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeDeprecatedNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" -var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 199, 228, 251, 273, 296, 323, 350, 373, 391, 412, 439} +var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 196, 217, 246, 269, 291, 314, 341, 368, 391, 409, 430, 457} func (i NodeType) String() string { if i < 0 || i >= NodeType(len(_NodeType_index)-1) { diff --git a/pkg/schemadsl/lexer/lex_def.go b/pkg/schemadsl/lexer/lex_def.go index 366db87fe6..cb090f9139 100644 --- a/pkg/schemadsl/lexer/lex_def.go +++ b/pkg/schemadsl/lexer/lex_def.go @@ -52,6 +52,7 @@ const ( TokenTypeStar // * // Additional tokens for CEL: https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax + TokenTypeAt // @ TokenTypeQuestionMark // ? TokenTypeConditionalOr // || TokenTypeConditionalAnd // && @@ -78,6 +79,7 @@ var keywords = map[string]struct{}{ "permission": {}, "nil": {}, "with": {}, + "deprecated": {}, } // IsKeyword returns whether the specified input string is a reserved keyword. @@ -153,6 +155,12 @@ Loop: case r == '%': l.emit(TokenTypePercent) + case r == '@': + if l.acceptString("deprecated") { + l.emit(TokenTypeKeyword) + } else { + l.emit(TokenTypeAt) + } case r == '<': if l.acceptString("=") { diff --git a/pkg/schemadsl/lexer/lex_test.go b/pkg/schemadsl/lexer/lex_test.go index a223cc2253..c22a635964 100644 --- a/pkg/schemadsl/lexer/lex_test.go +++ b/pkg/schemadsl/lexer/lex_test.go @@ -46,6 +46,8 @@ var lexerTests = []lexerTest{ {"hash", "#", []Lexeme{{TokenTypeHash, 0, "#", ""}, tEOF}}, {"ellipsis", "...", []Lexeme{{TokenTypeEllipsis, 0, "...", ""}, tEOF}}, + {"token @", "@", []Lexeme{{TokenTypeAt, 0, "@", ""}, tEOF}}, + {"relation reference", "foo#...", []Lexeme{ {TokenTypeIdentifier, 0, "foo", ""}, {TokenTypeHash, 0, "#", ""}, @@ -257,6 +259,17 @@ var lexerTests = []lexerTest{ {TokenTypeRightParen, 0, ")", ""}, tEOF, }}, + {"deprecation test with keyword", "@deprecated", []Lexeme{ + {TokenTypeKeyword, 0, "@deprecated", ""}, + tEOF, + }}, + {"deprecation test with keyword and identifier", "@deprecated(something)", []Lexeme{ + {TokenTypeKeyword, 0, "@deprecated", ""}, + {TokenTypeLeftParen, 0, "(", ""}, + {TokenTypeIdentifier, 0, "something", ""}, + {TokenTypeRightParen, 0, ")", ""}, + tEOF, + }}, } func TestLexer(t *testing.T) { diff --git a/pkg/schemadsl/lexer/tokentype_string.go b/pkg/schemadsl/lexer/tokentype_string.go index 79f358589c..7c29e0484c 100644 --- a/pkg/schemadsl/lexer/tokentype_string.go +++ b/pkg/schemadsl/lexer/tokentype_string.go @@ -34,27 +34,28 @@ func _() { _ = x[TokenTypeHash-23] _ = x[TokenTypeEllipsis-24] _ = x[TokenTypeStar-25] - _ = x[TokenTypeQuestionMark-26] - _ = x[TokenTypeConditionalOr-27] - _ = x[TokenTypeConditionalAnd-28] - _ = x[TokenTypeExclamationPoint-29] - _ = x[TokenTypeLeftBracket-30] - _ = x[TokenTypeRightBracket-31] - _ = x[TokenTypePeriod-32] - _ = x[TokenTypeComma-33] - _ = x[TokenTypePercent-34] - _ = x[TokenTypeLessThan-35] - _ = x[TokenTypeGreaterThan-36] - _ = x[TokenTypeLessThanOrEqual-37] - _ = x[TokenTypeGreaterThanOrEqual-38] - _ = x[TokenTypeEqualEqual-39] - _ = x[TokenTypeNotEqual-40] - _ = x[TokenTypeString-41] + _ = x[TokenTypeAt-26] + _ = x[TokenTypeQuestionMark-27] + _ = x[TokenTypeConditionalOr-28] + _ = x[TokenTypeConditionalAnd-29] + _ = x[TokenTypeExclamationPoint-30] + _ = x[TokenTypeLeftBracket-31] + _ = x[TokenTypeRightBracket-32] + _ = x[TokenTypePeriod-33] + _ = x[TokenTypeComma-34] + _ = x[TokenTypePercent-35] + _ = x[TokenTypeLessThan-36] + _ = x[TokenTypeGreaterThan-37] + _ = x[TokenTypeLessThanOrEqual-38] + _ = x[TokenTypeGreaterThanOrEqual-39] + _ = x[TokenTypeEqualEqual-40] + _ = x[TokenTypeNotEqual-41] + _ = x[TokenTypeString-42] } -const _TokenType_name = "TokenTypeErrorTokenTypeSyntheticSemicolonTokenTypeEOFTokenTypeWhitespaceTokenTypeSinglelineCommentTokenTypeMultilineCommentTokenTypeNewlineTokenTypeKeywordTokenTypeIdentifierTokenTypeNumberTokenTypeLeftBraceTokenTypeRightBraceTokenTypeLeftParenTokenTypeRightParenTokenTypePipeTokenTypePlusTokenTypeMinusTokenTypeAndTokenTypeDivTokenTypeEqualsTokenTypeColonTokenTypeSemicolonTokenTypeRightArrowTokenTypeHashTokenTypeEllipsisTokenTypeStarTokenTypeQuestionMarkTokenTypeConditionalOrTokenTypeConditionalAndTokenTypeExclamationPointTokenTypeLeftBracketTokenTypeRightBracketTokenTypePeriodTokenTypeCommaTokenTypePercentTokenTypeLessThanTokenTypeGreaterThanTokenTypeLessThanOrEqualTokenTypeGreaterThanOrEqualTokenTypeEqualEqualTokenTypeNotEqualTokenTypeString" +const _TokenType_name = "TokenTypeErrorTokenTypeSyntheticSemicolonTokenTypeEOFTokenTypeWhitespaceTokenTypeSinglelineCommentTokenTypeMultilineCommentTokenTypeNewlineTokenTypeKeywordTokenTypeIdentifierTokenTypeNumberTokenTypeLeftBraceTokenTypeRightBraceTokenTypeLeftParenTokenTypeRightParenTokenTypePipeTokenTypePlusTokenTypeMinusTokenTypeAndTokenTypeDivTokenTypeEqualsTokenTypeColonTokenTypeSemicolonTokenTypeRightArrowTokenTypeHashTokenTypeEllipsisTokenTypeStarTokenTypeAtTokenTypeQuestionMarkTokenTypeConditionalOrTokenTypeConditionalAndTokenTypeExclamationPointTokenTypeLeftBracketTokenTypeRightBracketTokenTypePeriodTokenTypeCommaTokenTypePercentTokenTypeLessThanTokenTypeGreaterThanTokenTypeLessThanOrEqualTokenTypeGreaterThanOrEqualTokenTypeEqualEqualTokenTypeNotEqualTokenTypeString" -var _TokenType_index = [...]uint16{0, 14, 41, 53, 72, 98, 123, 139, 155, 174, 189, 207, 226, 244, 263, 276, 289, 303, 315, 327, 342, 356, 374, 393, 406, 423, 436, 457, 479, 502, 527, 547, 568, 583, 597, 613, 630, 650, 674, 701, 720, 737, 752} +var _TokenType_index = [...]uint16{0, 14, 41, 53, 72, 98, 123, 139, 155, 174, 189, 207, 226, 244, 263, 276, 289, 303, 315, 327, 342, 356, 374, 393, 406, 423, 436, 447, 468, 490, 513, 538, 558, 579, 594, 608, 624, 641, 661, 685, 712, 731, 748, 763} func (i TokenType) String() string { if i < 0 || i >= TokenType(len(_TokenType_index)-1) { diff --git a/pkg/schemadsl/parser/parser.go b/pkg/schemadsl/parser/parser.go index 100ad9bf4f..1c78628204 100644 --- a/pkg/schemadsl/parser/parser.go +++ b/pkg/schemadsl/parser/parser.go @@ -315,6 +315,9 @@ func (p *sourceParser) consumeDefinition() AstNode { case p.isKeyword("permission"): defNode.Connect(dslshape.NodePredicateChild, p.consumePermission()) + + case p.isKeyword("@deprecated"): + defNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) } ok := p.consumeStatementTerminator() @@ -353,6 +356,33 @@ func (p *sourceParser) consumeRelation() AstNode { return relNode } +func (p *sourceParser) consumeDeprecation() AstNode { + relNode := p.startNode(dslshape.NodeTypeDeprecated) + defer p.mustFinishNode() + + // deprecation + p.consumeKeyword("@deprecated") + + _, ok := p.consume(lexer.TokenTypeLeftParen) + if !ok { + return relNode + } + + deprecationType, ok := p.consumeIdentifier() + if !ok { + return relNode + } + + relNode.MustDecorate(dslshape.NodeDeprecatedPredicateName, deprecationType) + + _, ok = p.consume(lexer.TokenTypeRightParen) + if !ok { + return relNode + } + + return relNode +} + // consumeTypeReference consumes a reference to a type or types of relations. // ```sometype | anothertype | anothertype:* ``` func (p *sourceParser) consumeTypeReference() AstNode { diff --git a/pkg/schemadsl/parser/parser_test.go b/pkg/schemadsl/parser/parser_test.go index a713a1dc88..7ef2931732 100644 --- a/pkg/schemadsl/parser/parser_test.go +++ b/pkg/schemadsl/parser/parser_test.go @@ -130,6 +130,20 @@ func TestParser(t *testing.T) { {"invalid use", "invaliduse"}, {"use after definition", "useafterdef"}, {"invalid use expiration test", "invaliduseexpiration"}, + {"use typechecking test", "use_typechecking"}, + {"permission type annotation test", "permission_type_annotation"}, + {"permission mixed annotations test", "permission_mixed_annotations"}, + {"permission multiple types test", "permission_multiple_types"}, + {"permission mixed single multiple test", "permission_mixed_single_multiple"}, + {"permission edge cases test", "permission_edge_cases"}, + {"permission type annotation empty after colon test", "permission_type_annotation_empty_after_colon"}, + {"permission type annotation pipe no type before test", "permission_type_annotation_pipe_no_type_before"}, + {"permission type annotation trailing pipe no type after test", "permission_type_annotation_trailing_pipe_no_type_after"}, + {"permission type annotation double colon test", "permission_type_annotation_double_colon"}, + {"permission type annotation newline after colon test", "permission_type_annotation_newline_after_colon"}, + {"permission type annotation just pipe test", "permission_type_annotation_just_pipe"}, + {"deprecated relation test", "deprecation"}, + {"invalid deprecated relation test", "invalid-deprecation"}, } for _, test := range parserTests { diff --git a/pkg/schemadsl/parser/tests/deprecation.zed b/pkg/schemadsl/parser/tests/deprecation.zed new file mode 100644 index 0000000000..4b3206b954 --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecation.zed @@ -0,0 +1,10 @@ +definition deprecated_relation { + + @deprecated(warn) + relation writer: user + + @deprecated(error) + relation reader: user +} + +definition user {} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/deprecation.zed.expected b/pkg/schemadsl/parser/tests/deprecation.zed.expected new file mode 100644 index 0000000000..2dd10514a8 --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecation.zed.expected @@ -0,0 +1,58 @@ +NodeTypeFile + end-rune = 152 + input-source = deprecated relation test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = deprecated_relation + end-rune = 132 + input-source = deprecated relation test + start-rune = 0 + child-node => + NodeTypeDeprecated + deprecated-relation = warn + end-rune = 54 + input-source = deprecated relation test + start-rune = 38 + NodeTypeRelation + end-rune = 80 + input-source = deprecated relation test + relation-name = writer + start-rune = 60 + allowed-types => + NodeTypeTypeReference + end-rune = 80 + input-source = deprecated relation test + start-rune = 77 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 80 + input-source = deprecated relation test + start-rune = 77 + type-name = user + NodeTypeDeprecated + deprecated-relation = error + end-rune = 104 + input-source = deprecated relation test + start-rune = 87 + NodeTypeRelation + end-rune = 130 + input-source = deprecated relation test + relation-name = reader + start-rune = 110 + allowed-types => + NodeTypeTypeReference + end-rune = 130 + input-source = deprecated relation test + start-rune = 127 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 130 + input-source = deprecated relation test + start-rune = 127 + type-name = user + NodeTypeDefinition + definition-name = user + end-rune = 152 + input-source = deprecated relation test + start-rune = 135 diff --git a/pkg/schemadsl/parser/tests/invalid-deprecation.zed b/pkg/schemadsl/parser/tests/invalid-deprecation.zed new file mode 100644 index 0000000000..24a730bdc6 --- /dev/null +++ b/pkg/schemadsl/parser/tests/invalid-deprecation.zed @@ -0,0 +1,6 @@ +definition deprecated_relation { + @deprecated() + relation reader: user +} + +definition user {} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected new file mode 100644 index 0000000000..ca8158875d --- /dev/null +++ b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected @@ -0,0 +1,34 @@ +NodeTypeFile + end-rune = 48 + input-source = invalid deprecated relation test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = deprecated_relation + end-rune = 48 + input-source = invalid deprecated relation test + start-rune = 0 + child-node => + NodeTypeDeprecated + end-rune = 48 + input-source = invalid deprecated relation test + start-rune = 37 + child-node => + NodeTypeError + end-rune = 48 + error-message = Expected identifier, found token TokenTypeRightParen + error-source = ) + input-source = invalid deprecated relation test + start-rune = 49 + NodeTypeError + end-rune = 48 + error-message = Expected end of statement or definition, found: TokenTypeRightParen + error-source = ) + input-source = invalid deprecated relation test + start-rune = 49 + NodeTypeError + end-rune = 48 + error-message = Unexpected token at root level: TokenTypeRightParen + error-source = ) + input-source = invalid deprecated relation test + start-rune = 49 diff --git a/proto/internal/core/v1/core.proto b/proto/internal/core/v1/core.proto index a393eed149..039b7331bb 100644 --- a/proto/internal/core/v1/core.proto +++ b/proto/internal/core/v1/core.proto @@ -206,6 +206,15 @@ message NamespaceDefinition { SourcePosition source_position = 4; } +/** + * DeprecationType is the type of deprecation for a relation. + */ +enum DeprecationType { + DEPRECATED_TYPE_UNSPECIFIED = 0; + DEPRECATED_TYPE_WARNING = 1; + DEPRECATED_TYPE_ERROR = 2; +} + /** * Relation represents the definition of a relation or permission under a namespace. */ @@ -233,6 +242,9 @@ message Relation { string aliasing_relation = 6; string canonical_cache_key = 7; + + /** deprecation_type is the type of deprecation for the relation */ + DeprecationType deprecation_type = 8; } /** @@ -420,6 +432,11 @@ message AllowedRelation { * required_expiration defines the required expiration on this relation. */ ExpirationTrait required_expiration = 7; + + /** + * deprecation_type defines the type of deprecation for this relation. + */ + DeprecationType deprecation_type = 8; } /** From de0cde6e997c14da5bbfb5d5a5895a4145df5ede Mon Sep 17 00:00:00 2001 From: Kartikay Date: Sat, 28 Jun 2025 00:41:54 +0530 Subject: [PATCH 2/6] use deprecation implementation and suggestions Signed-off-by: Kartikay --- .github/workflows/build-test.yaml | 2 +- .github/workflows/lint.yaml | 4 +- .github/workflows/nightly.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/security.yaml | 2 +- .github/workflows/wasm.yaml | 2 +- .golangci.yaml | 14 + Dockerfile | 10 +- Dockerfile.release | 6 +- TELEMETRY.md | 2 +- e2e/go.mod | 21 +- e2e/go.sum | 68 +- go.mod | 117 +-- go.sum | 188 ++-- internal/datasets/basesubjectset.go | 5 +- internal/datastore/common/changes.go | 9 +- internal/datastore/common/changes_test.go | 30 +- .../datastore/common/relationships_test.go | 2 +- internal/datastore/common/sql.go | 6 +- internal/datastore/crdb/debug.go | 2 +- internal/datastore/crdb/keys_test.go | 5 +- internal/datastore/crdb/options.go | 16 +- internal/datastore/crdb/options_test.go | 67 ++ internal/datastore/crdb/pool/balancer.go | 4 +- internal/datastore/crdb/reader.go | 13 +- internal/datastore/crdb/readwrite.go | 11 +- internal/datastore/crdb/schema/forcedindex.go | 31 + internal/datastore/crdb/schema/indexes.go | 114 +-- .../datastore/crdb/schema/indexes_test.go | 142 ++- internal/datastore/crdb/schema/indexutil.go | 240 +++++ .../datastore/crdb/schema/indexutil_test.go | 824 ++++++++++++++++++ internal/datastore/crdb/schema/schema.go | 2 +- internal/datastore/memdb/readonly.go | 2 +- internal/datastore/memdb/readwrite.go | 8 +- internal/datastore/mysql/datastore.go | 4 +- internal/datastore/mysql/debug.go | 2 +- internal/datastore/mysql/readwrite.go | 9 +- internal/datastore/postgres/common/pgx.go | 21 +- internal/datastore/postgres/debug.go | 2 +- internal/datastore/postgres/log_tracer.go | 2 +- .../datastore/postgres/migrations/driver.go | 1 + internal/datastore/postgres/postgres.go | 28 +- .../postgres/postgres_shared_test.go | 2 +- internal/datastore/postgres/postgres_test.go | 9 +- internal/datastore/postgres/readwrite.go | 10 +- internal/datastore/postgres/snapshot.go | 2 +- internal/datastore/postgres/strictreader.go | 6 +- .../datastore/postgres/strictreader_test.go | 2 +- internal/datastore/postgres/testutil.go | 6 +- internal/datastore/proxy/hedging_test.go | 36 +- internal/datastore/proxy/proxy_test/mock.go | 8 +- internal/datastore/revisions/optimized.go | 2 +- .../datastore/revisions/optimized_test.go | 4 +- internal/datastore/spanner/readwrite.go | 6 +- internal/datastore/spanner/spanner_test.go | 2 +- .../dispatch/graph/lookupsubjects_test.go | 10 +- internal/graph/check.go | 4 +- internal/graph/membershipset_test.go | 9 +- internal/lsp/lspdefs.go | 2 +- internal/lsp/testutil.go | 4 +- internal/middleware/chain.go | 8 +- internal/middleware/datastore/datastore.go | 4 +- internal/middleware/dispatcher/dispatcher.go | 4 +- .../handwrittenvalidation.go | 6 +- .../perfinsights/perfinsights_test.go | 14 +- internal/middleware/pertoken/pertoken.go | 4 +- internal/middleware/readonly/readonly.go | 4 +- .../servicespecific/servicespecific.go | 4 +- internal/namespace/canonicalization.go | 2 +- internal/namespace/caveats.go | 6 +- internal/relationships/validation.go | 5 +- .../integrationtesting/consistency_test.go | 21 +- .../consistencytestutil/accessibilityset.go | 5 +- internal/services/server.go | 1 + internal/services/shared/schema.go | 2 +- internal/services/v1/bulkcheck.go | 4 +- internal/services/v1/experimental.go | 8 +- internal/services/v1/experimental_test.go | 17 +- internal/services/v1/expreflection.go | 6 +- internal/services/v1/grouping_test.go | 5 +- internal/services/v1/hash_nonwasm.go | 5 +- internal/services/v1/hash_wasm.go | 6 +- internal/services/v1/permissions.go | 10 +- internal/services/v1/permissions_test.go | 17 +- internal/services/v1/reflectionapi.go | 6 +- internal/services/v1/relationships.go | 19 +- internal/services/v1/schema.go | 20 +- internal/services/v1/schema_test.go | 2 + internal/telemetry/reporter.go | 6 +- internal/testfixtures/generator.go | 2 +- internal/testserver/server.go | 1 + magefiles/alias.go | 2 +- magefiles/build.go | 14 +- magefiles/go.mod | 2 +- magefiles/go.sum | 4 +- pkg/cache/cache_otter.go | 75 +- pkg/caveats/context_hash.go | 5 +- pkg/caveats/structure_test.go | 5 +- pkg/caveats/types/ipaddress.go | 4 +- pkg/cmd/datastore/datastore.go | 2 +- pkg/cmd/serve.go | 1 + pkg/cmd/server/cacheconfig.go | 13 +- pkg/cmd/server/middleware.go | 4 +- pkg/cmd/server/middleware_test.go | 8 +- pkg/cmd/server/server.go | 32 +- pkg/cmd/server/zz_generated.options.go | 9 + pkg/cmd/testserver/testserver.go | 1 + pkg/cmd/util/util.go | 20 +- pkg/composableschemadsl/compiler/compiler.go | 4 +- pkg/composableschemadsl/compiler/node.go | 8 +- .../generator/generator.go | 6 +- .../input/sourcepositionmapper.go | 2 +- pkg/composableschemadsl/lexer/lex.go | 2 +- pkg/composableschemadsl/parser/parser.go | 7 +- pkg/composableschemadsl/parser/parser_impl.go | 4 +- pkg/composableschemadsl/parser/parser_test.go | 4 +- pkg/datastore/credentials.go | 5 +- pkg/datastore/test/caveat.go | 2 +- pkg/datastore/test/counters.go | 42 + pkg/datastore/test/datastore.go | 1 + pkg/datastore/test/pagination.go | 10 +- pkg/datastore/test/revisions.go | 4 +- pkg/datastore/test/transactions.go | 2 +- pkg/datastore/test/watch.go | 13 +- pkg/development/devcontext.go | 2 + pkg/diff/caveats/diff.go | 9 +- pkg/genutil/mapz/multimap.go | 11 +- pkg/genutil/mapz/set.go | 16 +- pkg/genutil/mapz/set_test.go | 159 +++- pkg/genutil/slicez/slicez.go | 41 + pkg/genutil/slicez/slicez_test.go | 282 ++++++ pkg/graph/walker.go | 8 +- pkg/middleware/consistency/consistency.go | 10 +- pkg/middleware/consistency/forcefull.go | 6 +- pkg/middleware/nodeid/nodeid.go | 4 +- pkg/namespace/metadata.go | 86 ++ pkg/namespace/metadata_test.go | 156 ++++ pkg/proto/impl/v1/impl.pb.go | 232 +++-- pkg/proto/impl/v1/impl.pb.validate.go | 129 +++ pkg/proto/impl/v1/impl_vtproto.pb.go | 241 +++++ pkg/releases/releases.go | 36 +- pkg/schema/errors.go | 8 + pkg/schema/reachabilitygraph.go | 11 +- pkg/schema/type_check_test.go | 117 +++ pkg/schema/typesystem_validation.go | 21 +- pkg/schemadsl/compiler/compiler.go | 18 +- pkg/schemadsl/compiler/node.go | 8 +- pkg/schemadsl/compiler/translator.go | 61 +- .../type_annotations_integration_test.go | 237 +++++ pkg/schemadsl/dslshape/dslshape.go | 20 +- .../dslshape/zz_generated.nodetype_string.go | 29 +- pkg/schemadsl/generator/generator.go | 20 +- pkg/schemadsl/generator/generator_test.go | 32 + pkg/schemadsl/input/sourcepositionmapper.go | 2 +- pkg/schemadsl/lexer/flaggablelexer_test.go | 6 + pkg/schemadsl/lexer/flags.go | 47 +- pkg/schemadsl/lexer/lex.go | 2 +- pkg/schemadsl/lexer/lex_def.go | 6 +- pkg/schemadsl/lexer/lex_test.go | 6 +- pkg/schemadsl/parser/parser.go | 83 +- pkg/schemadsl/parser/parser_impl.go | 4 +- pkg/schemadsl/parser/parser_test.go | 16 +- pkg/schemadsl/parser/tests/deprecation.zed | 2 + .../parser/tests/deprecation.zed.expected | 55 +- .../tests/invalid-deprecation.zed.expected | 2 +- .../parser/tests/invaliduse.zed.expected | 2 +- .../parser/tests/permission_edge_cases.zed | 18 + .../tests/permission_edge_cases.zed.expected | 183 ++++ .../tests/permission_mixed_annotations.zed | 7 + .../permission_mixed_annotations.zed.expected | 93 ++ .../permission_mixed_single_multiple.zed | 8 + ...mission_mixed_single_multiple.zed.expected | 119 +++ .../tests/permission_multiple_types.zed | 7 + .../permission_multiple_types.zed.expected | 108 +++ .../tests/permission_type_annotation.zed | 7 + .../permission_type_annotation.zed.expected | 93 ++ ...ermission_type_annotation_double_colon.zed | 4 + ..._type_annotation_double_colon.zed.expected | 69 ++ ...sion_type_annotation_empty_after_colon.zed | 4 + ..._annotation_empty_after_colon.zed.expected | 56 ++ .../permission_type_annotation_just_pipe.zed | 4 + ...ion_type_annotation_just_pipe.zed.expected | 69 ++ ...on_type_annotation_newline_after_colon.zed | 5 + ...nnotation_newline_after_colon.zed.expected | 56 ++ ...on_type_annotation_pipe_no_type_before.zed | 4 + ...nnotation_pipe_no_type_before.zed.expected | 69 ++ ...annotation_trailing_pipe_no_type_after.zed | 4 + ...n_trailing_pipe_no_type_after.zed.expected | 62 ++ .../parser/tests/use_typechecking.zed | 2 + .../tests/use_typechecking.zed.expected | 15 + pkg/spiceerrors/assert_off.go | 2 +- pkg/spiceerrors/assert_on.go | 2 +- pkg/testutil/require.go | 5 +- pkg/tuple/parsing.go | 4 +- proto/internal/impl/v1/impl.proto | 5 + tools.go | 17 - tools/analyzers/go.work.sum | 132 +++ 197 files changed, 5225 insertions(+), 958 deletions(-) create mode 100644 internal/datastore/crdb/options_test.go create mode 100644 internal/datastore/crdb/schema/forcedindex.go create mode 100644 internal/datastore/crdb/schema/indexutil.go create mode 100644 internal/datastore/crdb/schema/indexutil_test.go create mode 100644 pkg/genutil/slicez/slicez.go create mode 100644 pkg/genutil/slicez/slicez_test.go create mode 100644 pkg/schemadsl/compiler/type_annotations_integration_test.go create mode 100644 pkg/schemadsl/parser/tests/permission_edge_cases.zed create mode 100644 pkg/schemadsl/parser/tests/permission_edge_cases.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_mixed_annotations.zed create mode 100644 pkg/schemadsl/parser/tests/permission_mixed_annotations.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed create mode 100644 pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_multiple_types.zed create mode 100644 pkg/schemadsl/parser/tests/permission_multiple_types.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed.expected create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed create mode 100644 pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed.expected create mode 100644 pkg/schemadsl/parser/tests/use_typechecking.zed create mode 100644 pkg/schemadsl/parser/tests/use_typechecking.zed.expected delete mode 100644 tools.go diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 451934bbfb..6ab88e3fce 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -392,7 +392,7 @@ jobs: - uses: "authzed/actions/setup-go@391defc4658e3e4ac6e53ba66da5b90a3b3f80e2" # main - name: "Generate Protos" run: "go run mage.go gen:proto" - - uses: "chainguard-dev/actions/nodiff@ce51233d303aed2394a9976e7f5642fd2158f693" # main + - uses: "chainguard-dev/actions/nodiff@16e2fd6603a1c6a1fbc880fdbb922b2e8e2be3e7" # main with: path: "" fixup-command: "go run mage.go gen:proto" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 58747f43c4..0c862a82c7 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -32,7 +32,7 @@ jobs: - uses: "authzed/actions/setup-go@391defc4658e3e4ac6e53ba66da5b90a3b3f80e2" # main - name: "Lint Go" run: "go run mage.go lint:go" - - uses: "chainguard-dev/actions/nodiff@ce51233d303aed2394a9976e7f5642fd2158f693" # main + - uses: "chainguard-dev/actions/nodiff@16e2fd6603a1c6a1fbc880fdbb922b2e8e2be3e7" # main with: path: "" fixup-command: "go run mage.go lint:go" @@ -45,7 +45,7 @@ jobs: - uses: "authzed/actions/setup-go@391defc4658e3e4ac6e53ba66da5b90a3b3f80e2" # main - name: "Lint Everything Else" run: "go run mage.go lint:extra" - - uses: "chainguard-dev/actions/nodiff@ce51233d303aed2394a9976e7f5642fd2158f693" # main + - uses: "chainguard-dev/actions/nodiff@16e2fd6603a1c6a1fbc880fdbb922b2e8e2be3e7" # main with: path: "" fixup-command: "go run mage.go lint:extra" diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 73f5a6b977..497932fb81 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -28,7 +28,7 @@ jobs: github_token: "${{ secrets.GITHUB_TOKEN }}" dockerhub_token: "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" - uses: "docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392" # v3.6.0 - - uses: "docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2" # v3.10.0 + - uses: "docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435" # v3.11.1 - uses: "goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552" # v6.3.0 with: distribution: "goreleaser-pro" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 22837d12f4..1e264a9c98 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -37,7 +37,7 @@ jobs: github_token: "${{ secrets.GITHUB_TOKEN }}" dockerhub_token: "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" - uses: "docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392" # v3.6.0 - - uses: "docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2" # v3.10.0 + - uses: "docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435" # v3.11.1 - uses: "goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552" # v6.3.0 with: distribution: "goreleaser-pro" diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml index 86d7bddab2..db71562b2a 100644 --- a/.github/workflows/security.yaml +++ b/.github/workflows/security.yaml @@ -62,7 +62,7 @@ jobs: sudo snap install snapcraft --channel=8.x/stable --classic mkdir -p $HOME/.cache/snapcraft/download mkdir -p $HOME/.cache/snapcraft/stage-packages - - uses: "aquasecurity/trivy-action@26d71e622b84d103f86fb33a5a42c558e11f4ae0" # master + - uses: "aquasecurity/trivy-action@76071ef0d7ec797419534a183b498b4d6366cf37" # master with: scan-type: "fs" ignore-unfixed: true diff --git a/.github/workflows/wasm.yaml b/.github/workflows/wasm.yaml index ebe6af16fe..ab46e24a9f 100644 --- a/.github/workflows/wasm.yaml +++ b/.github/workflows/wasm.yaml @@ -18,7 +18,7 @@ jobs: - uses: "authzed/actions/setup-go@391defc4658e3e4ac6e53ba66da5b90a3b3f80e2" # main - name: "Build WASM" run: "go run mage.go build:wasm" - - uses: "shogo82148/actions-upload-release-asset@d22998fda4c1407f60d1ab48cd6fe67f360f34de" # v1.8.0 + - uses: "shogo82148/actions-upload-release-asset@610b1987249a69a79de9565777e112fb38f22436" # v1.8.1 with: upload_url: "${{ github.event.release.upload_url }}" asset_path: "dist/*" diff --git a/.golangci.yaml b/.golangci.yaml index 477ca3ca32..e183dc0920 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -6,6 +6,7 @@ linters: enable: - "bidichk" - "bodyclose" + - "depguard" - "errcheck" - "errname" - "errorlint" @@ -32,6 +33,12 @@ linters: - "whitespace" - "unused" settings: + depguard: + rules: + main: + deny: + - pkg: "k8s.io/utils/strings/slices$" + desc: "use github.com/samber/lo" staticcheck: checks: - "all" @@ -80,9 +87,16 @@ linters: formatters: enable: - "gci" + - "gofmt" - "gofumpt" - "goimports" settings: + gofmt: + rewrite-rules: + - pattern: "interface{}" + replacement: "any" + - pattern: "a[b:len(a)]" + replacement: "a[b:]" gci: sections: - "standard" diff --git a/Dockerfile b/Dockerfile index 1034b96195..480ab038b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,12 @@ -FROM golang:1.24.4-alpine3.21@sha256:17656bcdf9097d55d0028bef53f5a2789e9e49cda4eb31cd6f437f8a29f0754d AS spicedb-builder +# use `crane digest ` to get the multi-platform sha256 +FROM golang:1.24.4-alpine3.21@sha256:56a23791af0f77c87b049230ead03bd8c3ad41683415ea4595e84ce7eada121a AS spicedb-builder WORKDIR /go/src/app RUN apk update && apk add --no-cache git COPY . . RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg/mod CGO_ENABLED=0 go build -v ./cmd/... -FROM golang:1.24.4-alpine3.21@sha256:17656bcdf9097d55d0028bef53f5a2789e9e49cda4eb31cd6f437f8a29f0754d AS health-probe-builder +# use `crane digest ` to get the multi-platform sha256 +FROM golang:1.24.4-alpine3.21@sha256:56a23791af0f77c87b049230ead03bd8c3ad41683415ea4595e84ce7eada121a AS health-probe-builder WORKDIR /go/src/app RUN apk update && apk add --no-cache git RUN git clone https://github.com/authzed/grpc-health-probe.git @@ -12,8 +14,8 @@ WORKDIR /go/src/app/grpc-health-probe RUN git checkout master RUN CGO_ENABLED=0 go install -a -tags netgo -ldflags=-w -FROM cgr.dev/chainguard/static@sha256:1ff7590cbc50eaaa917c34b092de0720d307f67d6d795e4f749a0b80a2e95a2c -#COPY --from=ghcr.io/grpc-ecosystem/grpc-health-probe:v0.4.20 /ko-app/grpc-health-probe /usr/local/bin/grpc_health_probe +# use `crane digest ` to get the multi-platform sha256 +FROM cgr.dev/chainguard/static@sha256:092aad9f6448695b6e20333a8faa93fe3637bcf4e88aa804b8f01545eaf288bd COPY --from=health-probe-builder /go/bin/grpc-health-probe /bin/grpc_health_probe COPY --from=spicedb-builder /go/src/app/spicedb /usr/local/bin/spicedb ENV PATH="$PATH:/usr/local/bin" diff --git a/Dockerfile.release b/Dockerfile.release index b6bb021096..6535c3c578 100644 --- a/Dockerfile.release +++ b/Dockerfile.release @@ -1,5 +1,7 @@ # vim: syntax=dockerfile -FROM golang:1.24.4-alpine3.21@sha256:17656bcdf9097d55d0028bef53f5a2789e9e49cda4eb31cd6f437f8a29f0754d AS health-probe-builder +# use `crane digest ` to get the multi-platform sha256 +ARG BASE=cgr.dev/chainguard/static@sha256:092aad9f6448695b6e20333a8faa93fe3637bcf4e88aa804b8f01545eaf288bd +FROM golang:1.24.4-alpine3.21@sha256:56a23791af0f77c87b049230ead03bd8c3ad41683415ea4595e84ce7eada121a AS health-probe-builder WORKDIR /go/src/app RUN apk update && apk add --no-cache git RUN git clone https://github.com/authzed/grpc-health-probe.git @@ -7,7 +9,7 @@ WORKDIR /go/src/app/grpc-health-probe RUN git checkout master RUN CGO_ENABLED=0 go install -a -tags netgo -ldflags=-w -FROM cgr.dev/chainguard/static@sha256:1ff7590cbc50eaaa917c34b092de0720d307f67d6d795e4f749a0b80a2e95a2c +FROM $BASE COPY --from=health-probe-builder /go/bin/grpc-health-probe /usr/local/bin/grpc_health_probe COPY spicedb /usr/local/bin/spicedb ENV PATH="$PATH:/usr/local/bin" diff --git a/TELEMETRY.md b/TELEMETRY.md index 686ec54957..f5b87f0bcb 100644 --- a/TELEMETRY.md +++ b/TELEMETRY.md @@ -49,7 +49,7 @@ Histogram of cluster dispatches performed by the instance. - Cluster ID: unique identifier for a cluster's datastore - NodeID: unique identifier for the node, usually the hostname -### spicedb_logical_checks_total (Counter) +### spicedb_telemetry_logical_checks_total (Counter) Counter of the number of "logical" checks performed by this instance. A "logical" check is defined as the number of checks used for an operation, diff --git a/e2e/go.mod b/e2e/go.mod index 0c9fe2992c..4a0229521a 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -10,19 +10,20 @@ replace github.com/envoyproxy/go-control-plane => github.com/envoyproxy/go-contr replace github.com/authzed/spicedb => ../ require ( - github.com/authzed/authzed-go v1.4.0 + github.com/authzed/authzed-go v1.4.1 github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b github.com/authzed/spicedb v1.29.5 github.com/brianvoe/gofakeit/v6 v6.23.2 github.com/ecordell/optgen v0.0.10-0.20230609182709-018141bf9698 github.com/jackc/pgx/v5 v5.7.5 github.com/stretchr/testify v1.10.0 - golang.org/x/tools v0.32.0 + golang.org/x/tools v0.34.0 google.golang.org/grpc v1.73.0 mvdan.cc/gofumpt v0.8.0 ) require ( + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/authzed/cel-go v0.20.2 // indirect github.com/aws/aws-sdk-go-v2 v1.36.4 // indirect @@ -49,12 +50,12 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/go-errors/errors v1.5.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zerologr v1.2.3 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jzelinskie/stringz v0.0.3 // indirect @@ -69,15 +70,15 @@ require ( go.opentelemetry.io/otel v1.36.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect - golang.org/x/crypto v0.38.0 // indirect + golang.org/x/crypto v0.39.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/mod v0.25.0 // indirect - golang.org/x/net v0.40.0 // indirect - golang.org/x/sync v0.14.0 // indirect + golang.org/x/net v0.41.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect + golang.org/x/text v0.26.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/controller-runtime v0.21.0 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index c294645bb2..99e52b4d07 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -1,3 +1,5 @@ +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 h1:AUL6VF5YWL01j/1H/DQbPUSDkEwYqwVCNw7yhbpOxSQ= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg= @@ -50,8 +52,8 @@ cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJN cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= -cloud.google.com/go v0.121.0 h1:pgfwva8nGw7vivjZiRfrmglGWiCJBP+0OmDpenG/Fwg= -cloud.google.com/go v0.121.0/go.mod h1:rS7Kytwheu/y9buoDmu5EIpMMCI4Mb8ND4aeN4Vwj7Q= +cloud.google.com/go v0.121.2 h1:v2qQpN6Dx9x2NmwrqlesOt3Ys4ol5/lFZ6Mg1B7OJCg= +cloud.google.com/go v0.121.2/go.mod h1:nRFlrHq39MNVWu+zESP2PosMWA0ryJw8KUBZ2iZpxbw= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -363,8 +365,8 @@ cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -1376,8 +1378,8 @@ github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWM github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apache/thrift v0.17.0/go.mod h1:OLxhMRJxomX+1I/KUw03qoV3mMz16BwaKI+d4fPBx7Q= -github.com/authzed/authzed-go v1.4.0 h1:0LnVg/r38rJgbljBx0m9vWHvaHYEElMaomAXyEeaiI8= -github.com/authzed/authzed-go v1.4.0/go.mod h1:iW6QQWmTbgFfn4b6zPPzbgOUOSB93/or4VdQ+zLTjeY= +github.com/authzed/authzed-go v1.4.1 h1:46qqCeChXDi0l8UXR2ALfN+FGyvsR1zhA4MEYRCisZM= +github.com/authzed/authzed-go v1.4.1/go.mod h1:9sxRm+gviaW4x9LBXsgH+PTU2K0YmDNu3/MeqkmI+w0= github.com/authzed/cel-go v0.20.2 h1:GlmLecGry7Z8HU0k+hmaHHUV05ZHrsFxduXHtIePvck= github.com/authzed/cel-go v0.20.2/go.mod h1:pJHVFWbqUHV1J+klQoZubdKswlbxcsbojda3mye9kiU= github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b h1:wbh8IK+aMLTCey9sZasO7b6BWLAJnHHvb79fvWCXwxw= @@ -1534,8 +1536,8 @@ github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zerologr v1.2.3 h1:up5N9vcH9Xck3jJkXzgyOxozT14R47IyDODz8LM1KSs= @@ -1691,8 +1693,8 @@ github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5i github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0= +github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -1701,8 +1703,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4z github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 h1:+epNPbD5EqgpEMm5wrl4Hqts3jZt8+kYaqUisuuIGTk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= @@ -1834,16 +1836,14 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY= -github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc= +github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI= +github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/samber/slog-common v0.18.1 h1:c0EipD/nVY9HG5shgm/XAs67mgpWDMF+MmtptdJNCkQ= github.com/samber/slog-common v0.18.1/go.mod h1:QNZiNGKakvrfbJ2YglQXLCZauzkI9xZBjOhWFKS3IKk= github.com/samber/slog-zerolog/v2 v2.7.3 h1:/MkPDl/tJhijN2GvB1MWwBn2FU8RiL3rQ8gpXkQm2EY= github.com/samber/slog-zerolog/v2 v2.7.3/go.mod h1:oWU7WHof4Xp8VguiNO02r1a4VzkgoOyOZhY5CuRke60= github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= -github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE= -github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1975,8 +1975,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2118,8 +2118,8 @@ golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2184,8 +2184,8 @@ golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2334,8 +2334,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2415,8 +2415,8 @@ golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2508,8 +2508,8 @@ google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYl google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= -google.golang.org/api v0.232.0 h1:qGnmaIMf7KcuwHOlF3mERVzChloDYwRfOJOrHt8YC3I= -google.golang.org/api v0.232.0/go.mod h1:p9QCfBWZk1IJETUdbTKloR5ToFdKbYh2fkjsUL6vNoY= +google.golang.org/api v0.236.0 h1:CAiEiDVtO4D/Qja2IA9VzlFrgPnK3XVMmRoJZlSWbc0= +google.golang.org/api v0.236.0/go.mod h1:X1WF9CU2oTc+Jml1tiIxGmWFK/UZezdqEu09gcxZAj4= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2677,8 +2677,8 @@ google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqt google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= +google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= +google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= @@ -2709,8 +2709,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go. google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0= -google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw= @@ -2755,8 +2755,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/go.mod b/go.mod index 8b76862a8c..169ce29c19 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,15 @@ go 1.24.0 // upgrade Kubernetes to a version that uses a newer version of `cel-go`. require github.com/authzed/cel-go v0.20.2 +// Bring https://github.com/fsnotify/fsnotify/pull/650 +replace github.com/fsnotify/fsnotify => github.com/fsnotify/fsnotify v1.9.0 + // See: https://github.com/envoyproxy/go-control-plane/issues/1074 replace github.com/envoyproxy/go-control-plane => github.com/envoyproxy/go-control-plane v0.13.2 -replace github.com/influxdata/tdigest => github.com/hdrodz/tdigest v0.0.0-20230422191141-29913c04928d +// This repository contains additional fixes that are not upstream. +// https://github.com/hdrodz/tdigest/commits/fix-oob-access +replace github.com/influxdata/tdigest => github.com/hdrodz/tdigest v0.0.0-20230422191729-3d4528d8cfec require ( buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.36.6-20250320161912-af2aab87b1b3.1 @@ -21,7 +26,7 @@ require ( github.com/Masterminds/semver v1.5.0 github.com/Masterminds/squirrel v1.5.4 github.com/Yiling-J/theine-go v0.6.1 - github.com/authzed/authzed-go v1.4.0 + github.com/authzed/authzed-go v1.4.1 github.com/authzed/consistent v0.1.0 github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b github.com/aws/aws-sdk-go-v2 v1.36.4 @@ -29,6 +34,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.12 github.com/benbjohnson/clock v1.3.5 github.com/bits-and-blooms/bloom/v3 v3.7.0 + github.com/caio/go-tdigest/v4 v4.0.1 github.com/ccoveille/go-safecast v1.6.1 github.com/cenkalti/backoff/v4 v4.3.0 github.com/cespare/xxhash/v2 v2.3.0 @@ -46,15 +52,13 @@ require ( github.com/go-errors/errors v1.5.1 github.com/go-logr/zerologr v1.2.3 github.com/go-sql-driver/mysql v1.9.2 - github.com/gogo/protobuf v1.3.2 github.com/golang/snappy v1.0.0 github.com/google/go-cmp v0.7.0 - github.com/google/go-github/v43 v43.0.0 github.com/google/uuid v1.6.0 github.com/gosimple/slug v1.15.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 github.com/hashicorp/go-memdb v1.3.5 github.com/influxdata/tdigest v0.0.1 github.com/jackc/pgio v1.0.0 @@ -65,9 +69,8 @@ require ( github.com/jzelinskie/stringz v0.0.3 github.com/lithammer/fuzzysearch v1.1.8 github.com/lthibault/jitterbug v2.0.0+incompatible - github.com/magefile/mage v1.15.0 github.com/mattn/go-isatty v0.0.20 - github.com/maypok86/otter v1.2.4 + github.com/maypok86/otter/v2 v2.1.0 github.com/mostynb/go-grpc-compression v1.2.3 github.com/muesli/mango-cobra v1.2.0 github.com/muesli/roff v0.1.0 @@ -82,10 +85,8 @@ require ( github.com/rs/cors v1.11.1 github.com/rs/xid v1.6.0 github.com/rs/zerolog v1.34.0 - github.com/samber/lo v1.50.0 github.com/samber/slog-zerolog/v2 v2.7.3 github.com/schollz/progressbar/v3 v3.18.0 - github.com/scylladb/go-set v1.0.2 github.com/sean-/sysexits v1.0.0 github.com/sercand/kuberesolver/v5 v5.1.1 github.com/shopspring/decimal v1.4.0 @@ -104,12 +105,11 @@ require ( go.uber.org/goleak v1.3.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/mod v0.25.0 - golang.org/x/sync v0.14.0 + golang.org/x/sync v0.15.0 golang.org/x/time v0.12.0 - golang.org/x/vuln v1.1.4 - google.golang.org/api v0.232.0 - google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 + google.golang.org/api v0.236.0 + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 google.golang.org/grpc v1.73.0 google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v2 v2.4.0 @@ -118,30 +118,39 @@ require ( sigs.k8s.io/controller-runtime v0.21.0 ) -require ( - github.com/caio/go-tdigest/v4 v4.0.1 - github.com/golangci/golangci-lint/v2 v2.1.6 - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 -) +require golang.org/x/vuln v1.1.4 // indirect -require sigs.k8s.io/randfill v1.0.0 // indirect +// Most tools are managed in the magefiles module. These tools are just +// the ones that can't run from a submodule at the moment. +tool ( + // optgen is used directly in go:generate directives. + github.com/ecordell/optgen + // golangci-lint always uses the current directory's go.mod. + github.com/golangci/golangci-lint/v2/cmd/golangci-lint + // support running mage with go run mage.go + github.com/magefile/mage/mage + // vulncheck always uses the current directory's go.mod. + golang.org/x/vuln/cmd/govulncheck +) require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 // indirect buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.36.6-20240617172848-e1dbca2775a7.1 // indirect cel.dev/expr v0.23.1 // indirect - cloud.google.com/go v0.121.0 // indirect + cloud.google.com/go v0.121.2 // indirect cloud.google.com/go/auth v0.16.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/compute/metadata v0.7.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect + github.com/Abirdcfly/dupword v0.1.6 // indirect github.com/Antonboom/errname v1.1.0 // indirect github.com/Antonboom/nilnil v1.1.0 // indirect github.com/Antonboom/testifylint v1.6.1 // indirect @@ -155,7 +164,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.17.2 // indirect + github.com/alecthomas/chroma/v2 v2.18.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect @@ -187,7 +196,7 @@ require ( github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/catenacyber/perfsprint v0.9.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect @@ -195,7 +204,6 @@ require ( github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/chavacava/garif v0.1.0 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect github.com/containerd/continuity v0.4.5 // indirect @@ -210,7 +218,6 @@ require ( github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dolthub/maphash v0.1.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect github.com/fatih/structtag v1.2.0 // indirect @@ -219,13 +226,12 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/gammazero/deque v0.2.1 // indirect github.com/ghostiam/protogetter v0.3.15 // indirect github.com/go-critic/go-critic v0.13.0 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -237,25 +243,26 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.3.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.12.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.0 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect + github.com/golangci/golangci-lint/v2 v2.1.6 // indirect github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect github.com/google/gnostic-models v0.6.9 // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/googleapis/gax-go/v2 v2.14.2 // indirect github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gosimple/unidecode v1.0.1 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect @@ -274,9 +281,9 @@ require ( github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/jgautheron/goconst v1.8.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -291,23 +298,24 @@ require ( github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.3 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect + github.com/ldez/exptostd v0.4.4 // indirect + github.com/ldez/gomoddirectives v0.7.0 // indirect github.com/ldez/grignotin v0.9.0 // indirect github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.3 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect + github.com/magefile/mage v1.15.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/manuelarte/funcorder v0.2.1 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mgechev/revive v1.9.0 // indirect + github.com/mgechev/revive v1.10.0 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -325,7 +333,6 @@ require ( github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect github.com/nunnatsa/ginkgolinter v0.19.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.2.3 // indirect @@ -347,15 +354,16 @@ require ( github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/samber/lo v1.51.0 // indirect github.com/samber/slog-common v0.18.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.3 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.4 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.3.4 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.14.0 // indirect @@ -376,7 +384,7 @@ require ( github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect + github.com/uudashr/iface v1.4.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -405,16 +413,17 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.38.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/crypto v0.39.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 // indirect golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.25.0 // indirect - golang.org/x/tools v0.32.0 // indirect - google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect + golang.org/x/text v0.26.0 // indirect + golang.org/x/tools v0.34.0 // indirect + google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -424,9 +433,11 @@ require ( k8s.io/client-go v0.33.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 mvdan.cc/gofumpt v0.8.0 // indirect mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.5.0 // indirect ) diff --git a/go.sum b/go.sum index a09adb0cff..280a9ed567 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ 4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 h1:AUL6VF5YWL01j/1H/DQbPUSDkEwYqwVCNw7yhbpOxSQ= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.36.6-20240617172848-e1dbca2775a7.1 h1:DHj/fDjM+Ij3KR1IpFs6WdNcCtD4+Th3tEWyx3Xgs14= buf.build/gen/go/gogo/protobuf/protocolbuffers/go v1.36.6-20240617172848-e1dbca2775a7.1/go.mod h1:iCb72C37pWGhjKDeq9IbcMqVJAnXXHs5tEjiePfouhk= buf.build/gen/go/prometheus/prometheus/protocolbuffers/go v1.36.6-20250320161912-af2aab87b1b3.1 h1:EuFqAB/kfs/jh9aUGcvBjcxtU89wnXwsuQfcwGX1rhE= @@ -58,8 +60,8 @@ cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJN cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= -cloud.google.com/go v0.121.0 h1:pgfwva8nGw7vivjZiRfrmglGWiCJBP+0OmDpenG/Fwg= -cloud.google.com/go v0.121.0/go.mod h1:rS7Kytwheu/y9buoDmu5EIpMMCI4Mb8ND4aeN4Vwj7Q= +cloud.google.com/go v0.121.2 h1:v2qQpN6Dx9x2NmwrqlesOt3Ys4ol5/lFZ6Mg1B7OJCg= +cloud.google.com/go v0.121.2/go.mod h1:nRFlrHq39MNVWu+zESP2PosMWA0ryJw8KUBZ2iZpxbw= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -370,8 +372,8 @@ cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -1341,6 +1343,8 @@ cloud.google.com/go/workflows v1.12.1/go.mod h1:5A95OhD/edtOhQd/O741NSfIMezNTbCw cloud.google.com/go/workflows v1.12.2/go.mod h1:+OmBIgNqYJPVggnMo9nqmizW0qEXHhmnAzK/CnBqsHc= cloud.google.com/go/workflows v1.12.3/go.mod h1:fmOUeeqEwPzIU81foMjTRQIdwQHADi/vEr1cx9R1m5g= cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= @@ -1352,8 +1356,8 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= +github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= +github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= @@ -1402,8 +1406,8 @@ github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhk github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= -github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.18.0 h1:6h53Q4hW83SuF+jcsp7CVhLsMozzvQvO8HBbKQW+gn4= +github.com/alecthomas/chroma/v2 v2.18.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y= @@ -1441,8 +1445,8 @@ github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8ger github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= -github.com/authzed/authzed-go v1.4.0 h1:0LnVg/r38rJgbljBx0m9vWHvaHYEElMaomAXyEeaiI8= -github.com/authzed/authzed-go v1.4.0/go.mod h1:iW6QQWmTbgFfn4b6zPPzbgOUOSB93/or4VdQ+zLTjeY= +github.com/authzed/authzed-go v1.4.1 h1:46qqCeChXDi0l8UXR2ALfN+FGyvsR1zhA4MEYRCisZM= +github.com/authzed/authzed-go v1.4.1/go.mod h1:9sxRm+gviaW4x9LBXsgH+PTU2K0YmDNu3/MeqkmI+w0= github.com/authzed/cel-go v0.20.2 h1:GlmLecGry7Z8HU0k+hmaHHUV05ZHrsFxduXHtIePvck= github.com/authzed/cel-go v0.20.2/go.mod h1:pJHVFWbqUHV1J+klQoZubdKswlbxcsbojda3mye9kiU= github.com/authzed/consistent v0.1.0 h1:tlh1wvKoRbjRhMm2P+X5WQQyR54SRoS4MyjLOg17Mp8= @@ -1512,8 +1516,8 @@ github.com/caio/go-tdigest/v4 v4.0.1 h1:sx4ZxjmIEcLROUPs2j1BGe2WhOtHD6VSe6NNbBdK github.com/caio/go-tdigest/v4 v4.0.1/go.mod h1:Wsa+f0EZnV2gShdj1adgl0tQSoXRxtM0QioTgukFw8U= github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/ccoveille/go-safecast v1.6.1 h1:Nb9WMDR8PqhnKCVs2sCB+OqhohwO5qaXtCviZkIff5Q= github.com/ccoveille/go-safecast v1.6.1/go.mod h1:QqwNjxQ7DAqY0C721OIO9InMk9zCwcsO7tnRuHytad8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -1541,8 +1545,6 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -1612,8 +1614,6 @@ github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ= -github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -1650,8 +1650,6 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= -github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -1662,14 +1660,12 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= -github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU= github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= @@ -1703,8 +1699,8 @@ github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -1751,8 +1747,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= +github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -1824,10 +1820,10 @@ github.com/golangci/golangci-lint/v2 v2.1.6 h1:LXqShFfAGM5BDzEOWD2SL1IzJAgUOqES/ github.com/golangci/golangci-lint/v2 v2.1.6/go.mod h1:EPj+fgv4TeeBq3TcqaKZb3vkiV5dP4hHHKhXhEhzci8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= @@ -1860,12 +1856,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN 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/go-github/v43 v43.0.0 h1:y+GL7LIsAIF2NZlJ46ZoC/D1W1ivZasT0lnWHMYPZ+U= -github.com/google/go-github/v43 v43.0.0/go.mod h1:ZkTvvmCXBvsfPpTHXnH/d2hP9Y0cTbvN9kr5xqyXOIc= github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -1888,8 +1880,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= @@ -1934,8 +1926,8 @@ github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5i github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0= +github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= @@ -1968,8 +1960,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4z github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 h1:+epNPbD5EqgpEMm5wrl4Hqts3jZt8+kYaqUisuuIGTk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= @@ -1990,8 +1982,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hdrodz/tdigest v0.0.0-20230422191141-29913c04928d h1:DyoNvh/YzB6VgSmMqTsqEhN2m+GOI/9IL6C1RaKj7Fs= -github.com/hdrodz/tdigest v0.0.0-20230422191141-29913c04928d/go.mod h1:IzZaRqwTPmLpuU5m987B5SPuMTiybWYcuygkufhWL8U= +github.com/hdrodz/tdigest v0.0.0-20230422191729-3d4528d8cfec h1:SXlywBJFmy0BQ0tYAhEQUxtiBCF6IrGPUqTtZw+XqmI= +github.com/hdrodz/tdigest v0.0.0-20230422191729-3d4528d8cfec/go.mod h1:IzZaRqwTPmLpuU5m987B5SPuMTiybWYcuygkufhWL8U= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -2013,12 +2005,12 @@ github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jgautheron/goconst v1.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo414= -github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -2087,16 +2079,16 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= -github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= +github.com/ldez/exptostd v0.4.4 h1:58AtQjnLcT/tI5W/1KU7xE/O7zW9RAWB6c/ScQAnfus= +github.com/ldez/exptostd v0.4.4/go.mod h1:QfdzPw6oHjFVdNV7ILoPu5sw3OZ3OG1JS0I5JN3J4Js= +github.com/ldez/gomoddirectives v0.7.0 h1:EOx8Dd56BZYSez11LVgdj025lKwlP0/E5OLSl9HDwsY= +github.com/ldez/gomoddirectives v0.7.0/go.mod h1:wR4v8MN9J8kcwvrkzrx6sC9xe9Cp68gWYCsda5xvyGc= github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= -github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353 h1:X/79QL0b4YJVO5+OsPH9rF2u428CIrGL/jLmPsoOQQ4= github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= @@ -2122,8 +2114,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/manuelarte/funcorder v0.2.1 h1:7QJsw3qhljoZ5rH0xapIvjw31EcQeFbF31/7kQ/xS34= -github.com/manuelarte/funcorder v0.2.1/go.mod h1:BQQ0yW57+PF9ZpjpeJDKOffEsQbxDFKW8F8zSMe/Zd0= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= @@ -2144,7 +2136,6 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -2153,10 +2144,10 @@ github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/maypok86/otter v1.2.4 h1:HhW1Pq6VdJkmWwcZZq19BlEQkHtI8xgsQzBVXJU0nfc= -github.com/maypok86/otter v1.2.4/go.mod h1:mKLfoI7v1HOmQMwFgX4QkRk23mX6ge3RDvjdHOWG4R4= -github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= -github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= +github.com/maypok86/otter/v2 v2.1.0 h1:H+FO9NtLuSWYUlIUQ/kT6VNEpWSIF4w4GZJRDhxYb7k= +github.com/maypok86/otter/v2 v2.1.0/go.mod h1:jX2xEKz9PrNVbDqnk8JUuOt5kURK8h7jd1kDYI5QsZk= +github.com/mgechev/revive v1.10.0 h1:x2oJsd7yrDp0mC6IgZqSKBTjSUC9Zk5Ob2WfBwZic2I= +github.com/mgechev/revive v1.10.0/go.mod h1:1MRO9zUV7Yukhqh/nGRKSaw6xC5XDzPWPja5GMPWoSE= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= @@ -2206,12 +2197,10 @@ github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -2334,28 +2323,26 @@ github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9c github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY= -github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc= +github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI= +github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/samber/slog-common v0.18.1 h1:c0EipD/nVY9HG5shgm/XAs67mgpWDMF+MmtptdJNCkQ= github.com/samber/slog-common v0.18.1/go.mod h1:QNZiNGKakvrfbJ2YglQXLCZauzkI9xZBjOhWFKS3IKk= github.com/samber/slog-zerolog/v2 v2.7.3 h1:/MkPDl/tJhijN2GvB1MWwBn2FU8RiL3rQ8gpXkQm2EY= github.com/samber/slog-zerolog/v2 v2.7.3/go.mod h1:oWU7WHof4Xp8VguiNO02r1a4VzkgoOyOZhY5CuRke60= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= -github.com/scylladb/go-set v1.0.2 h1:SkvlMCKhP0wyyct6j+0IHJkBkSZL+TDzZ4E7f7BCcRE= -github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/sysexits v1.0.0 h1:FLf1xcUTBzTqUI1Nc77UwYPcoWgDM09lyMTt8+QCpbE= github.com/sean-/sysexits v1.0.0/go.mod h1:yRz1mwglmPHOlAm3+WGr40EV8qFg4hn8GE9MoNwoecg= -github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= -github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/securego/gosec/v2 v2.22.4 h1:21VdNGcKicFSv6rUDBc0cEtEl7lWyCKZxKIm0iwvrIM= +github.com/securego/gosec/v2 v2.22.4/go.mod h1:ww5Yie7KJ3AH8XZQTletkW5zOmIse6FACs/Ys8VR3qE= github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY= github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= @@ -2371,8 +2358,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.3.4 h1:ZeiM4rEeFTFSie/G5/HD9lHiMpQg/L4fnilaNmFQ2/A= +github.com/sonatard/noctx v0.3.4/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= @@ -2452,8 +2439,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/uudashr/iface v1.4.0 h1:ImZ+1oEJPXvjap7nK0md7gA9RRH7PMp4vliaLkJ2+cg= +github.com/uudashr/iface v1.4.0/go.mod h1:i/H4cfRMPe0izticV8Yz0g6/zcsh5xXlvthrdh1kqcY= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -2578,6 +2565,10 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -2607,8 +2598,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2758,8 +2749,8 @@ golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2824,8 +2815,8 @@ golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2989,8 +2980,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -3078,8 +3069,8 @@ golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -3176,8 +3167,8 @@ google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYl google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= -google.golang.org/api v0.232.0 h1:qGnmaIMf7KcuwHOlF3mERVzChloDYwRfOJOrHt8YC3I= -google.golang.org/api v0.232.0/go.mod h1:p9QCfBWZk1IJETUdbTKloR5ToFdKbYh2fkjsUL6vNoY= +google.golang.org/api v0.236.0 h1:CAiEiDVtO4D/Qja2IA9VzlFrgPnK3XVMmRoJZlSWbc0= +google.golang.org/api v0.236.0/go.mod h1:X1WF9CU2oTc+Jml1tiIxGmWFK/UZezdqEu09gcxZAj4= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -3345,8 +3336,8 @@ google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqt google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE= -google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE= +google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= +google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= @@ -3377,8 +3368,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go. google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0= -google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw= @@ -3423,8 +3414,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -3634,5 +3625,6 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= diff --git a/internal/datasets/basesubjectset.go b/internal/datasets/basesubjectset.go index 80ab6668d4..aedc36c114 100644 --- a/internal/datasets/basesubjectset.go +++ b/internal/datasets/basesubjectset.go @@ -1,7 +1,8 @@ package datasets import ( - "golang.org/x/exp/maps" + "maps" + "slices" "github.com/authzed/spicedb/internal/caveats" core "github.com/authzed/spicedb/pkg/proto/core/v1" @@ -257,7 +258,7 @@ func (bss BaseSubjectSet[T]) IsEmpty() bool { // AsSlice returns the contents of the subject set as a slice of found subjects. func (bss BaseSubjectSet[T]) AsSlice() []T { - values := maps.Values(bss.concrete) + values := slices.Collect(maps.Values(bss.concrete)) if wildcard, ok := bss.wildcard.get(); ok { values = append(values, wildcard) } diff --git a/internal/datastore/common/changes.go b/internal/datastore/common/changes.go index e2a0ec1322..ebb19bfe5b 100644 --- a/internal/datastore/common/changes.go +++ b/internal/datastore/common/changes.go @@ -2,10 +2,11 @@ package common import ( "context" + "maps" + "slices" "sort" "github.com/ccoveille/go-safecast" - "golang.org/x/exp/maps" "google.golang.org/protobuf/types/known/structpb" log "github.com/authzed/spicedb/internal/logging" @@ -327,9 +328,9 @@ func (ch *Changes[R, K]) revisionChanges(lessThanFunc func(lhs, rhs K) bool, bou for _, rel := range revisionChangeRecord.relDeletes { changes[i].RelationshipChanges = append(changes[i].RelationshipChanges, tuple.Delete(rel)) } - changes[i].ChangedDefinitions = maps.Values(revisionChangeRecord.definitionsChanged) - changes[i].DeletedNamespaces = maps.Keys(revisionChangeRecord.namespacesDeleted) - changes[i].DeletedCaveats = maps.Keys(revisionChangeRecord.caveatsDeleted) + changes[i].ChangedDefinitions = slices.Collect(maps.Values(revisionChangeRecord.definitionsChanged)) + changes[i].DeletedNamespaces = slices.Collect(maps.Keys(revisionChangeRecord.namespacesDeleted)) + changes[i].DeletedCaveats = slices.Collect(maps.Keys(revisionChangeRecord.caveatsDeleted)) if len(revisionChangeRecord.metadata) > 0 { metadata, err := structpb.NewStruct(revisionChangeRecord.metadata) diff --git a/internal/datastore/common/changes_test.go b/internal/datastore/common/changes_test.go index 39f9035681..765d6cfd54 100644 --- a/internal/datastore/common/changes_test.go +++ b/internal/datastore/common/changes_test.go @@ -443,14 +443,14 @@ func TestFilterAndRemoveRevisionChanges(t *testing.T) { { Revision: rev1, DeletedNamespaces: []string{"deletedns1"}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, { Revision: rev2, DeletedNamespaces: []string{"deletedns2"}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, }, results) @@ -462,8 +462,8 @@ func TestFilterAndRemoveRevisionChanges(t *testing.T) { { Revision: rev3, DeletedNamespaces: []string{"deletedns3"}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, }, remaining) @@ -506,18 +506,18 @@ func TestHLCOrdering(t *testing.T) { RelationshipChanges: []tuple.RelationshipUpdate{ tuple.Touch(tuple.MustParse("document:foo#viewer@user:tom")), }, - DeletedNamespaces: []string{}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedNamespaces: nil, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, { Revision: rev1, RelationshipChanges: []tuple.RelationshipUpdate{ tuple.Delete(tuple.MustParse("document:foo#viewer@user:tom")), }, - DeletedNamespaces: []string{}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedNamespaces: nil, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, }, remaining) } @@ -564,9 +564,9 @@ func TestHLCSameRevision(t *testing.T) { { Revision: rev0, RelationshipChanges: expected, - DeletedNamespaces: []string{}, - DeletedCaveats: []string{}, - ChangedDefinitions: []datastore.SchemaDefinition{}, + DeletedNamespaces: nil, + DeletedCaveats: nil, + ChangedDefinitions: nil, }, }, remaining) } diff --git a/internal/datastore/common/relationships_test.go b/internal/datastore/common/relationships_test.go index f11995d905..395a6bcb6f 100644 --- a/internal/datastore/common/relationships_test.go +++ b/internal/datastore/common/relationships_test.go @@ -16,7 +16,7 @@ type fakeQuerier struct { queriesRun []string } -func (fq *fakeQuerier) QueryFunc(ctx context.Context, f func(context.Context, Rows) error, sql string, args ...interface{}) error { +func (fq *fakeQuerier) QueryFunc(ctx context.Context, f func(context.Context, Rows) error, sql string, args ...any) error { fq.queriesRun = append(fq.queriesRun, sql) return nil } diff --git a/internal/datastore/common/sql.go b/internal/datastore/common/sql.go index d9b79789f0..12fbbab4ed 100644 --- a/internal/datastore/common/sql.go +++ b/internal/datastore/common/sql.go @@ -1,6 +1,7 @@ package common import ( + "cmp" "context" "fmt" "maps" @@ -9,7 +10,6 @@ import ( "time" sq "github.com/Masterminds/squirrel" - "github.com/jzelinskie/stringz" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -618,7 +618,7 @@ func (sqf SchemaQueryFilterer) FilterWithSubjectsSelectors(selectors ...datastor } else { orClause := sq.Or{} for _, relationName := range relations { - dsRelationName := stringz.DefaultEmpty(relationName, datastore.Ellipsis) + dsRelationName := cmp.Or(relationName, datastore.Ellipsis) orClause = append(orClause, sq.Eq{sqf.schema.ColUsersetRelation: dsRelationName}) sqf.recordColumnValue(sqf.schema.ColUsersetRelation, dsRelationName) } @@ -647,7 +647,7 @@ func (sqf SchemaQueryFilterer) FilterToSubjectFilter(filter *v1.SubjectFilter) S } if filter.OptionalRelation != nil { - dsRelationName := stringz.DefaultEmpty(filter.OptionalRelation.Relation, datastore.Ellipsis) + dsRelationName := cmp.Or(filter.OptionalRelation.Relation, datastore.Ellipsis) sqf.queryBuilder = sqf.queryBuilder.Where(sq.Eq{sqf.schema.ColUsersetRelation: dsRelationName}) sqf.recordColumnValue(sqf.schema.ColUsersetRelation, datastore.Ellipsis) diff --git a/internal/datastore/crdb/debug.go b/internal/datastore/crdb/debug.go index fd7c15e2ab..437ddf0122 100644 --- a/internal/datastore/crdb/debug.go +++ b/internal/datastore/crdb/debug.go @@ -15,7 +15,7 @@ func (cds *crdbDatastore) PreExplainStatements() []string { return nil } -func (cds *crdbDatastore) BuildExplainQuery(sql string, args []interface{}) (string, []any, error) { +func (cds *crdbDatastore) BuildExplainQuery(sql string, args []any) (string, []any, error) { return "EXPLAIN " + sql, args, nil } diff --git a/internal/datastore/crdb/keys_test.go b/internal/datastore/crdb/keys_test.go index 95b7410987..d2b3647bd5 100644 --- a/internal/datastore/crdb/keys_test.go +++ b/internal/datastore/crdb/keys_test.go @@ -2,7 +2,9 @@ package crdb import ( "context" + "maps" "net" + "slices" "sort" "strings" "testing" @@ -10,7 +12,6 @@ import ( "github.com/dustin/go-humanize" "github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" @@ -75,7 +76,7 @@ type testServer struct { } func (t testServer) Ping(ctx context.Context, _ *testpb.PingRequest) (*testpb.PingResponse, error) { - keys := maps.Keys(overlapKeysFromContext(ctx)) + keys := slices.Collect(maps.Keys(overlapKeysFromContext(ctx))) sort.Strings(keys) return &testpb.PingResponse{Value: strings.Join(keys, ",")}, nil } diff --git a/internal/datastore/crdb/options.go b/internal/datastore/crdb/options.go index 9e8ce90ab4..bf85cddba8 100644 --- a/internal/datastore/crdb/options.go +++ b/internal/datastore/crdb/options.go @@ -4,6 +4,8 @@ import ( "fmt" "time" + "k8s.io/utils/ptr" + "github.com/authzed/spicedb/internal/datastore/common" pgxcommon "github.com/authzed/spicedb/internal/datastore/postgres/common" log "github.com/authzed/spicedb/internal/logging" @@ -111,6 +113,16 @@ func generateConfig(options []Option) (crdbOptions, error) { log.Warn().Msg("filterMaximumIDCount not set, defaulting to 100") } + // Default to 30m jitter for CockroachDB database pools when not explicitly set + // or when explicitly set to zero (which happens when using pkg/cmd/datastore defaults) + if computed.readPoolOpts.ConnMaxLifetimeJitter == nil || *computed.readPoolOpts.ConnMaxLifetimeJitter == 0 { + computed.readPoolOpts.ConnMaxLifetimeJitter = ptr.To(30 * time.Minute) + } + + if computed.writePoolOpts.ConnMaxLifetimeJitter == nil || *computed.writePoolOpts.ConnMaxLifetimeJitter == 0 { + computed.writePoolOpts.ConnMaxLifetimeJitter = ptr.To(30 * time.Minute) + } + return computed, nil } @@ -183,7 +195,7 @@ func ReadConnMaxLifetime(lifetime time.Duration) Option { // ReadConnMaxLifetimeJitter is an interval to wait up to after the max lifetime // to close the connection. // -// This value defaults to 20% of the max lifetime. +// For CockroachDB, this value defaults to 30 minutes when not explicitly set. func ReadConnMaxLifetimeJitter(jitter time.Duration) Option { return func(po *crdbOptions) { po.readPoolOpts.ConnMaxLifetimeJitter = &jitter } } @@ -199,7 +211,7 @@ func WriteConnMaxLifetime(lifetime time.Duration) Option { // WriteConnMaxLifetimeJitter is an interval to wait up to after the max lifetime // to close the connection. // -// This value defaults to 20% of the max lifetime. +// For CockroachDB, this value defaults to 30 minutes when not explicitly set. func WriteConnMaxLifetimeJitter(jitter time.Duration) Option { return func(po *crdbOptions) { po.writePoolOpts.ConnMaxLifetimeJitter = &jitter } } diff --git a/internal/datastore/crdb/options_test.go b/internal/datastore/crdb/options_test.go new file mode 100644 index 0000000000..5fbb2066d6 --- /dev/null +++ b/internal/datastore/crdb/options_test.go @@ -0,0 +1,67 @@ +package crdb + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestConfiguration(t *testing.T) { + tests := []struct { + name string + options []Option + validate func(t *testing.T, config crdbOptions) + }{ + { + name: "default jitter configuration", + options: []Option{}, + validate: func(t *testing.T, config crdbOptions) { + require.NotNil(t, config.readPoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 30*time.Minute, *config.readPoolOpts.ConnMaxLifetimeJitter) + + require.NotNil(t, config.writePoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 30*time.Minute, *config.writePoolOpts.ConnMaxLifetimeJitter) + }, + }, + { + name: "explicit jitter values preserved", + options: []Option{ + ReadConnMaxLifetimeJitter(10 * time.Minute), + WriteConnMaxLifetimeJitter(15 * time.Minute), + }, + validate: func(t *testing.T, config crdbOptions) { + // Should preserve explicitly set values + require.NotNil(t, config.readPoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 10*time.Minute, *config.readPoolOpts.ConnMaxLifetimeJitter) + + require.NotNil(t, config.writePoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 15*time.Minute, *config.writePoolOpts.ConnMaxLifetimeJitter) + }, + }, + { + name: "zeros values applies defaults", + options: []Option{ + // This simulates what happens when pkg/cmd/datastore passes zero values + // from ConnPoolConfig.MaxLifetimeJitter (which defaults to 0) + ReadConnMaxLifetimeJitter(time.Duration(0)), + WriteConnMaxLifetimeJitter(time.Duration(0)), + }, + validate: func(t *testing.T, config crdbOptions) { + require.NotNil(t, config.readPoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 30*time.Minute, *config.readPoolOpts.ConnMaxLifetimeJitter) + + require.NotNil(t, config.writePoolOpts.ConnMaxLifetimeJitter) + require.Equal(t, 30*time.Minute, *config.writePoolOpts.ConnMaxLifetimeJitter) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config, err := generateConfig(tt.options) + require.NoError(t, err) + tt.validate(t, config) + }) + } +} diff --git a/internal/datastore/crdb/pool/balancer.go b/internal/datastore/crdb/pool/balancer.go index dc5a6c59a1..234f55a872 100644 --- a/internal/datastore/crdb/pool/balancer.go +++ b/internal/datastore/crdb/pool/balancer.go @@ -3,6 +3,7 @@ package pool import ( "context" "hash/maphash" + "maps" "math" "math/rand" "slices" @@ -13,7 +14,6 @@ import ( "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" - "golang.org/x/exp/maps" "golang.org/x/sync/semaphore" log "github.com/authzed/spicedb/internal/logging" @@ -186,7 +186,7 @@ func (p *nodeConnectionBalancer[P, C]) mustPruneConnections(ctx context.Context) } p.healthTracker.RUnlock() - nodes := maps.Keys(connectionCounts) + nodes := slices.Collect(maps.Keys(connectionCounts)) slices.Sort(nodes) // Shuffle nodes in place deterministically based on the initial seed. diff --git a/internal/datastore/crdb/reader.go b/internal/datastore/crdb/reader.go index 60c0a956a6..17f8f80cb2 100644 --- a/internal/datastore/crdb/reader.go +++ b/internal/datastore/crdb/reader.go @@ -101,8 +101,17 @@ func (cr *crdbReader) CountRelationships(ctx context.Context, name string) (int, return 0, err } - index := schema.IndexForFilter(cr.schema, relFilter) - query := cr.addFromToQuery(countRels, cr.schema.RelationshipTableName, index.Name) + index, err := schema.IndexForFilter(cr.schema, relFilter) + if err != nil { + return 0, err + } + + indexName := "" + if index != nil { + indexName = index.Name + } + + query := cr.addFromToQuery(countRels, cr.schema.RelationshipTableName, indexName) builder, err := common.NewSchemaQueryFiltererWithStartingQuery(cr.schema, query, cr.filterMaximumIDCount).FilterWithRelationshipsFilter(relFilter) if err != nil { return 0, err diff --git a/internal/datastore/crdb/readwrite.go b/internal/datastore/crdb/readwrite.go index 1916b1cf77..6eb5800c95 100644 --- a/internal/datastore/crdb/readwrite.go +++ b/internal/datastore/crdb/readwrite.go @@ -1,6 +1,7 @@ package crdb import ( + "cmp" "context" "errors" "fmt" @@ -8,7 +9,6 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/ccoveille/go-safecast" "github.com/jackc/pgx/v5" - "github.com/jzelinskie/stringz" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -409,7 +409,12 @@ func (rwt *crdbReadWriteTXN) DeleteRelationships(ctx context.Context, filter *v1 return 0, false, fmt.Errorf("unable to translate relationship filter: %w", err) } - query := rwt.queryDeleteTuples(schema.IndexForFilter(rwt.schema, dsFilter)) + index, err := schema.IndexForFilter(rwt.schema, dsFilter) + if err != nil { + return 0, false, fmt.Errorf("unable to determine index for filter: %w", err) + } + + query := rwt.queryDeleteTuples(index) if filter.ResourceType != "" { query = query.Where(sq.Eq{schema.ColNamespace: filter.ResourceType}) @@ -438,7 +443,7 @@ func (rwt *crdbReadWriteTXN) DeleteRelationships(ctx context.Context, filter *v1 query = query.Where(sq.Eq{schema.ColUsersetObjectID: subjectFilter.OptionalSubjectId}) } if relationFilter := subjectFilter.OptionalRelation; relationFilter != nil { - query = query.Where(sq.Eq{schema.ColUsersetRelation: stringz.DefaultEmpty(relationFilter.Relation, datastore.Ellipsis)}) + query = query.Where(sq.Eq{schema.ColUsersetRelation: cmp.Or(relationFilter.Relation, datastore.Ellipsis)}) } rwt.addOverlapKey(subjectFilter.SubjectType) } diff --git a/internal/datastore/crdb/schema/forcedindex.go b/internal/datastore/crdb/schema/forcedindex.go new file mode 100644 index 0000000000..5700e3a706 --- /dev/null +++ b/internal/datastore/crdb/schema/forcedindex.go @@ -0,0 +1,31 @@ +package schema + +import ( + "github.com/authzed/spicedb/internal/datastore/common" + "github.com/authzed/spicedb/pkg/spiceerrors" +) + +// forcedIndex is an index hint that forces the use of a specific index. +type forcedIndex struct { + index common.IndexDefinition +} + +func (f forcedIndex) FromSQLSuffix() (string, error) { + return "", nil +} + +func (f forcedIndex) FromTable(existingTableName string) (string, error) { + // Indexes are forced in CRDB by appending the index name after an @ sign after the table + // name in the FROM clause. + // Example: FROM relation_tuple@ix_relation_tuple_by_subject + if existingTableName == "" { + return "", spiceerrors.MustBugf("existing table name is empty") + } + return existingTableName + "@" + f.index.Name, nil +} + +func (f forcedIndex) SQLPrefix() (string, error) { + return "", nil +} + +var _ common.IndexingHint = forcedIndex{} diff --git a/internal/datastore/crdb/schema/indexes.go b/internal/datastore/crdb/schema/indexes.go index 713499398b..9fa0460161 100644 --- a/internal/datastore/crdb/schema/indexes.go +++ b/internal/datastore/crdb/schema/indexes.go @@ -4,8 +4,6 @@ import ( "github.com/authzed/spicedb/internal/datastore/common" "github.com/authzed/spicedb/pkg/datastore" "github.com/authzed/spicedb/pkg/datastore/queryshape" - "github.com/authzed/spicedb/pkg/genutil/mapz" - "github.com/authzed/spicedb/pkg/spiceerrors" ) // IndexPrimaryKey is a synthetic index that represents the primary key of the relation_tuple table. @@ -46,13 +44,24 @@ var IndexRelationshipWithIntegrity = common.IndexDefinition{ }, } -var crdbIndexes = []common.IndexDefinition{ +var crdbAllIndexes = []common.IndexDefinition{ IndexPrimaryKey, IndexRelationshipBySubject, IndexRelationshipBySubjectRelation, IndexRelationshipWithIntegrity, } +var crdbWithoutIntegrityIndexes = []common.IndexDefinition{ + IndexPrimaryKey, + IndexRelationshipBySubject, + IndexRelationshipBySubjectRelation, +} + +// TODO: add new indexes to integrity to match the existing ones on non-integrity. +var crdbWithIntegrityIndexes = []common.IndexDefinition{ + IndexRelationshipWithIntegrity, +} + var NoIndexingHint common.IndexingHint = nil // IndexingHintForQueryShape returns an indexing hint for the given query shape, if any. @@ -84,100 +93,11 @@ func IndexingHintForQueryShape(schema common.SchemaInformation, qs queryshape.Sh } // IndexForFilter returns the index to use for a given relationships filter or nil if no index is forced. -func IndexForFilter(schema common.SchemaInformation, filter datastore.RelationshipsFilter) *common.IndexDefinition { - // Special case: if the filter specifies the resource type and relation and the subject type and relation, then - // the schema diff index can be used. - if filter.OptionalResourceType != "" && - filter.OptionalResourceRelation != "" && - len(filter.OptionalSubjectsSelectors) == 1 && - filter.OptionalSubjectsSelectors[0].OptionalSubjectType != "" && - filter.OptionalSubjectsSelectors[0].RelationFilter.NonEllipsisRelation != "" && - !filter.OptionalSubjectsSelectors[0].RelationFilter.IncludeEllipsisRelation && - !filter.OptionalSubjectsSelectors[0].RelationFilter.OnlyNonEllipsisRelations { - return &IndexRelationshipBySubjectRelation - } - - // Otherwise, determine an index based on whether the filter has a larger match on the resources or subject. - resourceFieldDepth := 0 - if filter.OptionalResourceType != "" { - resourceFieldDepth = 1 - if len(filter.OptionalResourceIds) > 0 || filter.OptionalResourceIDPrefix != "" { - resourceFieldDepth = 2 - if filter.OptionalResourceRelation != "" { - if filter.OptionalResourceIDPrefix != "" { - return nil // Cannot use an index with a prefix and a relation. - } - - resourceFieldDepth = 3 - } - } - } - - subjectFieldDepths := mapz.NewSet[int]() - for _, subjectSelector := range filter.OptionalSubjectsSelectors { - sfd := 0 - if len(subjectSelector.OptionalSubjectIds) > 0 { - sfd = 1 - if subjectSelector.OptionalSubjectType != "" { - sfd = 2 - if subjectSelector.RelationFilter.NonEllipsisRelation != "" { - sfd = 3 - } - } - } - subjectFieldDepths.Add(sfd) - } - - if subjectFieldDepths.Len() > 1 { - return nil - } - - subjectFieldDepth := 0 - if !subjectFieldDepths.IsEmpty() { - subjectFieldDepth = subjectFieldDepths.AsSlice()[0] - } - - if resourceFieldDepth == 0 && subjectFieldDepth == 0 { - return nil - } - - if resourceFieldDepth > subjectFieldDepth { - return &IndexPrimaryKey - } - - if resourceFieldDepth < subjectFieldDepth { - if schema.IntegrityEnabled { - // Don't force this index since it doesn't exist for integrity-enabled schemas. - return nil - } - - return &IndexRelationshipBySubject - } - - return nil -} - -// forcedIndex is an index hint that forces the use of a specific index. -type forcedIndex struct { - index common.IndexDefinition -} - -func (f forcedIndex) FromSQLSuffix() (string, error) { - return "", nil -} - -func (f forcedIndex) FromTable(existingTableName string) (string, error) { - // Indexes are forced in CRDB by appending the index name after an @ sign after the table - // name in the FROM clause. - // Example: FROM relation_tuple@ix_relation_tuple_by_subject - if existingTableName == "" { - return "", spiceerrors.MustBugf("existing table name is empty") +func IndexForFilter(schema common.SchemaInformation, filter datastore.RelationshipsFilter) (*common.IndexDefinition, error) { + indexesToCheck := crdbWithoutIntegrityIndexes + if schema.IntegrityEnabled { + indexesToCheck = crdbWithIntegrityIndexes } - return existingTableName + "@" + f.index.Name, nil -} -func (f forcedIndex) SQLPrefix() (string, error) { - return "", nil + return forcedIndexForFilter(filter, indexesToCheck) } - -var _ common.IndexingHint = forcedIndex{} diff --git a/internal/datastore/crdb/schema/indexes_test.go b/internal/datastore/crdb/schema/indexes_test.go index 91a562591f..82f237a3e0 100644 --- a/internal/datastore/crdb/schema/indexes_test.go +++ b/internal/datastore/crdb/schema/indexes_test.go @@ -9,6 +9,8 @@ import ( "github.com/authzed/spicedb/pkg/datastore" ) +const letCockroachDBDecide = "" + func TestIndexForFilter(t *testing.T) { tests := []struct { name string @@ -19,14 +21,14 @@ func TestIndexForFilter(t *testing.T) { { name: "no filter", filter: datastore.RelationshipsFilter{}, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type", filter: datastore.RelationshipsFilter{OptionalResourceType: "foo"}, expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithIntegrity: "ix_relation_tuple_with_integrity", }, { name: "filter by resource type and relation", @@ -34,8 +36,8 @@ func TestIndexForFilter(t *testing.T) { OptionalResourceType: "foo", OptionalResourceRelation: "bar", }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type, resource ID and relation", @@ -45,7 +47,7 @@ func TestIndexForFilter(t *testing.T) { OptionalResourceRelation: "bar", }, expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithIntegrity: "ix_relation_tuple_with_integrity", }, { name: "filter by subject type, subject ID and relation", @@ -61,7 +63,7 @@ func TestIndexForFilter(t *testing.T) { }, }, expectedWithoutIntegrity: "ix_relation_tuple_by_subject", - expectedWithIntegrity: "", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by subject type, subject ID", @@ -74,7 +76,7 @@ func TestIndexForFilter(t *testing.T) { }, }, expectedWithoutIntegrity: "ix_relation_tuple_by_subject", - expectedWithIntegrity: "", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by subject relation, subject ID", @@ -88,8 +90,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "ix_relation_tuple_by_subject", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by subject type", @@ -100,8 +102,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type and subject type", @@ -113,8 +115,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type and subject object ID", @@ -126,8 +128,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type, relation and subject type and relation", @@ -144,7 +146,7 @@ func TestIndexForFilter(t *testing.T) { }, }, expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", - expectedWithIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type, relation and subject type", @@ -157,8 +159,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type, relation and subject relation", @@ -173,8 +175,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource relation and subject type and relation", @@ -189,8 +191,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type, relation and subject type and relation, include ellipsis", @@ -207,8 +209,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "filter by resource type and ID prefix", @@ -217,7 +219,7 @@ func TestIndexForFilter(t *testing.T) { OptionalResourceIDPrefix: "prefix", }, expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithIntegrity: "ix_relation_tuple_with_integrity", }, { name: "filter by resource type, ID prefix and relation", @@ -226,8 +228,8 @@ func TestIndexForFilter(t *testing.T) { OptionalResourceIDPrefix: "prefix", OptionalResourceRelation: "bar", }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "multiple subject selectors with different depths", @@ -245,8 +247,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "multiple subject selectors with same depth", @@ -263,7 +265,7 @@ func TestIndexForFilter(t *testing.T) { }, }, expectedWithoutIntegrity: "ix_relation_tuple_by_subject", - expectedWithIntegrity: "", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "multiple subject selectors with resource filter", @@ -279,8 +281,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "subject IDs without subject type", @@ -294,8 +296,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "ix_relation_tuple_by_subject", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, }, { name: "schema diff index with only non-ellipsis relations", @@ -313,8 +315,8 @@ func TestIndexForFilter(t *testing.T) { }, }, }, - expectedWithoutIntegrity: "pk_relation_tuple", - expectedWithIntegrity: "pk_relation_tuple", + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, }, { name: "empty subject selector", @@ -323,8 +325,66 @@ func TestIndexForFilter(t *testing.T) { {}, }, }, - expectedWithoutIntegrity: "", - expectedWithIntegrity: "", + expectedWithoutIntegrity: letCockroachDBDecide, + expectedWithIntegrity: letCockroachDBDecide, + }, + { + name: "IndexRelationshipBySubjectRelation with ellipsis for subject relation", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "foo", + OptionalResourceRelation: "bar", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "foo", + RelationFilter: datastore.SubjectRelationFilter{ + IncludeEllipsisRelation: true, + }, + }, + }, + }, + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, + }, + { + name: "IndexRelationshipBySubjectRelation with ellipsis and other relation for subject relation", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "foo", + OptionalResourceRelation: "bar", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "foo", + RelationFilter: datastore.SubjectRelationFilter{ + NonEllipsisRelation: "baz", + IncludeEllipsisRelation: true, + }, + }, + }, + }, + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, + }, + { + name: "IndexRelationshipBySubjectRelation with ellipsis and other relation as distinct filters on subject relation", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "foo", + OptionalResourceRelation: "bar", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "foo", + RelationFilter: datastore.SubjectRelationFilter{ + IncludeEllipsisRelation: true, + }, + }, + { + OptionalSubjectType: "foo2", + RelationFilter: datastore.SubjectRelationFilter{ + NonEllipsisRelation: "baz", + }, + }, + }, + }, + expectedWithoutIntegrity: "ix_relation_tuple_by_subject_relation", + expectedWithIntegrity: letCockroachDBDecide, }, } @@ -337,7 +397,9 @@ func TestIndexForFilter(t *testing.T) { schema := Schema(common.ColumnOptimizationOptionNone, withIntegrity, false) for _, test := range tests { t.Run(test.name+integritySuffix, func(t *testing.T) { - index := IndexForFilter(*schema, test.filter) + index, err := IndexForFilter(*schema, test.filter) + require.NoError(t, err) + expected := test.expectedWithoutIntegrity if withIntegrity { expected = test.expectedWithIntegrity diff --git a/internal/datastore/crdb/schema/indexutil.go b/internal/datastore/crdb/schema/indexutil.go new file mode 100644 index 0000000000..d4d3f1224d --- /dev/null +++ b/internal/datastore/crdb/schema/indexutil.go @@ -0,0 +1,240 @@ +package schema + +import ( + "fmt" + "regexp" + "strings" + + "github.com/authzed/spicedb/internal/datastore/common" + "github.com/authzed/spicedb/pkg/datastore" + "github.com/authzed/spicedb/pkg/genutil/mapz" + "github.com/authzed/spicedb/pkg/spiceerrors" +) + +var parsedColumnsPerIndex = map[string][]string{} + +func init() { + mustInit() +} + +func mustInit() { + for _, idx := range crdbAllIndexes { + parsed, err := parseIndexColumns(idx.ColumnsSQL) + if err != nil { + panic(err) + } + parsedColumnsPerIndex[idx.Name] = parsed + } +} + +func parseIndexColumns(columnsSQL string) ([]string, error) { + // Match columns within parentheses, handling both PRIMARY KEY and table_name formats + re := regexp.MustCompile(`\(([^)]+)\)`) + matches := re.FindStringSubmatch(columnsSQL) + if len(matches) < 2 { + return nil, fmt.Errorf("no columns found in parentheses in SQL: %s", columnsSQL) + } + + // Split by comma and trim whitespace + columnsStr := matches[1] + columns := regexp.MustCompile(`\s*,\s*`).Split(columnsStr, -1) + + // Trim any remaining whitespace + foundColumns := mapz.NewSet[string]() + for i, col := range columns { + trimmed := strings.TrimSpace(col) + if trimmed == "" { + return nil, fmt.Errorf("empty column name found in SQL: %s", columnsSQL) + } + + if !foundColumns.Add(trimmed) { + return nil, fmt.Errorf("duplicate column found in index definition: %s", trimmed) + } + + columns[i] = trimmed + } + + return columns, nil +} + +func forcedIndexForFilter(filter datastore.RelationshipsFilter, indexes []common.IndexDefinition) (*common.IndexDefinition, error) { + // Algorithm: Find the index that has the most leading columns matching the filter. + // If at any point a column within the index is not in the filter, we stop checking for + // that index. We return the index with the most leading columns matched. Resource IDs + // are treated as an *immediate* stop, as prefix scanning does not work well with + // a following field in the index. + var bestIndex *common.IndexDefinition + var bestCount int + + for _, idx := range indexes { + count, err := checkIfMatchingIndex(filter, idx) + if err != nil { + return nil, err + } + + if count > 0 { + if count > bestCount { + bestCount = count + bestIndex = &idx + } else if count == bestCount { + // If we find two matching indexes, let CRDB decide. + return nil, nil + } + } + } + + return bestIndex, nil +} + +const doesNotMatch = -1 + +func checkIfMatchingIndex(filter datastore.RelationshipsFilter, idx common.IndexDefinition) (int, error) { + columnNames, ok := parsedColumnsPerIndex[idx.Name] + if !ok { + return -1, spiceerrors.MustBugf("index %s not found in parsed columns", idx.Name) + } + + lastMatchingColIndex := doesNotMatch + + allowAdditionalColumns := true + for columnIndex, colName := range columnNames { + filterStatus, err := checkFilterColumnMatchesFilter(colName, filter) + if err != nil { + return doesNotMatch, err + } + + switch filterStatus { + case columnFilterNoMatch: + if columnIndex == 0 { + // If the first column doesn't match, this index is not a match. + return doesNotMatch, nil + } + + continue + + case columnFilterStop: + allowAdditionalColumns = false + if columnIndex > lastMatchingColIndex+1 { + // We had a gap in matching columns, so we stop here. + return doesNotMatch, nil + } + + lastMatchingColIndex = columnIndex + + case columnFilterMatch: + // If we have already stopped matching columns, we can't match any more. + // This handles prefix matching of resource IDs. + if !allowAdditionalColumns { + return doesNotMatch, nil + } + + if columnIndex > lastMatchingColIndex+1 { + // We had a gap in matching columns, so we stop here. + return doesNotMatch, nil + } + + lastMatchingColIndex = columnIndex + + case columnFilterForceNoMatch: + return doesNotMatch, nil + + default: + return doesNotMatch, spiceerrors.MustBugf("unknown column filter status: %d", filterStatus) + } + } + + return lastMatchingColIndex + 1, nil +} + +type columnFilterResult int + +const ( + columnFilterNoMatch columnFilterResult = iota + columnFilterMatch + columnFilterStop + columnFilterForceNoMatch +) + +func checkFilterColumnMatchesFilter(colName string, filter datastore.RelationshipsFilter) (columnFilterResult, error) { + switch colName { + case "namespace": + if filter.OptionalResourceType == "" { + return columnFilterNoMatch, nil + } + return columnFilterMatch, nil + case "object_id": + if filter.OptionalResourceIDPrefix != "" { + return columnFilterStop, nil + } + if len(filter.OptionalResourceIds) == 0 { + return columnFilterNoMatch, nil + } + return columnFilterMatch, nil + + case "relation": + if filter.OptionalResourceRelation == "" { + return columnFilterNoMatch, nil + } + return columnFilterMatch, nil + + case "userset_namespace": + if len(filter.OptionalSubjectsSelectors) == 0 { + return columnFilterNoMatch, nil + } + + foundCount := 0 + for _, sel := range filter.OptionalSubjectsSelectors { + if sel.OptionalSubjectType != "" { + foundCount++ + } + } + if foundCount == 0 { + return columnFilterNoMatch, nil + } else if foundCount < len(filter.OptionalSubjectsSelectors) { + return columnFilterForceNoMatch, nil + } else { + return columnFilterMatch, nil + } + + case "userset_object_id": + if len(filter.OptionalSubjectsSelectors) == 0 { + return columnFilterNoMatch, nil + } + + foundCount := 0 + for _, sel := range filter.OptionalSubjectsSelectors { + if len(sel.OptionalSubjectIds) > 0 { + foundCount++ + } + } + if foundCount == 0 { + return columnFilterNoMatch, nil + } else if foundCount < len(filter.OptionalSubjectsSelectors) { + return columnFilterForceNoMatch, nil + } else { + return columnFilterMatch, nil + } + + case "userset_relation": + if len(filter.OptionalSubjectsSelectors) == 0 { + return columnFilterNoMatch, nil + } + + foundCount := 0 + for _, sel := range filter.OptionalSubjectsSelectors { + if sel.RelationFilter.NonEllipsisRelation != "" || sel.RelationFilter.IncludeEllipsisRelation { + foundCount++ + } + } + if foundCount == 0 { + return columnFilterNoMatch, nil + } else if foundCount < len(filter.OptionalSubjectsSelectors) { + return columnFilterForceNoMatch, nil + } else { + return columnFilterMatch, nil + } + + default: + return columnFilterForceNoMatch, spiceerrors.MustBugf("unknown column name: %s", colName) + } +} diff --git a/internal/datastore/crdb/schema/indexutil_test.go b/internal/datastore/crdb/schema/indexutil_test.go new file mode 100644 index 0000000000..e649b2f11d --- /dev/null +++ b/internal/datastore/crdb/schema/indexutil_test.go @@ -0,0 +1,824 @@ +package schema + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/authzed/spicedb/internal/datastore/common" + "github.com/authzed/spicedb/pkg/datastore" +) + +func TestParseIndexColumns(t *testing.T) { + tests := []struct { + name string + columnsSQL string + expectedCols []string + expectError bool + }{ + { + name: "primary key columns", + columnsSQL: "PRIMARY KEY (namespace, object_id, relation, userset_namespace, userset_object_id, userset_relation)", + expectedCols: []string{"namespace", "object_id", "relation", "userset_namespace", "userset_object_id", "userset_relation"}, + }, + { + name: "index with table name", + columnsSQL: "relation_tuple (userset_object_id, userset_namespace, userset_relation, namespace, relation)", + expectedCols: []string{"userset_object_id", "userset_namespace", "userset_relation", "namespace", "relation"}, + }, + { + name: "index with table name and subject relation", + columnsSQL: "relation_tuple (userset_namespace, userset_relation, namespace, relation)", + expectedCols: []string{"userset_namespace", "userset_relation", "namespace", "relation"}, + }, + { + name: "index with storing clause", + columnsSQL: "relation_tuple_with_integrity (namespace, object_id, relation, userset_namespace, userset_object_id, userset_relation) STORING (integrity_key_id, integrity_hash, timestamp, caveat_name, caveat_context)", + expectedCols: []string{"namespace", "object_id", "relation", "userset_namespace", "userset_object_id", "userset_relation"}, + }, + { + name: "columns with extra whitespace", + columnsSQL: "PRIMARY KEY ( namespace , object_id , relation )", + expectedCols: []string{"namespace", "object_id", "relation"}, + }, + { + name: "no parentheses", + columnsSQL: "PRIMARY KEY namespace, object_id, relation", + expectError: true, + }, + { + name: "unclosed parentheses", + columnsSQL: "PRIMARY KEY (namespace, object_id, relation", + expectError: true, + }, + { + name: "empty parentheses", + columnsSQL: "PRIMARY KEY ()", + expectError: true, + }, + { + name: "single column", + columnsSQL: "relation_tuple (namespace)", + expectedCols: []string{"namespace"}, + }, + { + name: "single column with spaces", + columnsSQL: "relation_tuple ( namespace )", + expectedCols: []string{"namespace"}, + }, + { + name: "malformed single column with trailing comma", + columnsSQL: "relation_tuple ( ,namespace )", + expectedCols: []string{"namespace"}, + expectError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + columns, err := parseIndexColumns(test.columnsSQL) + + if test.expectError { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, test.expectedCols, columns) + }) + } +} + +func TestCheckIfMatchingIndex(t *testing.T) { + tests := []struct { + name string + filter datastore.RelationshipsFilter + index common.IndexDefinition + expectedCount int + expectedError bool + }{ + { + name: "empty filter with primary key", + filter: datastore.RelationshipsFilter{}, + index: IndexPrimaryKey, + expectedCount: -1, + }, + { + name: "resource type only with primary key", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + }, + index: IndexPrimaryKey, + expectedCount: 1, + }, + { + name: "resource type and relation with primary key", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceRelation: "viewer", + }, + index: IndexPrimaryKey, + expectedCount: -1, // namespace and relation match, but object_id missing, so no match at all + }, + { + name: "resource type, ID and relation with primary key", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + }, + index: IndexPrimaryKey, + expectedCount: 3, // namespace, object_id, and relation match + }, + { + name: "resource type with ID prefix with primary key", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIDPrefix: "doc_", + }, + index: IndexPrimaryKey, + expectedCount: 2, // Only namespace matches, then prefix stops further matching + }, + { + name: "complete resource with subject selector", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: 6, // All columns match: namespace, object_id, relation, userset_namespace, userset_object_id, userset_relation + }, + { + name: "subject selector with type only", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: -1, // No resource filters, so no match with primary key + }, + { + name: "subject selector with relation filter", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{}.WithEllipsisRelation(), + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: -1, // namespace matches but gap before userset_namespace, so no match + }, + { + name: "multiple subject selectors - all valid", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + { + OptionalSubjectType: "group", + OptionalSubjectIds: []string{"admins"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithEllipsisRelation(), + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: 6, // All columns match + }, + { + name: "multiple subject selectors - one missing subject type", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + { + OptionalSubjectIds: []string{"group1"}, // Missing OptionalSubjectType + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: -1, + }, + // Test cases for IndexRelationshipBySubject (userset_object_id, userset_namespace, userset_relation, namespace, relation) + { + name: "subject filter with IndexRelationshipBySubject", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexRelationshipBySubject, + expectedCount: 3, // userset_object_id, userset_namespace, userset_relation match + }, + { + name: "subject and resource filter with IndexRelationshipBySubject", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexRelationshipBySubject, + expectedCount: 5, // All columns match: userset_object_id, userset_namespace, userset_relation, namespace, relation + }, + { + name: "incomplete subject filter with IndexRelationshipBySubject", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + // Missing OptionalSubjectIds and RelationFilter + }, + }, + }, + index: IndexRelationshipBySubject, + expectedCount: -1, + }, + // Test cases for IndexRelationshipBySubjectRelation (userset_namespace, userset_relation, namespace, relation) + { + name: "subject type and relation with IndexRelationshipBySubjectRelation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexRelationshipBySubjectRelation, + expectedCount: 2, // userset_namespace, userset_relation match + }, + { + name: "complete filter with IndexRelationshipBySubjectRelation", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexRelationshipBySubjectRelation, + expectedCount: 4, // All columns match: userset_namespace, userset_relation, namespace, relation + }, + { + name: "subject without relation filter with IndexRelationshipBySubjectRelation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + // No RelationFilter + }, + }, + }, + index: IndexRelationshipBySubjectRelation, + expectedCount: 1, // Only userset_namespace matches, userset_relation doesn't match + }, + // Test cases for IndexRelationshipWithIntegrity (same as primary key columns) + { + name: "complete filter with IndexRelationshipWithIntegrity", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + }, + index: IndexRelationshipWithIntegrity, + expectedCount: 6, // All columns match: namespace, object_id, relation, userset_namespace, userset_object_id, userset_relation + }, + { + name: "resource type only with IndexRelationshipWithIntegrity", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + }, + index: IndexRelationshipWithIntegrity, + expectedCount: 1, // Only namespace matches + }, + // Edge cases and complex scenarios + { + name: "resource ID prefix stops matching at object_id", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIDPrefix: "doc_", + OptionalResourceRelation: "viewer", // This won't be matched due to prefix stop + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: -1, // Only namespace matches, then prefix stops further matching + }, + { + name: "subject selector with ellipsis relation", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithEllipsisRelation(), + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: 6, // All columns match including ellipsis relation + }, + { + name: "mixed subject selectors with different relation filters", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + { + OptionalSubjectType: "group", + RelationFilter: datastore.SubjectRelationFilter{}.WithEllipsisRelation(), + }, + }, + }, + index: IndexRelationshipBySubjectRelation, + expectedCount: 3, // userset_namespace, userset_relation, and namespace match + }, + { + name: "subject selector with OnlyNonEllipsisRelations", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{}.WithOnlyNonEllipsisRelations(), + }, + }, + }, + index: IndexRelationshipBySubjectRelation, + expectedCount: -1, // The current logic doesn't handle OnlyNonEllipsisRelations properly, so it fails + }, + { + name: "empty subject selectors slice", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{}, // Empty slice + }, + index: IndexPrimaryKey, + expectedCount: 1, // Only namespace matches, no subject selectors to check + }, + { + name: "resource with multiple IDs", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1", "doc2", "doc3"}, + OptionalResourceRelation: "viewer", + }, + index: IndexPrimaryKey, + expectedCount: 3, // namespace, object_id, and relation match + }, + { + name: "best index selection scenario - subject index should be better", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + OptionalResourceType: "document", + }, + index: IndexRelationshipBySubject, + expectedCount: 4, // userset_object_id, userset_namespace, userset_relation, namespace match + }, + // Test cases for caveat and expiration filters (these don't affect index matching) + { + name: "filter with caveat name", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalCaveatNameFilter: datastore.WithCaveatName("user_context"), + }, + index: IndexPrimaryKey, + expectedCount: 3, // Caveat filters don't affect index column matching: namespace, object_id, relation + }, + { + name: "filter with no caveat", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalCaveatNameFilter: datastore.WithNoCaveat(), + }, + index: IndexPrimaryKey, + expectedCount: 3, // Caveat filters don't affect index column matching: namespace, object_id, relation + }, + { + name: "filter with expiration option", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalExpirationOption: datastore.ExpirationFilterOptionHasExpiration, + }, + index: IndexPrimaryKey, + expectedCount: 3, // Expiration filters don't affect index column matching: namespace, object_id, relation + }, + { + name: "filter with no expiration option", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1"}, + OptionalResourceRelation: "viewer", + OptionalExpirationOption: datastore.ExpirationFilterOptionNoExpiration, + }, + index: IndexPrimaryKey, + expectedCount: 3, // Expiration filters don't affect index column matching: namespace, object_id, relation + }, + { + name: "comprehensive filter with all options", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalResourceIds: []string{"doc1", "doc2"}, + OptionalResourceRelation: "viewer", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + OptionalSubjectIds: []string{"alice", "bob"}, + RelationFilter: datastore.SubjectRelationFilter{}.WithNonEllipsisRelation("member"), + }, + }, + OptionalCaveatNameFilter: datastore.WithCaveatName("user_context"), + OptionalExpirationOption: datastore.ExpirationFilterOptionHasExpiration, + }, + index: IndexPrimaryKey, + expectedCount: 6, // All indexed columns match: namespace, object_id, relation, userset_namespace, userset_object_id, userset_relation + }, + { + name: "resource type and subject IDs only, over primary", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectIds: []string{"alice", "bob"}, + }, + }, + }, + index: IndexPrimaryKey, + expectedCount: -1, + }, + { + name: "resource type and subject IDs only, over relationship by subject", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectIds: []string{"alice", "bob"}, + }, + }, + }, + index: IndexRelationshipBySubject, + expectedCount: -1, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result, err := checkIfMatchingIndex(test.filter, test.index) + + if test.expectedError { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, test.expectedCount, result) + }) + } +} + +func TestCheckFilterColumnMatchesFilter(t *testing.T) { + tests := []struct { + name string + colName string + filter datastore.RelationshipsFilter + expectedResult columnFilterResult + expectedError bool + }{ + { + name: "namespace column with matching filter", + colName: "namespace", + filter: datastore.RelationshipsFilter{ + OptionalResourceType: "document", + }, + expectedResult: columnFilterMatch, + }, + { + name: "namespace column without matching filter", + colName: "namespace", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "object_id column with resource IDs", + colName: "object_id", + filter: datastore.RelationshipsFilter{ + OptionalResourceIds: []string{"doc1"}, + }, + expectedResult: columnFilterMatch, + }, + { + name: "object_id column with resource ID prefix (should stop)", + colName: "object_id", + filter: datastore.RelationshipsFilter{ + OptionalResourceIDPrefix: "doc_", + }, + expectedResult: columnFilterStop, + }, + { + name: "object_id column without resource filters", + colName: "object_id", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "relation column with matching filter", + colName: "relation", + filter: datastore.RelationshipsFilter{ + OptionalResourceRelation: "viewer", + }, + expectedResult: columnFilterMatch, + }, + { + name: "relation column without matching filter", + colName: "relation", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "userset_namespace column with subject selector", + colName: "userset_namespace", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "userset_namespace column without subject selector", + colName: "userset_namespace", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "userset_namespace column with empty subject type", + colName: "userset_namespace", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectIds: []string{"alice"}, + }, + }, + }, + expectedResult: columnFilterNoMatch, + }, + { + name: "userset_object_id column with valid subject selector", + colName: "userset_object_id", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectIds: []string{"alice"}, + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "userset_object_id column without subject selector", + colName: "userset_object_id", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "userset_relation column with relation filter", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{ + NonEllipsisRelation: "member", + }, + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "userset_relation column with ellipsis relation filter", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{ + IncludeEllipsisRelation: true, + }, + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "userset_relation column without relation filter", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + }, + }, + }, + expectedResult: columnFilterNoMatch, + }, + { + name: "userset_relation column without subject selector", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{}, + expectedResult: columnFilterNoMatch, + }, + { + name: "unknown column name should return error", + colName: "unknown_column", + filter: datastore.RelationshipsFilter{}, + expectedError: true, + }, + { + name: "multiple subject selectors - all have subject type", + colName: "userset_namespace", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + }, + { + OptionalSubjectType: "group", + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "multiple subject selectors - one missing subject type", + colName: "userset_namespace", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + }, + { + OptionalSubjectIds: []string{"alice"}, + }, + }, + }, + expectedResult: columnFilterForceNoMatch, + }, + { + name: "multiple subject selectors - all have relation filters", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{ + NonEllipsisRelation: "member", + }, + }, + { + OptionalSubjectType: "group", + RelationFilter: datastore.SubjectRelationFilter{ + IncludeEllipsisRelation: true, + }, + }, + }, + }, + expectedResult: columnFilterMatch, + }, + { + name: "multiple subject selectors - one missing relation filter", + colName: "userset_relation", + filter: datastore.RelationshipsFilter{ + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: "user", + RelationFilter: datastore.SubjectRelationFilter{ + NonEllipsisRelation: "member", + }, + }, + { + OptionalSubjectType: "group", + }, + }, + }, + expectedResult: columnFilterForceNoMatch, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if test.expectedError { + require.Panics(t, func() { + _, _ = checkFilterColumnMatchesFilter(test.colName, test.filter) + }) + return + } + + result, err := checkFilterColumnMatchesFilter(test.colName, test.filter) + require.NoError(t, err) + require.Equal(t, test.expectedResult, result) + }) + } +} + +func FuzzParseIndexColumns(f *testing.F) { + // Add seed inputs that cover different valid and invalid cases + f.Add("PRIMARY KEY (namespace, object_id, relation)") + f.Add("relation_tuple (userset_object_id, userset_namespace)") + f.Add("PRIMARY KEY ( namespace , object_id )") + f.Add("PRIMARY KEY ()") + f.Add("PRIMARY KEY namespace, object_id") + f.Add("(namespace)") + f.Add("") + f.Add(",") + f.Add(",columnName") + f.Add("PRIMARY KEY (namespace, object_id, relation") + f.Add("PRIMARY KEY namespace, object_id, relation)") + f.Add("PRIMARY KEY ( namespace, object_id, ") + f.Add("relation_tuple_with_integrity (namespace, object_id) STORING (integrity_key_id)") + + f.Fuzz(func(t *testing.T, input string) { + columns, err := parseIndexColumns(input) + + if err == nil { + // If no error, we should have at least one column + require.NotEmpty(t, columns, "parseIndexColumns returned no error but empty columns for input: %q", input) + + // All returned columns should be non-empty strings + for i, col := range columns { + require.NotEmpty(t, col, "parseIndexColumns returned empty column at index %d for input: %q", i, input) + } + } else { + require.Empty(t, columns, "parseIndexColumns returned no error but empty columns for input: %q", input) + } + }) +} diff --git a/internal/datastore/crdb/schema/schema.go b/internal/datastore/crdb/schema/schema.go index 407f49b3f0..e1878e8e93 100644 --- a/internal/datastore/crdb/schema/schema.go +++ b/internal/datastore/crdb/schema/schema.go @@ -70,7 +70,7 @@ func Schema(colOptimizationOpt common.ColumnOptimizationOption, withIntegrity bo common.WithColumnOptimization(colOptimizationOpt), common.WithIntegrityEnabled(withIntegrity), common.WithExpirationDisabled(expirationDisabled), - common.SetIndexes(crdbIndexes), + common.SetIndexes(crdbAllIndexes), // NOTE: this order differs from the default because the index // used for sorting by subject (ix_relation_tuple_by_subject) is diff --git a/internal/datastore/memdb/readonly.go b/internal/datastore/memdb/readonly.go index 739613fb60..deba941879 100644 --- a/internal/datastore/memdb/readonly.go +++ b/internal/datastore/memdb/readonly.go @@ -392,7 +392,7 @@ func filterFuncForFilters( optionalExpirationFilter datastore.ExpirationFilterOption, cursorFilter func(*relationship) bool, ) memdb.FilterFunc { - return func(tupleRaw interface{}) bool { + return func(tupleRaw any) bool { tuple := tupleRaw.(*relationship) switch { diff --git a/internal/datastore/memdb/readwrite.go b/internal/datastore/memdb/readwrite.go index 5e375e1594..474a71c182 100644 --- a/internal/datastore/memdb/readwrite.go +++ b/internal/datastore/memdb/readwrite.go @@ -1,12 +1,12 @@ package memdb import ( + "cmp" "context" "fmt" "strings" "github.com/hashicorp/go-memdb" - "github.com/jzelinskie/stringz" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -351,8 +351,8 @@ func (rwt *memdbReadWriteTx) BulkLoad(ctx context.Context, iter datastore.BulkWr return numCopied, err } -func relationshipFilterFilterFunc(filter *v1.RelationshipFilter) func(interface{}) bool { - return func(tupleRaw interface{}) bool { +func relationshipFilterFilterFunc(filter *v1.RelationshipFilter) func(any) bool { + return func(tupleRaw any) bool { tuple := tupleRaw.(*relationship) // If it doesn't match one of the resource filters, filter it. @@ -375,7 +375,7 @@ func relationshipFilterFilterFunc(filter *v1.RelationshipFilter) func(interface{ case subjectFilter.OptionalSubjectId != "" && subjectFilter.OptionalSubjectId != tuple.subjectObjectID: return true case subjectFilter.OptionalRelation != nil && - stringz.DefaultEmpty(subjectFilter.OptionalRelation.Relation, datastore.Ellipsis) != tuple.subjectRelation: + cmp.Or(subjectFilter.OptionalRelation.Relation, datastore.Ellipsis) != tuple.subjectRelation: return true } } diff --git a/internal/datastore/mysql/datastore.go b/internal/datastore/mysql/datastore.go index 3e83078932..854b6f8464 100644 --- a/internal/datastore/mysql/datastore.go +++ b/internal/datastore/mysql/datastore.go @@ -92,7 +92,7 @@ func init() { } type sqlFilter interface { - ToSql() (string, []interface{}, error) + ToSql() (string, []any, error) } // NewMySQLDatastore creates a new mysql.Datastore value configured with the MySQL instance @@ -446,7 +446,7 @@ func isErrorRetryable(err error) bool { } type querier interface { - QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryContext(context.Context, string, ...any) (*sql.Rows, error) } type asQueryableTx struct { diff --git a/internal/datastore/mysql/debug.go b/internal/datastore/mysql/debug.go index e49dc13631..1c7f0ddda7 100644 --- a/internal/datastore/mysql/debug.go +++ b/internal/datastore/mysql/debug.go @@ -25,7 +25,7 @@ func (mds *Datastore) PreExplainStatements() []string { } } -func (mds *Datastore) BuildExplainQuery(sql string, args []interface{}) (string, []any, error) { +func (mds *Datastore) BuildExplainQuery(sql string, args []any) (string, []any, error) { return "EXPLAIN FORMAT=JSON " + sql, args, nil } diff --git a/internal/datastore/mysql/readwrite.go b/internal/datastore/mysql/readwrite.go index fc11288958..d64f020792 100644 --- a/internal/datastore/mysql/readwrite.go +++ b/internal/datastore/mysql/readwrite.go @@ -2,6 +2,7 @@ package mysql import ( "bytes" + "cmp" "context" "database/sql" "database/sql/driver" @@ -15,8 +16,6 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/ccoveille/go-safecast" "github.com/go-sql-driver/mysql" - "github.com/jzelinskie/stringz" - "golang.org/x/exp/maps" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -62,7 +61,7 @@ func (cc *structpbWrapper) Scan(val any) error { return fmt.Errorf("unsupported type: %T", v) } - maps.Clear(*cc) + clear(*cc) return json.Unmarshal(v, &cc) } @@ -367,7 +366,7 @@ func (rwt *mysqlReadWriteTXN) DeleteRelationships(ctx context.Context, filter *v query = query.Where(sq.Eq{colUsersetObjectID: subjectFilter.OptionalSubjectId}) } if relationFilter := subjectFilter.OptionalRelation; relationFilter != nil { - query = query.Where(sq.Eq{colUsersetRelation: stringz.DefaultEmpty(relationFilter.Relation, datastore.Ellipsis)}) + query = query.Where(sq.Eq{colUsersetRelation: cmp.Or(relationFilter.Relation, datastore.Ellipsis)}) } } @@ -518,7 +517,7 @@ func (rwt *mysqlReadWriteTXN) BulkLoad(ctx context.Context, iter datastore.BulkW for rel != nil && err == nil { sqlStmt.Reset() sqlStmt.WriteString(sql) - var args []interface{} + var args []any var batchLen uint64 for ; rel != nil && err == nil && batchLen < bulkInsertRowsLimit; rel, err = iter.Next(ctx) { diff --git a/internal/datastore/postgres/common/pgx.go b/internal/datastore/postgres/common/pgx.go index 3e9873e29a..a83d7aaa75 100644 --- a/internal/datastore/postgres/common/pgx.go +++ b/internal/datastore/postgres/common/pgx.go @@ -66,7 +66,7 @@ func ConnectWithInstrumentationAndTimeout(ctx context.Context, url string, conne // info level events to debug, as they are rather verbose for SpiceDB's info level func ConfigurePGXLogger(connConfig *pgx.ConnConfig) { levelMappingFn := func(logger tracelog.Logger) tracelog.LoggerFunc { - return func(ctx context.Context, level tracelog.LogLevel, msg string, data map[string]interface{}) { + return func(ctx context.Context, level tracelog.LogLevel, msg string, data map[string]any) { if level == tracelog.LogLevelInfo { level = tracelog.LogLevelDebug } @@ -299,3 +299,22 @@ func SleepOnErr(ctx context.Context, err error, retries uint8) { case <-ctx.Done(): } } + +// ConfigureDefaultQueryExecMode parses a Postgres URI and determines if a default_query_exec_mode +// has been specified. If not, it defaults to "exec". +// SpiceDB queries have high variability of arguments and rarely benefit from using prepared statements. +// The default and recommended query exec mode is 'exec', which has shown the best performance under various +// synthetic workloads. See more in https://spicedb.dev/d/query-exec-mode. +// +// The docs for the different execution modes offered by pgx may be found +// here: https://pkg.go.dev/github.com/jackc/pgx/v5#QueryExecMode +func ConfigureDefaultQueryExecMode(config *pgx.ConnConfig) { + if !strings.Contains(config.ConnString(), "default_query_exec_mode") { + // the execution mode was not overridden by the user + config.DefaultQueryExecMode = pgx.QueryExecModeExec + } + + log.Info(). + Str("details-url", "https://spicedb.dev/d/query-exec-mode"). + Msg("found default_query_exec_mode in DB URI; leaving as-is") +} diff --git a/internal/datastore/postgres/debug.go b/internal/datastore/postgres/debug.go index dde0c565e5..b8c0fd2292 100644 --- a/internal/datastore/postgres/debug.go +++ b/internal/datastore/postgres/debug.go @@ -22,7 +22,7 @@ func (pgd *pgDatastore) PreExplainStatements() []string { return nil } -func (pgd *pgDatastore) BuildExplainQuery(sql string, args []interface{}) (string, []any, error) { +func (pgd *pgDatastore) BuildExplainQuery(sql string, args []any) (string, []any, error) { return "EXPLAIN (FORMAT JSON) " + sql, args, nil } diff --git a/internal/datastore/postgres/log_tracer.go b/internal/datastore/postgres/log_tracer.go index c240d5680d..38c1fd3873 100644 --- a/internal/datastore/postgres/log_tracer.go +++ b/internal/datastore/postgres/log_tracer.go @@ -10,7 +10,7 @@ import ( type tracingLogger struct{} -func (tl tracingLogger) Log(ctx context.Context, level tracelog.LogLevel, msg string, _ map[string]interface{}) { +func (tl tracingLogger) Log(ctx context.Context, level tracelog.LogLevel, msg string, _ map[string]any) { span := trace.SpanFromContext(ctx) span.AddEvent(msg, trace.WithAttributes(attribute.Stringer("level", level), attribute.String("datastore", "postgres"))) } diff --git a/internal/datastore/postgres/migrations/driver.go b/internal/datastore/postgres/migrations/driver.go index bf4a284572..1054ecde43 100644 --- a/internal/datastore/postgres/migrations/driver.go +++ b/internal/datastore/postgres/migrations/driver.go @@ -38,6 +38,7 @@ func NewAlembicPostgresDriver(ctx context.Context, url string, credentialsProvid } pgxcommon.ConfigurePGXLogger(connConfig) pgxcommon.ConfigureOTELTracer(connConfig, includeQueryParametersInTraces) + pgxcommon.ConfigureDefaultQueryExecMode(connConfig) if credentialsProvider != nil { log.Ctx(ctx).Debug().Str("name", credentialsProvider.Name()).Msg("using credentials provider") diff --git a/internal/datastore/postgres/postgres.go b/internal/datastore/postgres/postgres.go index 5fd9b5ec91..4b5442bb2e 100644 --- a/internal/datastore/postgres/postgres.go +++ b/internal/datastore/postgres/postgres.go @@ -8,7 +8,6 @@ import ( "math/rand/v2" "os" "strconv" - "strings" "sync/atomic" "time" @@ -92,7 +91,7 @@ var ( ) type sqlFilter interface { - ToSql() (string, []interface{}, error) + ToSql() (string, []any, error) } // NewPostgresDatastore initializes a SpiceDB datastore that uses a PostgreSQL @@ -142,14 +141,14 @@ func newPostgresDatastore( } // Parse the DB URI into configuration. - parsedConfig, err := pgxpool.ParseConfig(pgURL) + pgConfig, err := pgxpool.ParseConfig(pgURL) if err != nil { return nil, common.RedactAndLogSensitiveConnString(ctx, errUnableToInstantiate, err, pgURL) } // Setup the default custom plan setting, if applicable. // Setup the default query execution mode setting, if applicable. - pgConfig := DefaultQueryExecMode(parsedConfig) + pgxcommon.ConfigureDefaultQueryExecMode(pgConfig.ConnConfig) // Setup the credentials provider var credentialsProvider datastore.CredentialsProvider @@ -820,25 +819,4 @@ func currentlyLivingObjects(original sq.SelectBuilder) sq.SelectBuilder { return original.Where(sq.Eq{schema.ColDeletedXid: liveDeletedTxnID}) } -// DefaultQueryExecMode parses a Postgres URI and determines if a default_query_exec_mode -// has been specified. If not, it defaults to "exec". -// SpiceDB queries have high variability of arguments and rarely benefit from using prepared statements. -// The default and recommended query exec mode is 'exec', which has shown the best performance under various -// synthetic workloads. See more in https://spicedb.dev/d/query-exec-mode. -// -// The docs for the different execution modes offered by pgx may be found -// here: https://pkg.go.dev/github.com/jackc/pgx/v5#QueryExecMode -func DefaultQueryExecMode(poolConfig *pgxpool.Config) *pgxpool.Config { - if !strings.Contains(poolConfig.ConnString(), "default_query_exec_mode") { - // the execution mode was not overridden by the user - poolConfig.ConnConfig.DefaultQueryExecMode = pgx.QueryExecModeExec - return poolConfig - } - - log.Info(). - Str("details-url", "https://spicedb.dev/d/query-exec-mode"). - Msg("found default_query_exec_mode in DB URI; leaving as-is") - return poolConfig -} - var _ datastore.Datastore = &pgDatastore{} diff --git a/internal/datastore/postgres/postgres_shared_test.go b/internal/datastore/postgres/postgres_shared_test.go index 7c57f52e7b..85f816ef9f 100644 --- a/internal/datastore/postgres/postgres_shared_test.go +++ b/internal/datastore/postgres/postgres_shared_test.go @@ -1864,7 +1864,7 @@ func NullCaveatWatchTest(t *testing.T, ds datastore.Datastore) { rwt := drwt.(*pgReadWriteTXN) createInserts := writeTuple - valuesToWrite := []interface{}{ + valuesToWrite := []any{ "resource", "someresourceid", "somerelation", diff --git a/internal/datastore/postgres/postgres_test.go b/internal/datastore/postgres/postgres_test.go index b9a12c43b7..637a441b1b 100644 --- a/internal/datastore/postgres/postgres_test.go +++ b/internal/datastore/postgres/postgres_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/authzed/spicedb/internal/datastore/postgres/common" "github.com/authzed/spicedb/internal/datastore/postgres/version" testdatastore "github.com/authzed/spicedb/internal/testserver/datastore" @@ -85,14 +86,14 @@ func TestDefaultQueryExecMode(t *testing.T) { require.NoError(t, err) require.Equal(t, parsedConfig.ConnConfig.DefaultQueryExecMode, pgx.QueryExecModeCacheStatement) - pgConfig := DefaultQueryExecMode(parsedConfig) - require.Equal(t, pgConfig.ConnConfig.DefaultQueryExecMode, pgx.QueryExecModeExec) + common.ConfigureDefaultQueryExecMode(parsedConfig.ConnConfig) + require.Equal(t, parsedConfig.ConnConfig.DefaultQueryExecMode, pgx.QueryExecModeExec) } func TestDefaultQueryExecModeOverridden(t *testing.T) { parsedConfig, err := pgxpool.ParseConfig("postgres://username:password@localhost:5432/dbname?default_query_exec_mode=cache_statement") require.NoError(t, err) - pgConfig := DefaultQueryExecMode(parsedConfig) - require.Equal(t, pgConfig.ConnConfig.DefaultQueryExecMode, pgx.QueryExecModeCacheStatement) + common.ConfigureDefaultQueryExecMode(parsedConfig.ConnConfig) + require.Equal(t, parsedConfig.ConnConfig.DefaultQueryExecMode, pgx.QueryExecModeCacheStatement) } diff --git a/internal/datastore/postgres/readwrite.go b/internal/datastore/postgres/readwrite.go index 9dd97bed03..076e9e2d2d 100644 --- a/internal/datastore/postgres/readwrite.go +++ b/internal/datastore/postgres/readwrite.go @@ -1,6 +1,7 @@ package postgres import ( + "cmp" "context" "errors" "fmt" @@ -8,7 +9,6 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/ccoveille/go-safecast" "github.com/jackc/pgx/v5" - "github.com/jzelinskie/stringz" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -92,7 +92,7 @@ func appendForInsertion(builder sq.InsertBuilder, tpl tuple.Relationship) sq.Ins caveatContext = tpl.OptionalCaveat.Context.AsMap() } - valuesToWrite := []interface{}{ + valuesToWrite := []any{ tpl.Resource.ObjectType, tpl.Resource.ObjectID, tpl.Resource.Relation, @@ -462,7 +462,7 @@ func (rwt *pgReadWriteTXN) deleteRelationshipsWithLimit(ctx context.Context, fil query = query.Where(sq.Eq{schema.ColUsersetObjectID: subjectFilter.OptionalSubjectId}) } if relationFilter := subjectFilter.OptionalRelation; relationFilter != nil { - query = query.Where(sq.Eq{schema.ColUsersetRelation: stringz.DefaultEmpty(relationFilter.Relation, datastore.Ellipsis)}) + query = query.Where(sq.Eq{schema.ColUsersetRelation: cmp.Or(relationFilter.Relation, datastore.Ellipsis)}) } } @@ -531,7 +531,7 @@ func (rwt *pgReadWriteTXN) deleteRelationships(ctx context.Context, filter *v1.R query = query.Where(sq.Eq{schema.ColUsersetObjectID: subjectFilter.OptionalSubjectId}) } if relationFilter := subjectFilter.OptionalRelation; relationFilter != nil { - query = query.Where(sq.Eq{schema.ColUsersetRelation: stringz.DefaultEmpty(relationFilter.Relation, datastore.Ellipsis)}) + query = query.Where(sq.Eq{schema.ColUsersetRelation: cmp.Or(relationFilter.Relation, datastore.Ellipsis)}) } } @@ -565,7 +565,7 @@ func (rwt *pgReadWriteTXN) WriteNamespaces(ctx context.Context, newConfigs ...*c deletedNamespaceClause = append(deletedNamespaceClause, sq.Eq{schema.ColNamespace: newNamespace.Name}) - valuesToWrite := []interface{}{newNamespace.Name, serialized} + valuesToWrite := []any{newNamespace.Name, serialized} writeQuery = writeQuery.Values(valuesToWrite...) } diff --git a/internal/datastore/postgres/snapshot.go b/internal/datastore/postgres/snapshot.go index 7d2f65658d..1843e0c307 100644 --- a/internal/datastore/postgres/snapshot.go +++ b/internal/datastore/postgres/snapshot.go @@ -32,7 +32,7 @@ type SnapshotCodec struct { pgtype.TextCodec } -func (SnapshotCodec) DecodeValue(tm *pgtype.Map, oid uint32, format int16, src []byte) (interface{}, error) { +func (SnapshotCodec) DecodeValue(tm *pgtype.Map, oid uint32, format int16, src []byte) (any, error) { if src == nil { return nil, nil } diff --git a/internal/datastore/postgres/strictreader.go b/internal/datastore/postgres/strictreader.go index 9cc4e31acb..cc0fad9b78 100644 --- a/internal/datastore/postgres/strictreader.go +++ b/internal/datastore/postgres/strictreader.go @@ -24,15 +24,15 @@ type strictReaderQueryFuncs struct { func (srqf strictReaderQueryFuncs) ExecFunc(ctx context.Context, tagFunc func(ctx context.Context, tag pgconn.CommandTag, err error) error, sql string, args ...any) error { // NOTE: it is *required* for the pgx.QueryExecModeSimpleProtocol to be added as pgx will otherwise wrap // the query as a prepared statement, which does *not* support running more than a single statement at a time. - return srqf.rewriteError(srqf.wrapped.ExecFunc(ctx, tagFunc, srqf.addAssertToSelectSQL(sql), append([]interface{}{pgx.QueryExecModeSimpleProtocol}, args...)...)) + return srqf.rewriteError(srqf.wrapped.ExecFunc(ctx, tagFunc, srqf.addAssertToSelectSQL(sql), append([]any{pgx.QueryExecModeSimpleProtocol}, args...)...)) } func (srqf strictReaderQueryFuncs) QueryFunc(ctx context.Context, rowsFunc func(ctx context.Context, rows pgx.Rows) error, sql string, args ...any) error { - return srqf.rewriteError(srqf.wrapped.QueryFunc(ctx, rowsFunc, srqf.addAssertToSelectSQL(sql), append([]interface{}{pgx.QueryExecModeSimpleProtocol}, args...)...)) + return srqf.rewriteError(srqf.wrapped.QueryFunc(ctx, rowsFunc, srqf.addAssertToSelectSQL(sql), append([]any{pgx.QueryExecModeSimpleProtocol}, args...)...)) } func (srqf strictReaderQueryFuncs) QueryRowFunc(ctx context.Context, rowFunc func(ctx context.Context, row pgx.Row) error, sql string, args ...any) error { - return srqf.rewriteError(srqf.wrapped.QueryRowFunc(ctx, rowFunc, srqf.addAssertToSelectSQL(sql), append([]interface{}{pgx.QueryExecModeSimpleProtocol}, args...)...)) + return srqf.rewriteError(srqf.wrapped.QueryRowFunc(ctx, rowFunc, srqf.addAssertToSelectSQL(sql), append([]any{pgx.QueryExecModeSimpleProtocol}, args...)...)) } func (srqf strictReaderQueryFuncs) rewriteError(err error) error { diff --git a/internal/datastore/postgres/strictreader_test.go b/internal/datastore/postgres/strictreader_test.go index 4c5ebc2ce2..cbdc638e54 100644 --- a/internal/datastore/postgres/strictreader_test.go +++ b/internal/datastore/postgres/strictreader_test.go @@ -24,7 +24,7 @@ func (mc fakeQuerier) QueryRowFunc(ctx context.Context, rowFunc func(ctx context return mc.err } -func (mc fakeQuerier) ExecFunc(_ context.Context, _ func(ctx context.Context, tag pgconn.CommandTag, err error) error, _ string, _ ...interface{}) error { +func (mc fakeQuerier) ExecFunc(_ context.Context, _ func(ctx context.Context, tag pgconn.CommandTag, err error) error, _ string, _ ...any) error { return mc.err } diff --git a/internal/datastore/postgres/testutil.go b/internal/datastore/postgres/testutil.go index e560cb4548..335f0f1909 100644 --- a/internal/datastore/postgres/testutil.go +++ b/internal/datastore/postgres/testutil.go @@ -40,7 +40,7 @@ type withQueryInterceptor struct { explanations map[string]string } -func (ql *withQueryInterceptor) InterceptExec(ctx context.Context, querier pgxcommon.Querier, sql string, args ...interface{}) (pgconn.CommandTag, error) { +func (ql *withQueryInterceptor) InterceptExec(ctx context.Context, querier pgxcommon.Querier, sql string, args ...any) (pgconn.CommandTag, error) { if strings.HasPrefix(sql, "WITH") { // Note, we disable seqscan here to ensure we get an index scan for testing. _, err := querier.Exec(ctx, "set enable_seqscan = off;") @@ -59,10 +59,10 @@ func (ql *withQueryInterceptor) InterceptExec(ctx context.Context, querier pgxco return querier.Exec(ctx, sql, args...) } -func (ql *withQueryInterceptor) InterceptQueryRow(ctx context.Context, querier pgxcommon.Querier, sql string, optionsAndArgs ...interface{}) pgx.Row { +func (ql *withQueryInterceptor) InterceptQueryRow(ctx context.Context, querier pgxcommon.Querier, sql string, optionsAndArgs ...any) pgx.Row { return querier.QueryRow(ctx, sql, optionsAndArgs...) } -func (ql *withQueryInterceptor) InterceptQuery(ctx context.Context, querier pgxcommon.Querier, sql string, args ...interface{}) (pgx.Rows, error) { +func (ql *withQueryInterceptor) InterceptQuery(ctx context.Context, querier pgxcommon.Querier, sql string, args ...any) (pgx.Rows, error) { return querier.Query(ctx, sql, args...) } diff --git a/internal/datastore/proxy/hedging_test.go b/internal/datastore/proxy/hedging_test.go index 26b054a272..e51074b0ab 100644 --- a/internal/datastore/proxy/hedging_test.go +++ b/internal/datastore/proxy/hedging_test.go @@ -40,17 +40,17 @@ func TestDatastoreRequestHedging(t *testing.T) { testCases := []struct { methodName string useSnapshotReader bool - arguments []interface{} - firstCallResults []interface{} - secondCallResults []interface{} + arguments []any + firstCallResults []any + secondCallResults []any f testFunc }{ { "ReadNamespaceByName", true, - []interface{}{nsKnown}, - []interface{}{&core.NamespaceDefinition{}, revisionKnown, errKnown}, - []interface{}{&core.NamespaceDefinition{}, anotherRevisionKnown, errKnown}, + []any{nsKnown}, + []any{&core.NamespaceDefinition{}, revisionKnown, errKnown}, + []any{&core.NamespaceDefinition{}, anotherRevisionKnown, errKnown}, func(t *testing.T, proxy datastore.Datastore, expectFirst bool) { require := require.New(t) _, rev, err := proxy.SnapshotReader(datastore.NoRevision).ReadNamespaceByName(t.Context(), nsKnown) @@ -65,9 +65,9 @@ func TestDatastoreRequestHedging(t *testing.T) { { "OptimizedRevision", false, - []interface{}{mock.Anything, mock.Anything}, - []interface{}{revisionKnown, errKnown}, - []interface{}{anotherRevisionKnown, errKnown}, + []any{mock.Anything, mock.Anything}, + []any{revisionKnown, errKnown}, + []any{anotherRevisionKnown, errKnown}, func(t *testing.T, proxy datastore.Datastore, expectFirst bool) { require := require.New(t) rev, err := proxy.OptimizedRevision(t.Context()) @@ -82,9 +82,9 @@ func TestDatastoreRequestHedging(t *testing.T) { { "HeadRevision", false, - []interface{}{mock.Anything}, - []interface{}{revisionKnown, errKnown}, - []interface{}{anotherRevisionKnown, errKnown}, + []any{mock.Anything}, + []any{revisionKnown, errKnown}, + []any{anotherRevisionKnown, errKnown}, func(t *testing.T, proxy datastore.Datastore, expectFirst bool) { require := require.New(t) rev, err := proxy.HeadRevision(t.Context()) @@ -99,9 +99,9 @@ func TestDatastoreRequestHedging(t *testing.T) { { "QueryRelationships", true, - []interface{}{mock.Anything, mock.Anything}, - []interface{}{emptyIterator, errKnown}, - []interface{}{emptyIterator, errAnotherKnown}, + []any{mock.Anything, mock.Anything}, + []any{emptyIterator, errKnown}, + []any{emptyIterator, errAnotherKnown}, func(t *testing.T, proxy datastore.Datastore, expectFirst bool) { require := require.New(t) _, err := proxy. @@ -117,9 +117,9 @@ func TestDatastoreRequestHedging(t *testing.T) { { "ReverseQueryRelationships", true, - []interface{}{mock.Anything, mock.Anything}, - []interface{}{emptyIterator, errKnown}, - []interface{}{emptyIterator, errAnotherKnown}, + []any{mock.Anything, mock.Anything}, + []any{emptyIterator, errKnown}, + []any{emptyIterator, errAnotherKnown}, func(t *testing.T, proxy datastore.Datastore, expectFirst bool) { require := require.New(t) _, err := proxy. diff --git a/internal/datastore/proxy/proxy_test/mock.go b/internal/datastore/proxy/proxy_test/mock.go index 44c951b80e..94b32ecd20 100644 --- a/internal/datastore/proxy/proxy_test/mock.go +++ b/internal/datastore/proxy/proxy_test/mock.go @@ -125,7 +125,7 @@ func (dm *MockReader) QueryRelationships( filter datastore.RelationshipsFilter, options ...options.QueryOptionsOption, ) (datastore.RelationshipIterator, error) { - callArgs := make([]interface{}, 0, len(options)+1) + callArgs := make([]any, 0, len(options)+1) callArgs = append(callArgs, filter) for _, option := range options { callArgs = append(callArgs, option) @@ -145,7 +145,7 @@ func (dm *MockReader) ReverseQueryRelationships( subjectsFilter datastore.SubjectsFilter, options ...options.ReverseQueryOptionsOption, ) (datastore.RelationshipIterator, error) { - callArgs := make([]interface{}, 0, len(options)+1) + callArgs := make([]any, 0, len(options)+1) callArgs = append(callArgs, subjectsFilter) for _, option := range options { callArgs = append(callArgs, option) @@ -224,7 +224,7 @@ func (dm *MockReadWriteTransaction) QueryRelationships( filter datastore.RelationshipsFilter, options ...options.QueryOptionsOption, ) (datastore.RelationshipIterator, error) { - callArgs := make([]interface{}, 0, len(options)+1) + callArgs := make([]any, 0, len(options)+1) callArgs = append(callArgs, filter) for _, option := range options { callArgs = append(callArgs, option) @@ -244,7 +244,7 @@ func (dm *MockReadWriteTransaction) ReverseQueryRelationships( subjectsFilter datastore.SubjectsFilter, options ...options.ReverseQueryOptionsOption, ) (datastore.RelationshipIterator, error) { - callArgs := make([]interface{}, 0, len(options)+1) + callArgs := make([]any, 0, len(options)+1) callArgs = append(callArgs, subjectsFilter) for _, option := range options { callArgs = append(callArgs, option) diff --git a/internal/datastore/revisions/optimized.go b/internal/datastore/revisions/optimized.go index 3a5a9190d9..df34dee65b 100644 --- a/internal/datastore/revisions/optimized.go +++ b/internal/datastore/revisions/optimized.go @@ -62,7 +62,7 @@ func (cor *CachedOptimizedRevisions) OptimizedRevision(ctx context.Context) (dat } cor.RUnlock() - newQuantizedRevision, err, _ := cor.updateGroup.Do("", func() (interface{}, error) { + newQuantizedRevision, err, _ := cor.updateGroup.Do("", func() (any, error) { log.Ctx(ctx).Debug().Time("now", localNow).Msg("computing new revision") span.AddEvent("computing new revision") diff --git a/internal/datastore/revisions/optimized_test.go b/internal/datastore/revisions/optimized_test.go index 4131900a74..db0d13468f 100644 --- a/internal/datastore/revisions/optimized_test.go +++ b/internal/datastore/revisions/optimized_test.go @@ -8,12 +8,12 @@ import ( "github.com/benbjohnson/clock" "github.com/ccoveille/go-safecast" - "github.com/samber/lo" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/authzed/spicedb/pkg/datastore" + "github.com/authzed/spicedb/pkg/genutil/slicez" ) type trackingRevisionFunction struct { @@ -130,7 +130,7 @@ func TestOptimizedRevisionCache(t *testing.T) { require.Eventually(func() bool { revision, err := or.OptimizedRevision(ctx) require.NoError(err) - printableRevSet := lo.Map(expectedRevSet, func(val datastore.Revision, index int) string { + printableRevSet := slicez.Map(expectedRevSet, func(val datastore.Revision) string { return val.String() }) require.Contains(expectedRevSet, revision, "must return the proper revision, allowed set %#v, received %s", printableRevSet, revision) diff --git a/internal/datastore/spanner/readwrite.go b/internal/datastore/spanner/readwrite.go index 66e5e89c06..9fa929b055 100644 --- a/internal/datastore/spanner/readwrite.go +++ b/internal/datastore/spanner/readwrite.go @@ -1,13 +1,13 @@ package spanner import ( + "cmp" "context" "fmt" "cloud.google.com/go/spanner" sq "github.com/Masterminds/squirrel" "github.com/ccoveille/go-safecast" - "github.com/jzelinskie/stringz" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -282,7 +282,7 @@ func deleteWithFilterAndNoLimit(ctx context.Context, rwt *spanner.ReadWriteTrans } type builder[T any] interface { - Where(pred interface{}, args ...interface{}) T + Where(pred any, args ...any) T } func applyFilterToQuery[T builder[T]](query T, filter *v1.RelationshipFilter) (T, error) { @@ -311,7 +311,7 @@ func applyFilterToQuery[T builder[T]](query T, filter *v1.RelationshipFilter) (T query = query.Where(sq.Eq{colUsersetObjectID: subjectFilter.OptionalSubjectId}) } if relationFilter := subjectFilter.OptionalRelation; relationFilter != nil { - query = query.Where(sq.Eq{colUsersetRelation: stringz.DefaultEmpty(relationFilter.Relation, datastore.Ellipsis)}) + query = query.Where(sq.Eq{colUsersetRelation: cmp.Or(relationFilter.Relation, datastore.Ellipsis)}) } } diff --git a/internal/datastore/spanner/spanner_test.go b/internal/datastore/spanner/spanner_test.go index f13bf52c92..d9a7d3dd6f 100644 --- a/internal/datastore/spanner/spanner_test.go +++ b/internal/datastore/spanner/spanner_test.go @@ -120,7 +120,7 @@ func FakeStatsTest(t *testing.T, ds datastore.Datastore) { // Add some stats row with a byte count. _, err = spannerClient.Apply(ctx, []*spanner.Mutation{ - spanner.Insert("fake_stats_table", []string{"interval_end", "table_name", "used_bytes"}, []interface{}{ + spanner.Insert("fake_stats_table", []string{"interval_end", "table_name", "used_bytes"}, []any{ time.Now().UTC().Add(-100 * time.Second), tableRelationship, 100, }), }) diff --git a/internal/dispatch/graph/lookupsubjects_test.go b/internal/dispatch/graph/lookupsubjects_test.go index 0f6013caae..6f0ee7c658 100644 --- a/internal/dispatch/graph/lookupsubjects_test.go +++ b/internal/dispatch/graph/lookupsubjects_test.go @@ -906,18 +906,18 @@ func TestLookupSubjectsOverSchema(t *testing.T) { { SubjectId: "tom", CaveatExpression: caveatAnd( - caveatAndCtx("caveat1", map[string]interface{}{"someparam1": 42}), - caveatAndCtx("caveat2", map[string]interface{}{"someparam2": 43}), + caveatAndCtx("caveat1", map[string]any{"someparam1": 42}), + caveatAndCtx("caveat2", map[string]any{"someparam2": 43}), ), }, { SubjectId: "fred", CaveatExpression: caveatAnd( caveatAnd( - caveatAndCtx("caveat1", map[string]interface{}{"someparam1": 42}), - caveatAndCtx("caveat2", map[string]interface{}{"someparam2": 43}), + caveatAndCtx("caveat1", map[string]any{"someparam1": 42}), + caveatAndCtx("caveat2", map[string]any{"someparam2": 43}), ), - caveatAndCtx("anothercaveat", map[string]interface{}{"anotherparam": 43}), + caveatAndCtx("anothercaveat", map[string]any{"anotherparam": 43}), ), }, }, diff --git a/internal/graph/check.go b/internal/graph/check.go index 04513d783c..d326672747 100644 --- a/internal/graph/check.go +++ b/internal/graph/check.go @@ -7,7 +7,6 @@ import ( "time" "github.com/prometheus/client_golang/prometheus" - "github.com/samber/lo" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" "google.golang.org/protobuf/types/known/durationpb" @@ -22,6 +21,7 @@ import ( "github.com/authzed/spicedb/pkg/datastore/options" "github.com/authzed/spicedb/pkg/datastore/queryshape" "github.com/authzed/spicedb/pkg/genutil/mapz" + "github.com/authzed/spicedb/pkg/genutil/slicez" "github.com/authzed/spicedb/pkg/middleware/nodeid" nspkg "github.com/authzed/spicedb/pkg/namespace" core "github.com/authzed/spicedb/pkg/proto/core/v1" @@ -193,7 +193,7 @@ func (cc *ConcurrentChecker) checkInternal(ctx context.Context, req ValidatedChe } // Deduplicate any incoming resource IDs. - resourceIds := lo.Uniq(req.ResourceIds) + resourceIds := slicez.Unique(req.ResourceIds) // Filter the incoming resource IDs for any which match the subject directly. For example, if we receive // a check for resource `user:{tom, fred, sarah}#...` and a subject of `user:sarah#...`, then we know diff --git a/internal/graph/membershipset_test.go b/internal/graph/membershipset_test.go index 202438fa2d..c8dcbaf4fc 100644 --- a/internal/graph/membershipset_test.go +++ b/internal/graph/membershipset_test.go @@ -1,11 +1,12 @@ package graph import ( + "maps" + "slices" "sort" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" "google.golang.org/protobuf/types/known/structpb" "github.com/authzed/spicedb/internal/caveats" @@ -762,7 +763,7 @@ func TestMembershipSetUnionWithNonMemberEntries(t *testing.T) { }, }) - keys := maps.Keys(ms.membersByID) + keys := slices.Collect(maps.Keys(ms.membersByID)) sort.Strings(keys) require.Equal(t, 2, ms.Size()) @@ -786,7 +787,7 @@ func TestMembershipSetIntersectWithNonMemberEntries(t *testing.T) { require.Equal(t, 1, ms.Size()) require.True(t, ms.HasDeterminedMember()) - require.Equal(t, []string{"resource2"}, maps.Keys(ms.membersByID)) + require.Equal(t, []string{"resource2"}, slices.Collect(maps.Keys(ms.membersByID))) } func TestMembershipSetSubtractWithNonMemberEntries(t *testing.T) { @@ -806,7 +807,7 @@ func TestMembershipSetSubtractWithNonMemberEntries(t *testing.T) { require.Equal(t, 1, ms.Size()) require.True(t, ms.HasDeterminedMember()) - require.Equal(t, []string{"resource1"}, maps.Keys(ms.membersByID)) + require.Equal(t, []string{"resource1"}, slices.Collect(maps.Keys(ms.membersByID))) } func unwrapCaveat(ce *core.CaveatExpression) *core.ContextualizedCaveat { diff --git a/internal/lsp/lspdefs.go b/internal/lsp/lspdefs.go index 0e3dd50466..5bd02508f0 100644 --- a/internal/lsp/lspdefs.go +++ b/internal/lsp/lspdefs.go @@ -46,7 +46,7 @@ type InitializeParams struct { RootURI baselsp.DocumentURI `json:"rootUri,omitempty"` ClientInfo baselsp.ClientInfo `json:"clientInfo,omitempty"` Trace baselsp.Trace `json:"trace,omitempty"` - InitializationOptions interface{} `json:"initializationOptions,omitempty"` + InitializationOptions any `json:"initializationOptions,omitempty"` Capabilities ClientCapabilities `json:"capabilities"` WorkDoneToken string `json:"workDoneToken,omitempty"` diff --git a/internal/lsp/testutil.go b/internal/lsp/testutil.go index 151e0390dc..0fa09e81c6 100644 --- a/internal/lsp/testutil.go +++ b/internal/lsp/testutil.go @@ -71,7 +71,7 @@ func (lt *lspTester) setFileContents(path string, contents string) { }) } -func sendAndExpectError(lt *lspTester, method string, params interface{}) (*jsonrpc2.Error, serverState) { +func sendAndExpectError(lt *lspTester, method string, params any) (*jsonrpc2.Error, serverState) { paramsBytes, err := json.Marshal(params) require.NoError(lt.t, err) @@ -108,7 +108,7 @@ func sendAndExpectError(lt *lspTester, method string, params interface{}) (*json return nil, serverStateNotInitialized } -func sendAndReceive[T any](lt *lspTester, method string, params interface{}) (T, serverState) { +func sendAndReceive[T any](lt *lspTester, method string, params any) (T, serverState) { paramsBytes, err := json.Marshal(params) require.NoError(lt.t, err) diff --git a/internal/middleware/chain.go b/internal/middleware/chain.go index de08ffcee1..0d9c220516 100644 --- a/internal/middleware/chain.go +++ b/internal/middleware/chain.go @@ -17,9 +17,9 @@ import ( func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { n := len(interceptors) - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler { - return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) { + return func(currentCtx context.Context, currentReq any) (any, error) { return currentInter(currentCtx, currentReq, info, currentHandler) } } @@ -41,9 +41,9 @@ func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnarySer func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor { n := len(interceptors) - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { chainer := func(currentInter grpc.StreamServerInterceptor, currentHandler grpc.StreamHandler) grpc.StreamHandler { - return func(currentSrv interface{}, currentStream grpc.ServerStream) error { + return func(currentSrv any, currentStream grpc.ServerStream) error { return currentInter(currentSrv, currentStream, info, currentHandler) } } diff --git a/internal/middleware/datastore/datastore.go b/internal/middleware/datastore/datastore.go index 8c321b3d77..8df9cdc6fc 100644 --- a/internal/middleware/datastore/datastore.go +++ b/internal/middleware/datastore/datastore.go @@ -61,7 +61,7 @@ func ContextWithDatastore(ctx context.Context, datastore datastore.Datastore) co // UnaryServerInterceptor returns a new unary server interceptor that adds the // datastore to the context func UnaryServerInterceptor(datastore datastore.Datastore) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { newCtx := ContextWithHandle(ctx) if err := SetInContext(newCtx, datastore); err != nil { return nil, err @@ -74,7 +74,7 @@ func UnaryServerInterceptor(datastore datastore.Datastore) grpc.UnaryServerInter // StreamServerInterceptor returns a new stream server interceptor that adds the // datastore to the context func StreamServerInterceptor(datastore datastore.Datastore) grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wrapped := middleware.WrapServerStream(stream) wrapped.WrappedContext = ContextWithHandle(wrapped.WrappedContext) if err := SetInContext(wrapped.WrappedContext, datastore); err != nil { diff --git a/internal/middleware/dispatcher/dispatcher.go b/internal/middleware/dispatcher/dispatcher.go index c57618d0a7..1e720918cb 100644 --- a/internal/middleware/dispatcher/dispatcher.go +++ b/internal/middleware/dispatcher/dispatcher.go @@ -46,7 +46,7 @@ func SetInContext(ctx context.Context, dispatcher dispatch.Dispatcher) error { // UnaryServerInterceptor returns a new unary server interceptor that adds the // dispatcher to the context func UnaryServerInterceptor(dispatcher dispatch.Dispatcher) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { newCtx := ContextWithHandle(ctx) if err := SetInContext(newCtx, dispatcher); err != nil { return nil, err @@ -59,7 +59,7 @@ func UnaryServerInterceptor(dispatcher dispatch.Dispatcher) grpc.UnaryServerInte // StreamServerInterceptor returns a new stream server interceptor that adds the // dispatcher to the context func StreamServerInterceptor(dispatcher dispatch.Dispatcher) grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wrapped := middleware.WrapServerStream(stream) wrapped.WrappedContext = ContextWithHandle(wrapped.WrappedContext) if err := SetInContext(wrapped.WrappedContext, dispatcher); err != nil { diff --git a/internal/middleware/handwrittenvalidation/handwrittenvalidation.go b/internal/middleware/handwrittenvalidation/handwrittenvalidation.go index 2adc4b3e31..f2e4ab4254 100644 --- a/internal/middleware/handwrittenvalidation/handwrittenvalidation.go +++ b/internal/middleware/handwrittenvalidation/handwrittenvalidation.go @@ -14,7 +14,7 @@ type handwrittenValidator interface { // UnaryServerInterceptor returns a new unary server interceptor that runs the handwritten validation // on the incoming request, if any. -func UnaryServerInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { +func UnaryServerInterceptor(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { validator, ok := req.(handwrittenValidator) if ok { err := validator.HandwrittenValidate() @@ -28,7 +28,7 @@ func UnaryServerInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryS // StreamServerInterceptor returns a new stream server interceptor that runs the handwritten validation // on the incoming request messages, if any. -func StreamServerInterceptor(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error { +func StreamServerInterceptor(srv any, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wrapper := &recvWrapper{stream} return handler(srv, wrapper) } @@ -37,7 +37,7 @@ type recvWrapper struct { grpc.ServerStream } -func (s *recvWrapper) RecvMsg(m interface{}) error { +func (s *recvWrapper) RecvMsg(m any) error { if err := s.ServerStream.RecvMsg(m); err != nil { return err } diff --git a/internal/middleware/perfinsights/perfinsights_test.go b/internal/middleware/perfinsights/perfinsights_test.go index 56d2d7c05d..7e428a101d 100644 --- a/internal/middleware/perfinsights/perfinsights_test.go +++ b/internal/middleware/perfinsights/perfinsights_test.go @@ -264,7 +264,7 @@ var TestServiceServiceDesc = grpc.ServiceDesc{ Metadata: "test.proto", } -func ServiceUnaryCallHandlerForTesting(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func ServiceUnaryCallHandlerForTesting(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) { in := new(TestRequest) if err := dec(in); err != nil { return nil, err @@ -276,13 +276,13 @@ func ServiceUnaryCallHandlerForTesting(srv interface{}, ctx context.Context, dec Server: srv, FullMethod: "/perfinsights.TestService/UnaryCall", } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { + handler := func(ctx context.Context, req any) (any, error) { return srv.(TestServiceServer).UnaryCall(ctx, req.(*TestRequest)) } return interceptor(ctx, in, info, handler) } -func ServiceStreamCallHandlerForTesting(srv interface{}, stream grpc.ServerStream) error { +func ServiceStreamCallHandlerForTesting(srv any, stream grpc.ServerStream) error { return srv.(TestServiceServer).StreamCall(&testServiceStreamCallServer{stream}) } @@ -319,7 +319,7 @@ func TestUnaryRPCMetricReporting(t *testing.T) { require.NotNil(t, interceptor) // Create a handler that calls our service - handler := func(ctx context.Context, req interface{}) (interface{}, error) { + handler := func(ctx context.Context, req any) (any, error) { return service.UnaryCall(ctx, req.(*TestRequest)) } @@ -352,7 +352,7 @@ func TestStreamRPCMetricReporting(t *testing.T) { } // Create a handler that calls our service - handler := func(srv interface{}, stream grpc.ServerStream) error { + handler := func(srv any, stream grpc.ServerStream) error { return service.StreamCall(&testServiceStreamCallServer{stream}) } @@ -384,14 +384,14 @@ func (m *fakeServerStream) Context() context.Context { return m.ctx } -func (m *fakeServerStream) SendMsg(msg interface{}) error { +func (m *fakeServerStream) SendMsg(msg any) error { if resp, ok := msg.(*TestResponse); ok { m.sentMsgs = append(m.sentMsgs, resp) } return nil } -func (m *fakeServerStream) RecvMsg(msg interface{}) error { +func (m *fakeServerStream) RecvMsg(msg any) error { if m.recvIdx >= len(m.recvMsgs) { return io.EOF } diff --git a/internal/middleware/pertoken/pertoken.go b/internal/middleware/pertoken/pertoken.go index 5676791c33..d9db1526a1 100644 --- a/internal/middleware/pertoken/pertoken.go +++ b/internal/middleware/pertoken/pertoken.go @@ -75,7 +75,7 @@ func (m *MiddlewareForTesting) getOrCreateDatastore(ctx context.Context) (datast // UnaryServerInterceptor returns a new unary server interceptor that sets a separate in-memory datastore per token func (m *MiddlewareForTesting) UnaryServerInterceptor() grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { tokenDatastore, err := m.getOrCreateDatastore(ctx) if err != nil { return nil, err @@ -92,7 +92,7 @@ func (m *MiddlewareForTesting) UnaryServerInterceptor() grpc.UnaryServerIntercep // StreamServerInterceptor returns a new stream server interceptor that sets a separate in-memory datastore per token func (m *MiddlewareForTesting) StreamServerInterceptor() grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { tokenDatastore, err := m.getOrCreateDatastore(stream.Context()) if err != nil { return err diff --git a/internal/middleware/readonly/readonly.go b/internal/middleware/readonly/readonly.go index e1510f1178..25eddef942 100644 --- a/internal/middleware/readonly/readonly.go +++ b/internal/middleware/readonly/readonly.go @@ -12,7 +12,7 @@ import ( // UnaryServerInterceptor returns a new unary server interceptor that sets the datastore to readonly func UnaryServerInterceptor() grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { if err := datastoremw.SetInContext(ctx, proxy.NewReadonlyDatastore(datastoremw.MustFromContext(ctx))); err != nil { return nil, err } @@ -23,7 +23,7 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor { // StreamServerInterceptor returns a new stream server interceptor that sets the datastore to readonly func StreamServerInterceptor() grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wrapped := middleware.WrapServerStream(stream) if err := datastoremw.SetInContext(wrapped.WrappedContext, proxy.NewReadonlyDatastore(datastoremw.MustFromContext(stream.Context()))); err != nil { return err diff --git a/internal/middleware/servicespecific/servicespecific.go b/internal/middleware/servicespecific/servicespecific.go index 10fe753a33..50e51804a7 100644 --- a/internal/middleware/servicespecific/servicespecific.go +++ b/internal/middleware/servicespecific/servicespecific.go @@ -19,7 +19,7 @@ type ExtraStreamInterceptor interface { } // UnaryServerInterceptor returns a new unary server interceptor that runs bundled interceptors. -func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { +func UnaryServerInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { if hasExtraInterceptor, ok := info.Server.(ExtraUnaryInterceptor); ok { interceptor := hasExtraInterceptor.UnaryInterceptor() return interceptor(ctx, req, info, handler) @@ -29,7 +29,7 @@ func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.Una } // StreamServerInterceptor returns a new stream server interceptor that runs bundled interceptors. -func StreamServerInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { +func StreamServerInterceptor(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { if hasExtraInterceptor, ok := srv.(ExtraStreamInterceptor); ok { interceptor := hasExtraInterceptor.StreamInterceptor() return interceptor(srv, stream, info, handler) diff --git a/internal/namespace/canonicalization.go b/internal/namespace/canonicalization.go index 1583608582..b7fac3b627 100644 --- a/internal/namespace/canonicalization.go +++ b/internal/namespace/canonicalization.go @@ -243,7 +243,7 @@ func buildBddVarMap(relations []*core.Relation, aliasMap map[string]string) (bdd continue } - _, err := graph.WalkRewrite(rewrite, func(childOneof *core.SetOperation_Child) (interface{}, error) { + _, err := graph.WalkRewrite(rewrite, func(childOneof *core.SetOperation_Child) (any, error) { switch child := childOneof.ChildType.(type) { case *core.SetOperation_Child_TupleToUserset: key := child.TupleToUserset.Tupleset.Relation + "->" + child.TupleToUserset.ComputedUserset.Relation diff --git a/internal/namespace/caveats.go b/internal/namespace/caveats.go index 5ddfa9d739..2a05631c3c 100644 --- a/internal/namespace/caveats.go +++ b/internal/namespace/caveats.go @@ -2,8 +2,8 @@ package namespace import ( "fmt" - - "golang.org/x/exp/maps" + "maps" + "slices" "github.com/authzed/spicedb/pkg/caveats" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" @@ -41,7 +41,7 @@ func ValidateCaveatDefinition(ts *caveattypes.TypeSet, caveat *core.CaveatDefini ) } - referencedNames, err := deserialized.ReferencedParameters(maps.Keys(caveat.ParameterTypes)) + referencedNames, err := deserialized.ReferencedParameters(slices.Collect(maps.Keys(caveat.ParameterTypes))) if err != nil { return err } diff --git a/internal/relationships/validation.go b/internal/relationships/validation.go index ff4a6fb034..611f805c77 100644 --- a/internal/relationships/validation.go +++ b/internal/relationships/validation.go @@ -3,13 +3,12 @@ package relationships import ( "context" - "github.com/samber/lo" - "github.com/authzed/spicedb/internal/namespace" "github.com/authzed/spicedb/pkg/caveats" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" "github.com/authzed/spicedb/pkg/datastore" "github.com/authzed/spicedb/pkg/genutil/mapz" + "github.com/authzed/spicedb/pkg/genutil/slicez" ns "github.com/authzed/spicedb/pkg/namespace" core "github.com/authzed/spicedb/pkg/proto/core/v1" "github.com/authzed/spicedb/pkg/schema" @@ -25,7 +24,7 @@ func ValidateRelationshipUpdates( caveatTypeSet *caveattypes.TypeSet, updates []tuple.RelationshipUpdate, ) error { - rels := lo.Map(updates, func(item tuple.RelationshipUpdate, _ int) tuple.Relationship { + rels := slicez.Map(updates, func(item tuple.RelationshipUpdate) tuple.Relationship { return item.Relationship }) diff --git a/internal/services/integrationtesting/consistency_test.go b/internal/services/integrationtesting/consistency_test.go index ea641a5bfa..050fda1c68 100644 --- a/internal/services/integrationtesting/consistency_test.go +++ b/internal/services/integrationtesting/consistency_test.go @@ -5,14 +5,15 @@ package integrationtesting_test import ( "fmt" + "maps" "path" + "slices" "sort" "testing" "time" "github.com/jzelinskie/stringz" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" "google.golang.org/protobuf/types/known/structpb" yamlv2 "gopkg.in/yaml.v2" @@ -391,7 +392,10 @@ func validateLookupResources(t *testing.T, vctx validationContext) { } } - requireSameSets(t, maps.Keys(accessibleResources), maps.Keys(resolvedResources)) + requireSameSets(t, + slices.Collect(maps.Keys(accessibleResources)), + slices.Collect(maps.Keys(resolvedResources)), + ) // Ensure that every returned concrete object Checks directly. checkBulkItems := make([]*v1.CheckBulkPermissionsRequestItem, 0, len(resolvedResources)) @@ -477,7 +481,10 @@ func validateLookupSubjects(t *testing.T, vctx validationContext) { // permissions as their subject relation, or wildcards), this should be a // subset. expectedDefinedSubjects := vctx.accessibilitySet.DirectlyAccessibleDefinedSubjectsOfType(resource, subjectType) - requireSubsetOf(t, maps.Keys(resolvedSubjects), maps.Keys(expectedDefinedSubjects)) + requireSubsetOf(t, + slices.Collect(maps.Keys(resolvedSubjects)), + slices.Collect(maps.Keys(expectedDefinedSubjects)), + ) // Ensure all subjects in true and caveated assertions for the subject type are found // in the LookupSubject result, except those added via wildcard. @@ -695,7 +702,7 @@ func runAssertions(t *testing.T, vctx validationContext) { } // Check the assertion was returned for a direct (with context) lookup. - resolvedDirectResourceIds := maps.Keys(resolvedDirectResourcesMap) + resolvedDirectResourceIds := slices.Collect(maps.Keys(resolvedDirectResourcesMap)) switch permissionship { case v1.CheckPermissionResponse_PERMISSIONSHIP_NO_PERMISSION: require.NotContains(t, resolvedDirectResourceIds, rel.Resource.ObjectID, "Found unexpected object %s in direct lookup for assertion %s", rel.Resource, rel) @@ -710,7 +717,7 @@ func runAssertions(t *testing.T, vctx validationContext) { } // Check the assertion was returned for an indirect (without context) lookup. - resolvedIndirectResourceIds := maps.Keys(resolvedIndirectResourcesMap) + resolvedIndirectResourceIds := slices.Collect(maps.Keys(resolvedIndirectResourcesMap)) accessibility, _, _ := vctx.accessibilitySet.AccessibiliyAndPermissionshipFor(rel.Resource, rel.Subject) switch permissionship { @@ -831,7 +838,7 @@ func validateDevelopmentAssertions(t *testing.T, devContext *development.DevCont } } - assertionsMap := map[string]interface{}{ + assertionsMap := map[string]any{ "assertTrue": trueAssertions, "assertCaveated": caveatedAssertions, "assertFalse": falseAssertions, @@ -853,7 +860,7 @@ func validateDevelopmentAssertions(t *testing.T, devContext *development.DevCont // that expected. func validateDevelopmentExpectedRels(t *testing.T, devContext *development.DevContext, vctx validationContext) { // Build the Expected Relations (inputs only). - expectedMap := map[string]interface{}{} + expectedMap := map[string]any{} for relString, permissionship := range vctx.accessibilitySet.PermissionshipByRelationship { if permissionship == dispatchv1.ResourceCheckResult_NOT_MEMBER { continue diff --git a/internal/services/integrationtesting/consistencytestutil/accessibilityset.go b/internal/services/integrationtesting/consistencytestutil/accessibilityset.go index 950598a0f5..fe2acd5857 100644 --- a/internal/services/integrationtesting/consistencytestutil/accessibilityset.go +++ b/internal/services/integrationtesting/consistencytestutil/accessibilityset.go @@ -1,10 +1,11 @@ package consistencytestutil import ( + "maps" + "slices" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" "github.com/authzed/spicedb/internal/developmentmembership" "github.com/authzed/spicedb/internal/dispatch" @@ -303,7 +304,7 @@ func (as *AccessibilitySet) SubjectTypes() []tuple.RelationReference { for _, subject := range as.SubjectsByNamespace.Values() { subjectTypes[tuple.StringRR(subject.RelationReference())] = subject.RelationReference() } - return maps.Values(subjectTypes) + return slices.Collect(maps.Values(subjectTypes)) } // AllSubjectsNoWildcards returns all *defined*, non-wildcard subjects found. diff --git a/internal/services/server.go b/internal/services/server.go index d003235b54..a4844f0781 100644 --- a/internal/services/server.go +++ b/internal/services/server.go @@ -73,6 +73,7 @@ func RegisterGrpcServices( CaveatTypeSet: permSysConfig.CaveatTypeSet, AdditiveOnly: schemaServiceOption == V1SchemaServiceAdditiveOnly, ExpiringRelsEnabled: permSysConfig.ExpiringRelationshipsEnabled, + DeprecatedRelsEnabled: permSysConfig.DeprecatedRelationshipsEnabled, PerformanceInsightMetricsEnabled: permSysConfig.PerformanceInsightMetricsEnabled, } v1.RegisterSchemaServiceServer(srv, v1svc.NewSchemaServer(schemaConfig)) diff --git a/internal/services/shared/schema.go b/internal/services/shared/schema.go index 9f66e1631e..e31729b116 100644 --- a/internal/services/shared/schema.go +++ b/internal/services/shared/schema.go @@ -437,7 +437,7 @@ func sanityCheckNamespaceChanges( // errorIfTupleIteratorReturnsTuples takes a tuple iterator and any error that was generated // when the original iterator was created, and returns an error if iterator contains any tuples. -func errorIfTupleIteratorReturnsTuples(_ context.Context, qy datastore.RelationshipIterator, qyErr error, message string, args ...interface{}) error { +func errorIfTupleIteratorReturnsTuples(_ context.Context, qy datastore.RelationshipIterator, qyErr error, message string, args ...any) error { if qyErr != nil { return qyErr } diff --git a/internal/services/v1/bulkcheck.go b/internal/services/v1/bulkcheck.go index 232c52a8a4..8954513fad 100644 --- a/internal/services/v1/bulkcheck.go +++ b/internal/services/v1/bulkcheck.go @@ -1,12 +1,12 @@ package v1 import ( + "cmp" "context" "slices" "sync" "time" - "github.com/jzelinskie/stringz" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/durationpb" @@ -260,7 +260,7 @@ func (bc *bulkChecker) checkBulkPermissions(ctx context.Context, req *v1.CheckBu }, { NamespaceName: group.params.Subject.ObjectType, - RelationName: stringz.DefaultEmpty(group.params.Subject.Relation, graph.Ellipsis), + RelationName: cmp.Or(group.params.Subject.Relation, graph.Ellipsis), AllowEllipsis: true, }, }, ds) diff --git a/internal/services/v1/experimental.go b/internal/services/v1/experimental.go index feb0c30f76..72548ede5c 100644 --- a/internal/services/v1/experimental.go +++ b/internal/services/v1/experimental.go @@ -1,10 +1,12 @@ package v1 import ( + "cmp" "context" "errors" "fmt" "io" + "maps" "slices" "sort" "strings" @@ -12,8 +14,6 @@ import ( "github.com/ccoveille/go-safecast" grpcvalidate "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator" - "github.com/jzelinskie/stringz" - "github.com/samber/lo" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/timestamppb" @@ -180,7 +180,7 @@ func (a *bulkLoadAdapter) Next(_ context.Context) (*tuple.Relationship, error) { a.current.Resource.Relation = a.currentBatch[a.numSent].Relation a.current.Subject.ObjectType = a.currentBatch[a.numSent].Subject.Object.ObjectType a.current.Subject.ObjectID = a.currentBatch[a.numSent].Subject.Object.ObjectId - a.current.Subject.Relation = stringz.DefaultEmpty(a.currentBatch[a.numSent].Subject.OptionalRelation, tuple.Ellipsis) + a.current.Subject.Relation = cmp.Or(a.currentBatch[a.numSent].Subject.OptionalRelation, tuple.Ellipsis) if a.currentBatch[a.numSent].OptionalCaveat != nil { a.caveat.CaveatName = a.currentBatch[a.numSent].OptionalCaveat.CaveatName @@ -234,7 +234,7 @@ func extractBatchNewReferencedNamespacesAndCaveats( } } - return lo.Keys(newNamespaces), lo.Keys(newCaveats) + return slices.Collect(maps.Keys(newNamespaces)), slices.Collect(maps.Keys(newCaveats)) } // TODO: this is now duplicate code with ImportBulkRelationships diff --git a/internal/services/v1/experimental_test.go b/internal/services/v1/experimental_test.go index 723f7fbb8e..8908badb5d 100644 --- a/internal/services/v1/experimental_test.go +++ b/internal/services/v1/experimental_test.go @@ -12,7 +12,6 @@ import ( "github.com/ccoveille/go-safecast" "github.com/jzelinskie/stringz" - "github.com/scylladb/go-set" "github.com/stretchr/testify/require" "go.uber.org/goleak" "google.golang.org/grpc" @@ -183,7 +182,7 @@ func TestBulkExportRelationships(t *testing.T) { } totalToWrite := 1_000 - expectedRels := set.NewStringSetWithSize(totalToWrite) + expectedRels := mapz.NewSet[string]() batch := make([]*v1.Relationship, totalToWrite) for i := range batch { nsAndRel := nsAndRels[i%len(nsAndRels)] @@ -223,7 +222,7 @@ func TestBulkExportRelationships(t *testing.T) { var totalRead int remainingRels := expectedRels.Copy() - require.Equal(totalToWrite, expectedRels.Size()) + require.Equal(totalToWrite, expectedRels.Len()) var cursor *v1.Cursor var done bool @@ -252,7 +251,7 @@ func TestBulkExportRelationships(t *testing.T) { totalRead += len(batch.Relationships) for _, rel := range batch.Relationships { - remainingRels.Remove(tuple.MustV1RelString(rel)) + remainingRels.Delete(tuple.MustV1RelString(rel)) } } @@ -260,7 +259,7 @@ func TestBulkExportRelationships(t *testing.T) { } require.Equal(totalToWrite, totalRead) - require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.List()) + require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.AsSlice()) }) } } @@ -337,7 +336,7 @@ func TestBulkExportRelationshipsWithFilter(t *testing.T) { {tf.DocumentNS.Name, "expiring_viewer"}, } - expectedRels := set.NewStringSetWithSize(1000) + expectedRels := mapz.NewSet[string]() batch := make([]*v1.Relationship, 1000) for i := range batch { nsAndRel := nsAndRels[i%len(nsAndRels)] @@ -355,7 +354,7 @@ func TestBulkExportRelationshipsWithFilter(t *testing.T) { expectedRels.Add(tuple.MustV1RelString(v1rel)) } - require.Equal(tc.expectedCount, expectedRels.Size()) + require.Equal(tc.expectedCount, expectedRels.Len()) ctx := t.Context() writer, err := client.BulkImportRelationships(ctx) @@ -407,7 +406,7 @@ func TestBulkExportRelationshipsWithFilter(t *testing.T) { } require.True(remainingRels.Has(tuple.MustV1RelString(rel)), "relationship was not expected or was repeated: %s", rel) - remainingRels.Remove(tuple.MustV1RelString(rel)) + remainingRels.Delete(tuple.MustV1RelString(rel)) foundRels.Add(tuple.MustV1RelString(rel)) } @@ -417,7 +416,7 @@ func TestBulkExportRelationshipsWithFilter(t *testing.T) { // These are statically defined. expectedCount, _ := safecast.ToUint64(tc.expectedCount) require.Equal(expectedCount, totalRead, "found: %v", foundRels.AsSlice()) - require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.List()) + require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.AsSlice()) }) } } diff --git a/internal/services/v1/expreflection.go b/internal/services/v1/expreflection.go index ab034744cc..1a5c7b358c 100644 --- a/internal/services/v1/expreflection.go +++ b/internal/services/v1/expreflection.go @@ -1,11 +1,11 @@ package v1 import ( + "maps" + "slices" "sort" "strings" - "golang.org/x/exp/maps" - v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/caveats" @@ -651,7 +651,7 @@ func expCaveatAPIRepr(caveatDef *core.CaveatDefinition, expSchemaFilters *expSch } parameters := make([]*v1.ExpCaveatParameter, 0, len(caveatDef.ParameterTypes)) - paramNames := maps.Keys(caveatDef.ParameterTypes) + paramNames := slices.Collect(maps.Keys(caveatDef.ParameterTypes)) sort.Strings(paramNames) for _, paramName := range paramNames { diff --git a/internal/services/v1/grouping_test.go b/internal/services/v1/grouping_test.go index f142d3a2cb..2934982a96 100644 --- a/internal/services/v1/grouping_test.go +++ b/internal/services/v1/grouping_test.go @@ -1,13 +1,14 @@ package v1 import ( + "maps" "math" + "slices" "sort" "strings" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" @@ -204,7 +205,7 @@ func TestGroupItems(t *testing.T) { if tt.err != "" { require.ErrorContains(t, err, tt.err) } else { - ccp := maps.Values(ccpByHash) + ccp := slices.Collect(maps.Values(ccpByHash)) require.NoError(t, err) require.Equal(t, len(tt.groupings), len(ccp)) diff --git a/internal/services/v1/hash_nonwasm.go b/internal/services/v1/hash_nonwasm.go index fad4a409d6..ce2a51c52a 100644 --- a/internal/services/v1/hash_nonwasm.go +++ b/internal/services/v1/hash_nonwasm.go @@ -5,10 +5,11 @@ package v1 import ( "fmt" + "maps" + "slices" "sort" "github.com/cespare/xxhash/v2" - "golang.org/x/exp/maps" ) func computeAPICallHash(apiName string, arguments map[string]string) (string, error) { @@ -23,7 +24,7 @@ func computeAPICallHash(apiName string, arguments map[string]string) (string, er return "", err } - keys := maps.Keys(arguments) + keys := slices.Collect(maps.Keys(arguments)) sort.Strings(keys) for _, key := range keys { diff --git a/internal/services/v1/hash_wasm.go b/internal/services/v1/hash_wasm.go index 4c75aa07b0..6f36e54e63 100644 --- a/internal/services/v1/hash_wasm.go +++ b/internal/services/v1/hash_wasm.go @@ -3,9 +3,9 @@ package v1 import ( "crypto/sha256" "fmt" + "maps" + "slices" "sort" - - "golang.org/x/exp/maps" ) func computeAPICallHash(apiName string, arguments map[string]string) (string, error) { @@ -21,7 +21,7 @@ func computeAPICallHash(apiName string, arguments map[string]string) (string, er return "", err } - keys := maps.Keys(arguments) + keys := slices.Collect(maps.Keys(arguments)) sort.Strings(keys) for _, key := range keys { diff --git a/internal/services/v1/permissions.go b/internal/services/v1/permissions.go index f7aeaa5631..5e1d098755 100644 --- a/internal/services/v1/permissions.go +++ b/internal/services/v1/permissions.go @@ -1,6 +1,7 @@ package v1 import ( + "cmp" "context" "errors" "fmt" @@ -8,7 +9,6 @@ import ( "slices" "strings" - "github.com/jzelinskie/stringz" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" @@ -327,7 +327,7 @@ func TranslateRelationshipTree(tree *v1.PermissionRelationshipTree) *core.Relati Subject: &core.ObjectAndRelation{ Namespace: subj.Object.ObjectType, ObjectId: subj.Object.ObjectId, - Relation: stringz.DefaultEmpty(subj.OptionalRelation, graph.Ellipsis), + Relation: cmp.Or(subj.OptionalRelation, graph.Ellipsis), }, }) } @@ -624,7 +624,7 @@ func (ps *permissionServer) LookupSubjects(req *v1.LookupSubjectsRequest, resp v }, { NamespaceName: req.SubjectObjectType, - RelationName: stringz.DefaultEmpty(req.OptionalSubjectRelation, tuple.Ellipsis), + RelationName: cmp.Or(req.OptionalSubjectRelation, tuple.Ellipsis), AllowEllipsis: true, }, }, ds); err != nil { @@ -716,7 +716,7 @@ func (ps *permissionServer) LookupSubjects(req *v1.LookupSubjectsRequest, resp v ResourceIds: []string{req.Resource.ObjectId}, SubjectRelation: &core.RelationReference{ Namespace: req.SubjectObjectType, - Relation: stringz.DefaultEmpty(req.OptionalSubjectRelation, tuple.Ellipsis), + Relation: cmp.Or(req.OptionalSubjectRelation, tuple.Ellipsis), }, }, stream) @@ -840,7 +840,7 @@ func (a *loadBulkAdapter) Next(_ context.Context) (*tuple.Relationship, error) { a.current.Resource.Relation = a.currentBatch[a.numSent].Relation a.current.Subject.ObjectType = a.currentBatch[a.numSent].Subject.Object.ObjectType a.current.Subject.ObjectID = a.currentBatch[a.numSent].Subject.Object.ObjectId - a.current.Subject.Relation = stringz.DefaultEmpty(a.currentBatch[a.numSent].Subject.OptionalRelation, tuple.Ellipsis) + a.current.Subject.Relation = cmp.Or(a.currentBatch[a.numSent].Subject.OptionalRelation, tuple.Ellipsis) if a.currentBatch[a.numSent].OptionalCaveat != nil { a.caveat.CaveatName = a.currentBatch[a.numSent].OptionalCaveat.CaveatName diff --git a/internal/services/v1/permissions_test.go b/internal/services/v1/permissions_test.go index 65b9f30819..543d9285fb 100644 --- a/internal/services/v1/permissions_test.go +++ b/internal/services/v1/permissions_test.go @@ -15,7 +15,6 @@ import ( "time" "github.com/ccoveille/go-safecast" - "github.com/scylladb/go-set" "github.com/stretchr/testify/require" "go.uber.org/goleak" "google.golang.org/genproto/googleapis/rpc/errdetails" @@ -2237,7 +2236,7 @@ func TestExportBulkRelationships(t *testing.T) { } totalToWrite := 1_000 - expectedRels := set.NewStringSetWithSize(totalToWrite) + expectedRels := mapz.NewSet[string]() batch := make([]*v1.Relationship, totalToWrite) for i := range batch { nsAndRel := nsAndRels[i%len(nsAndRels)] @@ -2277,7 +2276,7 @@ func TestExportBulkRelationships(t *testing.T) { var totalRead int remainingRels := expectedRels.Copy() - require.Equal(totalToWrite, expectedRels.Size()) + require.Equal(totalToWrite, expectedRels.Len()) var cursor *v1.Cursor var done bool @@ -2306,7 +2305,7 @@ func TestExportBulkRelationships(t *testing.T) { totalRead += len(batch.Relationships) for _, rel := range batch.Relationships { - remainingRels.Remove(tuple.MustV1RelString(rel)) + remainingRels.Delete(tuple.MustV1RelString(rel)) } } @@ -2314,7 +2313,7 @@ func TestExportBulkRelationships(t *testing.T) { } require.Equal(totalToWrite, totalRead) - require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.List()) + require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.AsSlice()) }) } } @@ -2388,7 +2387,7 @@ func TestExportBulkRelationshipsWithFilter(t *testing.T) { {tf.DocumentNS.Name, "expiring_viewer"}, } - expectedRels := set.NewStringSetWithSize(1000) + expectedRels := mapz.NewSet[string]() batch := make([]*v1.Relationship, 1000) for i := range batch { nsAndRel := nsAndRels[i%len(nsAndRels)] @@ -2406,7 +2405,7 @@ func TestExportBulkRelationshipsWithFilter(t *testing.T) { expectedRels.Add(tuple.MustV1RelString(v1rel)) } - require.Equal(tc.expectedCount, expectedRels.Size()) + require.Equal(tc.expectedCount, expectedRels.Len()) ctx := t.Context() writer, err := client.ImportBulkRelationships(ctx) @@ -2458,7 +2457,7 @@ func TestExportBulkRelationshipsWithFilter(t *testing.T) { } require.True(remainingRels.Has(tuple.MustV1RelString(rel)), "relationship was not expected or was repeated: %s", rel) - remainingRels.Remove(tuple.MustV1RelString(rel)) + remainingRels.Delete(tuple.MustV1RelString(rel)) foundRels.Add(tuple.MustV1RelString(rel)) } @@ -2468,7 +2467,7 @@ func TestExportBulkRelationshipsWithFilter(t *testing.T) { // These are statically defined. expectedCount, _ := safecast.ToUint64(tc.expectedCount) require.Equal(expectedCount, totalRead, "found: %v", foundRels.AsSlice()) - require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.List()) + require.True(remainingRels.IsEmpty(), "rels were not exported %#v", remainingRels.AsSlice()) }) } } diff --git a/internal/services/v1/reflectionapi.go b/internal/services/v1/reflectionapi.go index 9686482cc0..c101299e1a 100644 --- a/internal/services/v1/reflectionapi.go +++ b/internal/services/v1/reflectionapi.go @@ -1,11 +1,11 @@ package v1 import ( + "maps" + "slices" "sort" "strings" - "golang.org/x/exp/maps" - v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" "github.com/authzed/spicedb/pkg/caveats" @@ -651,7 +651,7 @@ func caveatAPIRepr(caveatDef *core.CaveatDefinition, schemaFilters *schemaFilter } parameters := make([]*v1.ReflectionCaveatParameter, 0, len(caveatDef.ParameterTypes)) - paramNames := maps.Keys(caveatDef.ParameterTypes) + paramNames := slices.Collect(maps.Keys(caveatDef.ParameterTypes)) sort.Strings(paramNames) for _, paramName := range paramNames { diff --git a/internal/services/v1/relationships.go b/internal/services/v1/relationships.go index f6d175cb70..83fde5fab2 100644 --- a/internal/services/v1/relationships.go +++ b/internal/services/v1/relationships.go @@ -1,12 +1,12 @@ package v1 import ( + "cmp" "context" "fmt" "time" grpcvalidate "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator" - "github.com/jzelinskie/stringz" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.opentelemetry.io/otel/trace" @@ -105,6 +105,9 @@ type PermissionsServerConfig struct { // ExpiringRelationshipsEnabled defines whether or not expiring relationships are enabled. ExpiringRelationshipsEnabled bool + // DeprecatedRelationshipsEnabled defines whether or not deprecated relationships are enabled. + DeprecatedRelationshipsEnabled bool + // CaveatTypeSet is the set of caveat types to use for caveats. If not specified, // the default type set is used. CaveatTypeSet *caveattypes.TypeSet @@ -134,6 +137,7 @@ func NewPermissionsServer( MaxCheckBulkConcurrency: defaultIfZero(config.MaxCheckBulkConcurrency, 50), CaveatTypeSet: caveattypes.TypeSetOrDefault(config.CaveatTypeSet), ExpiringRelationshipsEnabled: config.ExpiringRelationshipsEnabled, + DeprecatedRelationshipsEnabled: config.DeprecatedRelationshipsEnabled, PerformanceInsightMetricsEnabled: config.PerformanceInsightMetricsEnabled, } @@ -326,7 +330,7 @@ func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.Writ updateRelationshipSet := mapz.NewSet[string]() for _, update := range req.Updates { // TODO(jschorr): Change to struct-based keys. - if err := checkForDeprecatedRelationships(ctx, update, ds); err != nil { + if err := checkForDeprecatedRelationships(ctx, update, ds, ps); err != nil { return nil, ps.rewriteError(ctx, err) } @@ -554,7 +558,7 @@ func checkFilterComponent(ctx context.Context, objectType, optionalRelation stri return nil } - relationToTest := stringz.DefaultEmpty(optionalRelation, datastore.Ellipsis) + relationToTest := cmp.Or(optionalRelation, datastore.Ellipsis) allowEllipsis := optionalRelation == "" return namespace.CheckNamespaceAndRelation(ctx, objectType, relationToTest, allowEllipsis, ds) } @@ -627,7 +631,7 @@ func labelsForFilter(filter *v1.RelationshipFilter) perfinsights.APIShapeLabels } } -func checkForDeprecatedRelationships(ctx context.Context, update *v1.RelationshipUpdate, ds datastore.Datastore) error { +func checkForDeprecatedRelationships(ctx context.Context, update *v1.RelationshipUpdate, ds datastore.Datastore, ps *permissionServer) error { resource := update.Relationship.Resource headRevision, err := ds.HeadRevision(ctx) if err != nil { @@ -639,6 +643,13 @@ func checkForDeprecatedRelationships(ctx context.Context, update *v1.Relationshi return err } + if !ps.config.DeprecatedRelationshipsEnabled && relDef.DeprecationType != corev1.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + return ps.rewriteError( + ctx, + fmt.Errorf("support for deprecated relationships is not enabled"), + ) + } + switch relDef.DeprecationType { case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: log.Warn(). diff --git a/internal/services/v1/schema.go b/internal/services/v1/schema.go index e579bc1e66..c162d0f630 100644 --- a/internal/services/v1/schema.go +++ b/internal/services/v1/schema.go @@ -41,6 +41,9 @@ type SchemaServerConfig struct { // ExpiringRelsEnabled indicates whether expiring relationships are enabled. ExpiringRelsEnabled bool + // DeprecatedRelsEnabled indicates whether deprecated relations are enabled. + DeprecatedRelsEnabled bool + // PerformanceInsightMetricsEnabled indicates whether performance insight metrics are enabled. PerformanceInsightMetricsEnabled bool } @@ -61,9 +64,10 @@ func NewSchemaServer(config SchemaServerConfig) v1.SchemaServiceServer { perfinsights.StreamServerInterceptor(config.PerformanceInsightMetricsEnabled), ), }, - additiveOnly: config.AdditiveOnly, - expiringRelsEnabled: config.ExpiringRelsEnabled, - caveatTypeSet: cts, + additiveOnly: config.AdditiveOnly, + expiringRelsEnabled: config.ExpiringRelsEnabled, + deprecatedRelsEnabled: config.DeprecatedRelsEnabled, + caveatTypeSet: cts, } } @@ -71,9 +75,10 @@ type schemaServer struct { v1.UnimplementedSchemaServiceServer shared.WithServiceSpecificInterceptors - caveatTypeSet *caveattypes.TypeSet - additiveOnly bool - expiringRelsEnabled bool + caveatTypeSet *caveattypes.TypeSet + additiveOnly bool + expiringRelsEnabled bool + deprecatedRelsEnabled bool } func (ss *schemaServer) rewriteError(ctx context.Context, err error) error { @@ -148,6 +153,9 @@ func (ss *schemaServer) WriteSchema(ctx context.Context, in *v1.WriteSchemaReque opts = append(opts, compiler.DisallowExpirationFlag()) } + if !ss.deprecatedRelsEnabled { + opts = append(opts, compiler.DisallowDeprecationFlag()) + } opts = append(opts, compiler.CaveatTypeSet(ss.caveatTypeSet)) compiled, err := compiler.Compile(compiler.InputSchema{ diff --git a/internal/services/v1/schema_test.go b/internal/services/v1/schema_test.go index e713e5abd9..093d152433 100644 --- a/internal/services/v1/schema_test.go +++ b/internal/services/v1/schema_test.go @@ -1651,6 +1651,7 @@ func TestSchemaChangeRelationDeprecation(t *testing.T) { // Write a basic schema with deprecation type warning. originalSchema := ` + use deprecation definition user {} definition document { @@ -1672,6 +1673,7 @@ func TestSchemaChangeRelationDeprecation(t *testing.T) { require.Nil(t, err) deprecatedErrSchema := ` + use deprecation definition user {} definition document { diff --git a/internal/telemetry/reporter.go b/internal/telemetry/reporter.go index 1016952c46..4f6f38818a 100644 --- a/internal/telemetry/reporter.go +++ b/internal/telemetry/reporter.go @@ -14,11 +14,11 @@ import ( prompb "buf.build/gen/go/prometheus/prometheus/protocolbuffers/go" "github.com/cenkalti/backoff/v4" - "github.com/gogo/protobuf/proto" "github.com/golang/snappy" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/expfmt" "github.com/prometheus/common/model" + "google.golang.org/protobuf/proto" log "github.com/authzed/spicedb/internal/logging" "github.com/authzed/spicedb/pkg/x509util" @@ -46,9 +46,7 @@ const ( func writeTimeSeries(ctx context.Context, client *http.Client, endpoint string, ts []*prompb.TimeSeries) error { // Reference upstream client: // https://github.com/prometheus/prometheus/blob/6555cc68caf8d8f323056e497ae7bb1e32a81667/storage/remote/client.go#L191 - pbBytes, err := proto.Marshal(&prompb.WriteRequest{ - Timeseries: ts, - }) + pbBytes, err := proto.Marshal(&prompb.WriteRequest{Timeseries: ts}) if err != nil { return fmt.Errorf("failed to marshal Prometheus remote write protobuf: %w", err) } diff --git a/internal/testfixtures/generator.go b/internal/testfixtures/generator.go index 9d7417ea84..24d3d13293 100644 --- a/internal/testfixtures/generator.go +++ b/internal/testfixtures/generator.go @@ -70,7 +70,7 @@ func (btg *BulkRelationshipGenerator) Next(_ context.Context) (*tuple.Relationsh var caveat *corev1.ContextualizedCaveat if btg.WithCaveat { - c, err := structpb.NewStruct(map[string]interface{}{ + c, err := structpb.NewStruct(map[string]any{ "secret": "1235", }) if err != nil { diff --git a/internal/testserver/server.go b/internal/testserver/server.go index 60b9bd3fa4..d0e2ab0f8a 100644 --- a/internal/testserver/server.go +++ b/internal/testserver/server.go @@ -76,6 +76,7 @@ func NewTestServerWithConfigAndDatastore(require *require.Assertions, cts := caveattypes.TypeSetOrDefault(config.CaveatTypeSet) srv, err := server.NewConfigWithOptionsAndDefaults( server.WithEnableExperimentalRelationshipExpiration(true), + server.WithEnableExperimentalRelationshipDeprecation(true), server.WithDatastore(ds), server.WithDispatcher(graph.NewLocalOnlyDispatcher(cts, 10, 100)), server.WithDispatchMaxDepth(50), diff --git a/magefiles/alias.go b/magefiles/alias.go index b95472cbf0..33cfce2804 100644 --- a/magefiles/alias.go +++ b/magefiles/alias.go @@ -2,7 +2,7 @@ package main -var Aliases = map[string]interface{}{ +var Aliases = map[string]any{ "test": Test.Unit, "generate": Gen.All, "lint": Lint.All, diff --git a/magefiles/build.go b/magefiles/build.go index 5fc16d2d07..30e87d9b4e 100644 --- a/magefiles/build.go +++ b/magefiles/build.go @@ -9,10 +9,22 @@ import ( type Build mg.Namespace +// Binary builds the binary +func (Build) Binary() error { + return sh.RunWithV( + map[string]string{}, + "go", "build", + "-o", "./dist", + "./cmd/spicedb/main.go", + ) +} + // Wasm Build the wasm bundle func (Build) Wasm() error { return sh.RunWithV(map[string]string{"GOOS": "js", "GOARCH": "wasm"}, - "go", "build", "-o", "dist/development.wasm", "./pkg/development/wasm/...") + // -s: Omit the symbol table. + // -w: Omit the DWARF debugging information. + "go", "build", "-ldflags=-s -w", "-o", "dist/development.wasm", "./pkg/development/wasm/...") } // Testimage Build the spicedb image for tests diff --git a/magefiles/go.mod b/magefiles/go.mod index 59463ef755..0913f73db6 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -47,7 +47,7 @@ require ( github.com/fatih/structtag v1.2.0 // indirect github.com/felixge/fgprof v0.9.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-chi/chi/v5 v5.0.14 // indirect + github.com/go-chi/chi/v5 v5.2.2 // indirect github.com/go-interpreter/wagon v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/magefiles/go.sum b/magefiles/go.sum index b910dabef7..d2672cf30f 100644 --- a/magefiles/go.sum +++ b/magefiles/go.sum @@ -137,8 +137,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/go-chi/chi/v5 v5.0.14 h1:PyEwo2Vudraa0x/Wl6eDRRW2NXBvekgfxyydcM0WGE0= -github.com/go-chi/chi/v5 v5.0.14/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= +github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= diff --git a/pkg/cache/cache_otter.go b/pkg/cache/cache_otter.go index dda52b4388..6f05b486c7 100644 --- a/pkg/cache/cache_otter.go +++ b/pkg/cache/cache_otter.go @@ -5,15 +5,15 @@ package cache import ( "math" - "sync" + "sync/atomic" "github.com/ccoveille/go-safecast" - "github.com/maypok86/otter" + "github.com/maypok86/otter/v2" + "github.com/maypok86/otter/v2/stats" "github.com/rs/zerolog" ) func NewOtterCacheWithMetrics[K KeyString, V any](name string, config *Config) (Cache[K, V], error) { - // TODO: support metrics return NewOtterCache[K, V](config) } @@ -23,42 +23,37 @@ type valueAndCost[V any] struct { } func NewOtterCache[K KeyString, V any](config *Config) (Cache[K, V], error) { - if config.DefaultTTL <= 0 { - cache, err := otter.MustBuilder[string, valueAndCost[V]](int(config.MaxCost)). - CollectStats(). - Cost(func(key string, value valueAndCost[V]) uint32 { - return value.cost - }). - Build() - if err != nil { - return nil, err - } - - return &otterCache[K, V]{cache, sync.Once{}}, nil + uintCost, err := safecast.ToUint64(config.MaxCost) + if err != nil { + return nil, err } - cache, err := otter.MustBuilder[string, valueAndCost[V]](int(config.MaxCost)). - CollectStats(). - Cost(func(key string, value valueAndCost[V]) uint32 { + counter := stats.NewCounter() + opts := &otter.Options[string, valueAndCost[V]]{ + MaximumWeight: uintCost, + Weigher: func(key string, value valueAndCost[V]) uint32 { return value.cost - }). - WithTTL(config.DefaultTTL). - Build() - if err != nil { - return nil, err + }, + StatsRecorder: counter, + } + if config.DefaultTTL > 0 { + opts.ExpiryCalculator = otter.ExpiryAccessing[string, valueAndCost[V]](config.DefaultTTL) } - return &otterCache[K, V]{cache, sync.Once{}}, nil + cache, err := otter.New(opts) + return &otterCache[K, V]{ + cache, + otterMetrics{atomic.Uint64{}, counter}, + }, err } type otterCache[K KeyString, V any] struct { - cache otter.Cache[string, valueAndCost[V]] - closed sync.Once + cache *otter.Cache[string, valueAndCost[V]] + metrics otterMetrics } func (wtc *otterCache[K, V]) Get(key K) (V, bool) { - keyString := key.KeyString() - vac, ok := wtc.cache.Get(keyString) + vac, ok := wtc.cache.GetIfPresent(key.KeyString()) if !ok { return *new(V), false } @@ -67,27 +62,31 @@ func (wtc *otterCache[K, V]) Get(key K) (V, bool) { } func (wtc *otterCache[K, V]) Set(key K, value V, cost int64) bool { - keyString := key.KeyString() uintCost, err := safecast.ToUint32(cost) if err != nil { // We make an assumption that if the cast fails, it's because the value // was too big, so we set to maxint in that case. uintCost = math.MaxUint32 } - return wtc.cache.Set(keyString, valueAndCost[V]{value, uintCost}) + wtc.metrics.costAdded.Add(uint64(uintCost)) + wtc.cache.Set(key.KeyString(), valueAndCost[V]{value, uintCost}) + return true // Otter doesn't drop insertions for performance } -func (wtc *otterCache[K, V]) Wait() { - // No-op because otter doesn't have a wait function. -} +func (wtc *otterCache[K, V]) Wait() {} +func (wtc *otterCache[K, V]) Close() {} -func (wtc *otterCache[K, V]) Close() { - wtc.closed.Do(func() { - wtc.cache.Close() - }) +type otterMetrics struct { + costAdded atomic.Uint64 + *stats.Counter } -func (wtc *otterCache[K, V]) GetMetrics() Metrics { return &noopMetrics{} } +func (o *otterMetrics) CostAdded() uint64 { return o.costAdded.Load() } +func (o *otterMetrics) CostEvicted() uint64 { return o.Counter.Snapshot().EvictionWeight } +func (o *otterMetrics) Hits() uint64 { return o.Counter.Snapshot().Hits } +func (o *otterMetrics) Misses() uint64 { return o.Counter.Snapshot().Misses } + +func (wtc *otterCache[K, V]) GetMetrics() Metrics { return &wtc.metrics } func (wtc *otterCache[K, V]) MarshalZerologObject(e *zerolog.Event) { e.Bool("otter", true) } diff --git a/pkg/caveats/context_hash.go b/pkg/caveats/context_hash.go index af5a2f2629..c70ded5b8b 100644 --- a/pkg/caveats/context_hash.go +++ b/pkg/caveats/context_hash.go @@ -3,11 +3,12 @@ package caveats import ( "bytes" "fmt" + "maps" "net/url" + "slices" "sort" "strconv" - "golang.org/x/exp/maps" "google.golang.org/protobuf/types/known/structpb" ) @@ -42,7 +43,7 @@ func (hc HashableContext) AppendToHash(hasher HasherInterface) { } fields := hc.Fields - keys := maps.Keys(fields) + keys := slices.Collect(maps.Keys(fields)) sort.Strings(keys) for _, key := range keys { diff --git a/pkg/caveats/structure_test.go b/pkg/caveats/structure_test.go index 89b3fdeb18..66be1c87f3 100644 --- a/pkg/caveats/structure_test.go +++ b/pkg/caveats/structure_test.go @@ -1,11 +1,12 @@ package caveats import ( + "maps" + "slices" "sort" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" "github.com/authzed/spicedb/pkg/caveats/types" ) @@ -95,7 +96,7 @@ func TestReferencedParameters(t *testing.T) { sort.Strings(tc.referencedParamNames) - found, err := compiled.ReferencedParameters(maps.Keys(tc.env.variables)) + found, err := compiled.ReferencedParameters(slices.Collect(maps.Keys(tc.env.variables))) require.NoError(t, err) foundSlice := found.AsSlice() diff --git a/pkg/caveats/types/ipaddress.go b/pkg/caveats/types/ipaddress.go index 2a9269730b..9da8ef226d 100644 --- a/pkg/caveats/types/ipaddress.go +++ b/pkg/caveats/types/ipaddress.go @@ -36,7 +36,7 @@ func (ipa IPAddress) SerializedString() string { return ipa.ip.String() } -func (ipa IPAddress) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (ipa IPAddress) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc { case reflect.TypeOf(""): return ipa.ip.String(), nil @@ -66,7 +66,7 @@ func (ipa IPAddress) Type() ref.Type { return ipaddressCelType } -func (ipa IPAddress) Value() interface{} { +func (ipa IPAddress) Value() any { return ipa } diff --git a/pkg/cmd/datastore/datastore.go b/pkg/cmd/datastore/datastore.go index 51113dc1a0..56b0e491b2 100644 --- a/pkg/cmd/datastore/datastore.go +++ b/pkg/cmd/datastore/datastore.go @@ -85,7 +85,7 @@ func RegisterConnPoolFlagsWithPrefix(flagSet *pflag.FlagSet, prefix string, defa flagSet.IntVar(&opts.MaxOpenConns, flagName("max-open"), defaults.MaxOpenConns, "number of concurrent connections open in a remote datastore's connection pool") flagSet.IntVar(&opts.MinOpenConns, flagName("min-open"), defaults.MinOpenConns, "number of minimum concurrent connections open in a remote datastore's connection pool") flagSet.DurationVar(&opts.MaxLifetime, flagName("max-lifetime"), defaults.MaxLifetime, "maximum amount of time a connection can live in a remote datastore's connection pool") - flagSet.DurationVar(&opts.MaxLifetimeJitter, flagName("max-lifetime-jitter"), defaults.MaxLifetimeJitter, "waits rand(0, jitter) after a connection is open for max lifetime to actually close the connection (default: 20% of max lifetime)") + flagSet.DurationVar(&opts.MaxLifetimeJitter, flagName("max-lifetime-jitter"), defaults.MaxLifetimeJitter, "waits rand(0, jitter) after a connection is open for max lifetime to actually close the connection (default: 20% of max lifetime, 30m for CockroachDB)") flagSet.DurationVar(&opts.MaxIdleTime, flagName("max-idletime"), defaults.MaxIdleTime, "maximum amount of time a connection can idle in a remote datastore's connection pool") flagSet.DurationVar(&opts.HealthCheckInterval, flagName("healthcheck-interval"), defaults.HealthCheckInterval, "amount of time between connection health checks in a remote datastore's connection pool") } diff --git a/pkg/cmd/serve.go b/pkg/cmd/serve.go index 75abe30030..5f59f3d194 100644 --- a/pkg/cmd/serve.go +++ b/pkg/cmd/serve.go @@ -172,6 +172,7 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error { } experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipExpiration, "enable-experimental-relationship-expiration", false, "enables experimental support for first-class relationship expiration") + experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipDeprecation, "enable-experimental-relationship-deprecation", false, "enables experimental support for deprecating relations") experimentalFlags.BoolVar(&config.EnableExperimentalWatchableSchemaCache, "enable-experimental-watchable-schema-cache", false, "enables the experimental schema cache which makes use of the Watch API for automatic updates") // TODO: these two could reasonably be put in either the Dispatch group or the Experimental group. Is there a preference? experimentalFlags.StringToStringVar(&config.DispatchSecondaryUpstreamAddrs, "experimental-dispatch-secondary-upstream-addrs", nil, "secondary upstream addresses for dispatches, each with a name") diff --git a/pkg/cmd/server/cacheconfig.go b/pkg/cmd/server/cacheconfig.go index 9795c354ed..9b79d7ed36 100644 --- a/pkg/cmd/server/cacheconfig.go +++ b/pkg/cmd/server/cacheconfig.go @@ -1,6 +1,7 @@ package server import ( + "cmp" "errors" "fmt" "strconv" @@ -9,7 +10,6 @@ import ( "github.com/ccoveille/go-safecast" "github.com/dustin/go-humanize" - "github.com/jzelinskie/stringz" "github.com/pbnjay/memory" "github.com/spf13/pflag" @@ -91,9 +91,8 @@ func CompleteCache[K cache.KeyString, V any](cc *CacheConfig) (cache.Cache[K, V] case "otter": return cache.NewOtterCache[K, V](&cache.Config{ - MaxCost: intMaxCost, - NumCounters: cc.NumCounters, - DefaultTTL: cc.defaultTTL, + MaxCost: intMaxCost, + DefaultTTL: cc.defaultTTL, }) default: @@ -134,15 +133,15 @@ func parsePercent(str string, freeMem uint64) (uint64, error) { // caches. func MustRegisterCacheFlags(flags *pflag.FlagSet, flagPrefix string, config, defaults *CacheConfig) { config.Name = defaults.Name - flagPrefix = stringz.DefaultEmpty(flagPrefix, "cache") + flagPrefix = cmp.Or(flagPrefix, "cache") flags.StringVar(&config.MaxCost, flagPrefix+"-max-cost", defaults.MaxCost, "upper bound cache size in bytes or percent of available memory") flags.Int64Var(&config.NumCounters, flagPrefix+"-num-counters", defaults.NumCounters, "number of TinyLFU samples to track") flags.BoolVar(&config.Metrics, flagPrefix+"-metrics", defaults.Metrics, "enable cache metrics") flags.BoolVar(&config.Enabled, flagPrefix+"-enabled", defaults.Enabled, "enable caching") // Hidden flags. - flags.StringVar(&config.CacheKindForTesting, flagPrefix+"-cache-kind-for-testing", defaults.CacheKindForTesting, "choose a different kind of cache, for testing") - if err := flags.MarkHidden(flagPrefix + "-cache-kind-for-testing"); err != nil { + flags.StringVar(&config.CacheKindForTesting, flagPrefix+"-kind-for-testing", defaults.CacheKindForTesting, "choose a different kind of cache, for testing") + if err := flags.MarkHidden(flagPrefix + "-kind-for-testing"); err != nil { panic(err) } } diff --git a/pkg/cmd/server/middleware.go b/pkg/cmd/server/middleware.go index c26785d6a0..4a492c3b34 100644 --- a/pkg/cmd/server/middleware.go +++ b/pkg/cmd/server/middleware.go @@ -304,7 +304,7 @@ func (soeb *StreamOrderEnforcerBuilder) Done() ReferenceableMiddleware[grpc.Stre return ReferenceableMiddleware[grpc.StreamServerInterceptor]{ Name: soeb.name, Internal: soeb.internal, - Middleware: func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + Middleware: func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wss := middleware.WrapServerStream(ss) if wss.WrappedContext.Value(streamExecuted{}) == nil { handle := executedHandle{executed: make(map[string]struct{}, 0)} @@ -385,7 +385,7 @@ func (soeb *UnaryOrderEnforcerBuilder) Done() ReferenceableMiddleware[grpc.Unary return ReferenceableMiddleware[grpc.UnaryServerInterceptor]{ Name: soeb.name, Internal: soeb.internal, - Middleware: func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + Middleware: func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { if ctx.Value(interceptorsExecuted{}) == nil { handle := executedHandle{executed: make(map[string]struct{}, 0)} ctx = context.WithValue(ctx, interceptorsExecuted{}, &handle) diff --git a/pkg/cmd/server/middleware_test.go b/pkg/cmd/server/middleware_test.go index 33f4da7de9..1e60e5a676 100644 --- a/pkg/cmd/server/middleware_test.go +++ b/pkg/cmd/server/middleware_test.go @@ -340,7 +340,7 @@ type mockUnaryInterceptor struct { val int } -func (m mockUnaryInterceptor) unaryIntercept(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (resp interface{}, err error) { +func (m mockUnaryInterceptor) unaryIntercept(_ context.Context, _ any, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (resp any, err error) { return m.val, nil } @@ -348,7 +348,7 @@ type mockStreamInterceptor struct { val error } -func (m mockStreamInterceptor) streamIntercept(_ interface{}, _ grpc.ServerStream, _ *grpc.StreamServerInfo, _ grpc.StreamHandler) error { +func (m mockStreamInterceptor) streamIntercept(_ any, _ grpc.ServerStream, _ *grpc.StreamServerInfo, _ grpc.StreamHandler) error { return m.val } @@ -429,10 +429,10 @@ func TestIncorrectOrderAssertionFails(t *testing.T) { datastore.WithRequestHedgingEnabled(false), ) require.NoError(t, err) - noopUnary := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + noopUnary := func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { return nil, nil } - noopStreaming := func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + noopStreaming := func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { return handler(srv, ss) } diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index f5ca33afb9..b69629171f 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -111,21 +111,22 @@ type Config struct { ClusterDispatchCacheConfig CacheConfig `debugmap:"visible"` // API Behavior - DisableV1SchemaAPI bool `debugmap:"visible"` - V1SchemaAdditiveOnly bool `debugmap:"visible"` - MaximumUpdatesPerWrite uint16 `debugmap:"visible"` - MaximumPreconditionCount uint16 `debugmap:"visible"` - MaxDatastoreReadPageSize uint64 `debugmap:"visible"` - StreamingAPITimeout time.Duration `debugmap:"visible"` - WatchHeartbeat time.Duration `debugmap:"visible"` - MaxReadRelationshipsLimit uint32 `debugmap:"visible"` - MaxDeleteRelationshipsLimit uint32 `debugmap:"visible"` - MaxLookupResourcesLimit uint32 `debugmap:"visible"` - MaxBulkExportRelationshipsLimit uint32 `debugmap:"visible"` - EnableExperimentalLookupResources bool `debugmap:"visible"` - EnableExperimentalRelationshipExpiration bool `debugmap:"visible"` - EnableRevisionHeartbeat bool `debugmap:"visible"` - EnablePerformanceInsightMetrics bool `debugmap:"visible"` + DisableV1SchemaAPI bool `debugmap:"visible"` + V1SchemaAdditiveOnly bool `debugmap:"visible"` + MaximumUpdatesPerWrite uint16 `debugmap:"visible"` + MaximumPreconditionCount uint16 `debugmap:"visible"` + MaxDatastoreReadPageSize uint64 `debugmap:"visible"` + StreamingAPITimeout time.Duration `debugmap:"visible"` + WatchHeartbeat time.Duration `debugmap:"visible"` + MaxReadRelationshipsLimit uint32 `debugmap:"visible"` + MaxDeleteRelationshipsLimit uint32 `debugmap:"visible"` + MaxLookupResourcesLimit uint32 `debugmap:"visible"` + MaxBulkExportRelationshipsLimit uint32 `debugmap:"visible"` + EnableExperimentalLookupResources bool `debugmap:"visible"` + EnableExperimentalRelationshipExpiration bool `debugmap:"visible"` + EnableExperimentalRelationshipDeprecation bool `debugmap:"visible"` + EnableRevisionHeartbeat bool `debugmap:"visible"` + EnablePerformanceInsightMetrics bool `debugmap:"visible"` // Additional Services MetricsAPI util.HTTPServerConfig `debugmap:"visible"` @@ -455,6 +456,7 @@ func (c *Config) Complete(ctx context.Context) (RunnableServer, error) { MaxBulkExportRelationshipsLimit: c.MaxBulkExportRelationshipsLimit, DispatchChunkSize: c.DispatchChunkSize, ExpiringRelationshipsEnabled: c.EnableExperimentalRelationshipExpiration, + DeprecatedRelationshipsEnabled: c.EnableExperimentalRelationshipDeprecation, CaveatTypeSet: c.DatastoreConfig.CaveatTypeSet, PerformanceInsightMetricsEnabled: c.EnablePerformanceInsightMetrics, } diff --git a/pkg/cmd/server/zz_generated.options.go b/pkg/cmd/server/zz_generated.options.go index 95d1c16b5c..72190d1f90 100644 --- a/pkg/cmd/server/zz_generated.options.go +++ b/pkg/cmd/server/zz_generated.options.go @@ -91,6 +91,7 @@ func (c *Config) ToOption() ConfigOption { to.MaxBulkExportRelationshipsLimit = c.MaxBulkExportRelationshipsLimit to.EnableExperimentalLookupResources = c.EnableExperimentalLookupResources to.EnableExperimentalRelationshipExpiration = c.EnableExperimentalRelationshipExpiration + to.EnableExperimentalRelationshipDeprecation = c.EnableExperimentalRelationshipDeprecation to.EnableRevisionHeartbeat = c.EnableRevisionHeartbeat to.EnablePerformanceInsightMetrics = c.EnablePerformanceInsightMetrics to.MetricsAPI = c.MetricsAPI @@ -163,6 +164,7 @@ func (c Config) DebugMap() map[string]any { debugMap["MaxBulkExportRelationshipsLimit"] = helpers.DebugValue(c.MaxBulkExportRelationshipsLimit, false) debugMap["EnableExperimentalLookupResources"] = helpers.DebugValue(c.EnableExperimentalLookupResources, false) debugMap["EnableExperimentalRelationshipExpiration"] = helpers.DebugValue(c.EnableExperimentalRelationshipExpiration, false) + debugMap["EnableExperimentalRelationshipDeprecation"] = helpers.DebugValue(c.EnableExperimentalRelationshipDeprecation, false) debugMap["EnableRevisionHeartbeat"] = helpers.DebugValue(c.EnableRevisionHeartbeat, false) debugMap["EnablePerformanceInsightMetrics"] = helpers.DebugValue(c.EnablePerformanceInsightMetrics, false) debugMap["MetricsAPI"] = helpers.DebugValue(c.MetricsAPI, false) @@ -598,6 +600,13 @@ func WithEnableExperimentalRelationshipExpiration(enableExperimentalRelationship } } +// WithEnableExperimentalRelationshipDeprecation returns an option that can set EnableExperimentalRelationshipDeprecation on a Config +func WithEnableExperimentalRelationshipDeprecation(enableExperimentalRelationshipDeprecation bool) ConfigOption { + return func(c *Config) { + c.EnableExperimentalRelationshipDeprecation = enableExperimentalRelationshipDeprecation + } +} + // WithEnableRevisionHeartbeat returns an option that can set EnableRevisionHeartbeat on a Config func WithEnableRevisionHeartbeat(enableRevisionHeartbeat bool) ConfigOption { return func(c *Config) { diff --git a/pkg/cmd/testserver/testserver.go b/pkg/cmd/testserver/testserver.go index 96d852094c..af61011e5f 100644 --- a/pkg/cmd/testserver/testserver.go +++ b/pkg/cmd/testserver/testserver.go @@ -87,6 +87,7 @@ func (c *Config) Complete() (RunnableTestServer, error) { MaxBulkExportRelationshipsLimit: c.MaxBulkExportRelationshipsLimit, DispatchChunkSize: defaultMaxChunkSize, ExpiringRelationshipsEnabled: true, + DeprecatedRelationshipsEnabled: true, CaveatTypeSet: cts, }, 1*time.Second, diff --git a/pkg/cmd/util/util.go b/pkg/cmd/util/util.go index 81b3944c0d..366ee79c2e 100644 --- a/pkg/cmd/util/util.go +++ b/pkg/cmd/util/util.go @@ -3,6 +3,7 @@ package util //go:generate go run github.com/ecordell/optgen -output zz_generated.options.go . GRPCServerConfig HTTPServerConfig import ( + "cmp" "context" "crypto/tls" "crypto/x509" @@ -13,9 +14,7 @@ import ( "time" "github.com/jzelinskie/cobrautil/v2/cobraotel" - "github.com/jzelinskie/stringz" - // Register Snappy S2 compression - _ "github.com/mostynb/go-grpc-compression/experimental/s2" + _ "github.com/mostynb/go-grpc-compression/experimental/s2" // Register Snappy S2 compression "github.com/rs/zerolog" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -25,8 +24,7 @@ import ( "google.golang.org/grpc/keepalive" "google.golang.org/grpc/test/bufconn" "sigs.k8s.io/controller-runtime/pkg/certwatcher" - // Register cert watcher metrics - _ "sigs.k8s.io/controller-runtime/pkg/certwatcher/metrics" + _ "sigs.k8s.io/controller-runtime/pkg/certwatcher/metrics" // Register cert watcher metrics "github.com/authzed/spicedb/internal/grpchelpers" log "github.com/authzed/spicedb/internal/logging" @@ -58,9 +56,9 @@ type GRPCServerConfig struct { // - "$PREFIX-tls-key-path" // - "$PREFIX-max-conn-age" func RegisterGRPCServerFlags(flags *pflag.FlagSet, config *GRPCServerConfig, flagPrefix, serviceName, defaultAddr string, defaultEnabled bool) { - flagPrefix = stringz.DefaultEmpty(flagPrefix, "grpc") - serviceName = stringz.DefaultEmpty(serviceName, "grpc") - defaultAddr = stringz.DefaultEmpty(defaultAddr, ":50051") + flagPrefix = cmp.Or(flagPrefix, "grpc") + serviceName = cmp.Or(serviceName, "grpc") + defaultAddr = cmp.Or(defaultAddr, ":50051") config.flagPrefix = flagPrefix flags.StringVar(&config.Address, flagPrefix+"-addr", defaultAddr, "address to listen on to serve "+serviceName) @@ -403,9 +401,9 @@ func (c *completedHTTPServer) Close() { // - "$PREFIX-tls-key-path" // - "$PREFIX-enabled" func RegisterHTTPServerFlags(flags *pflag.FlagSet, config *HTTPServerConfig, flagPrefix, serviceName, defaultAddr string, defaultEnabled bool) { - flagPrefix = stringz.DefaultEmpty(flagPrefix, "http") - serviceName = stringz.DefaultEmpty(serviceName, "http") - defaultAddr = stringz.DefaultEmpty(defaultAddr, ":8443") + flagPrefix = cmp.Or(flagPrefix, "http") + serviceName = cmp.Or(serviceName, "http") + defaultAddr = cmp.Or(defaultAddr, ":8443") config.flagPrefix = flagPrefix flags.StringVar(&config.HTTPAddress, flagPrefix+"-addr", defaultAddr, "address to listen on to serve "+serviceName) flags.StringVar(&config.HTTPTLSCertPath, flagPrefix+"-tls-cert-path", "", "local path to the TLS certificate used to serve "+serviceName) diff --git a/pkg/composableschemadsl/compiler/compiler.go b/pkg/composableschemadsl/compiler/compiler.go index 80071cba7d..90a1aaacb8 100644 --- a/pkg/composableschemadsl/compiler/compiler.go +++ b/pkg/composableschemadsl/compiler/compiler.go @@ -5,13 +5,13 @@ import ( "fmt" "google.golang.org/protobuf/proto" - "k8s.io/utils/strings/slices" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" "github.com/authzed/spicedb/pkg/composableschemadsl/dslshape" "github.com/authzed/spicedb/pkg/composableschemadsl/input" "github.com/authzed/spicedb/pkg/composableschemadsl/parser" "github.com/authzed/spicedb/pkg/genutil/mapz" + "github.com/authzed/spicedb/pkg/genutil/slicez" core "github.com/authzed/spicedb/pkg/proto/core/v1" ) @@ -90,7 +90,7 @@ const expirationFlag = "expiration" func DisallowExpirationFlag() Option { return func(cfg *config) { - cfg.allowedFlags = slices.Filter([]string{}, cfg.allowedFlags, func(s string) bool { + cfg.allowedFlags = slicez.Filter(cfg.allowedFlags, func(s string) bool { return s != expirationFlag }) } diff --git a/pkg/composableschemadsl/compiler/node.go b/pkg/composableschemadsl/compiler/node.go index 62ea56603b..aec5b4f24d 100644 --- a/pkg/composableschemadsl/compiler/node.go +++ b/pkg/composableschemadsl/compiler/node.go @@ -11,14 +11,14 @@ import ( type dslNode struct { nodeType dslshape.NodeType - properties map[string]interface{} + properties map[string]any children map[string]*list.List } func createAstNode(_ input.Source, kind dslshape.NodeType) parser.AstNode { return &dslNode{ nodeType: kind, - properties: make(map[string]interface{}), + properties: make(map[string]any), children: make(map[string]*list.List), } } @@ -172,7 +172,7 @@ func (tn *dslNode) Lookup(predicateName string) (*dslNode, error) { return nil, fmt.Errorf("nothing in predicate %s", predicateName) } -func (tn *dslNode) Errorf(message string, args ...interface{}) error { +func (tn *dslNode) Errorf(message string, args ...any) error { return withNodeError{ error: fmt.Errorf(message, args...), errorSourceCode: "", @@ -180,7 +180,7 @@ func (tn *dslNode) Errorf(message string, args ...interface{}) error { } } -func (tn *dslNode) WithSourceErrorf(sourceCode string, message string, args ...interface{}) error { +func (tn *dslNode) WithSourceErrorf(sourceCode string, message string, args ...any) error { return withNodeError{ error: fmt.Errorf(message, args...), errorSourceCode: sourceCode, diff --git a/pkg/composableschemadsl/generator/generator.go b/pkg/composableschemadsl/generator/generator.go index 74b64888c7..09b1e3f3f2 100644 --- a/pkg/composableschemadsl/generator/generator.go +++ b/pkg/composableschemadsl/generator/generator.go @@ -3,11 +3,11 @@ package generator import ( "bufio" "fmt" + "maps" + "slices" "sort" "strings" - "golang.org/x/exp/maps" - "github.com/authzed/spicedb/pkg/caveats" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" "github.com/authzed/spicedb/pkg/composableschemadsl/compiler" @@ -138,7 +138,7 @@ func (sg *sourceGenerator) emitCaveat(caveat *core.CaveatDefinition) error { sg.append(caveat.Name) sg.append("(") - parameterNames := maps.Keys(caveat.ParameterTypes) + parameterNames := slices.Collect(maps.Keys(caveat.ParameterTypes)) sort.Strings(parameterNames) for index, paramName := range parameterNames { diff --git a/pkg/composableschemadsl/input/sourcepositionmapper.go b/pkg/composableschemadsl/input/sourcepositionmapper.go index 1bca03c81a..7dff70f871 100644 --- a/pkg/composableschemadsl/input/sourcepositionmapper.go +++ b/pkg/composableschemadsl/input/sourcepositionmapper.go @@ -50,7 +50,7 @@ type lineAndStart struct { startPosition int } -func inclusiveComparator(a, b interface{}) int { +func inclusiveComparator(a, b any) int { i1 := a.(inclusiveRange) i2 := b.(inclusiveRange) diff --git a/pkg/composableschemadsl/lexer/lex.go b/pkg/composableschemadsl/lexer/lex.go index e45b6669b8..8602eac548 100644 --- a/pkg/composableschemadsl/lexer/lex.go +++ b/pkg/composableschemadsl/lexer/lex.go @@ -154,7 +154,7 @@ func (l *Lexer) emit(t TokenType) { // errorf returns an error token and terminates the scan by passing // back a nil pointer that will be the next state, terminating l.nexttoken. -func (l *Lexer) errorf(currentRune rune, format string, args ...interface{}) stateFn { +func (l *Lexer) errorf(currentRune rune, format string, args ...any) stateFn { l.tokens <- Lexeme{TokenTypeError, l.start, string(currentRune), fmt.Sprintf(format, args...)} return nil } diff --git a/pkg/composableschemadsl/parser/parser.go b/pkg/composableschemadsl/parser/parser.go index 08eedc860b..1f87802f08 100644 --- a/pkg/composableschemadsl/parser/parser.go +++ b/pkg/composableschemadsl/parser/parser.go @@ -2,10 +2,10 @@ package parser import ( + "maps" + "slices" "strings" - "golang.org/x/exp/maps" - "github.com/authzed/spicedb/pkg/composableschemadsl/dslshape" "github.com/authzed/spicedb/pkg/composableschemadsl/input" "github.com/authzed/spicedb/pkg/composableschemadsl/lexer" @@ -267,7 +267,8 @@ func (p *sourceParser) consumeUseFlag(afterDefinition bool) AstNode { } if _, ok := lexer.Flags[useFlag]; !ok { - p.emitErrorf("Unknown use flag: `%s`. Options are: %s", useFlag, strings.Join(maps.Keys(lexer.Flags), ", ")) + opts := strings.Join(slices.Collect(maps.Keys(lexer.Flags)), ", ") + p.emitErrorf("Unknown use flag: `%s`. Options are: %s", useFlag, opts) return useNode } diff --git a/pkg/composableschemadsl/parser/parser_impl.go b/pkg/composableschemadsl/parser/parser_impl.go index 829f1128ee..c508bf2b4f 100644 --- a/pkg/composableschemadsl/parser/parser_impl.go +++ b/pkg/composableschemadsl/parser/parser_impl.go @@ -78,7 +78,7 @@ func (p *sourceParser) createNode(kind dslshape.NodeType) AstNode { } // createErrorNodef creates a new error node and returns it. -func (p *sourceParser) createErrorNodef(format string, args ...interface{}) AstNode { +func (p *sourceParser) createErrorNodef(format string, args ...any) AstNode { message := fmt.Sprintf(format, args...) node := p.startNode(dslshape.NodeTypeError).MustDecorate(dslshape.NodePredicateErrorMessage, message) p.mustFinishNode() @@ -171,7 +171,7 @@ func (p *sourceParser) isKeyword(keyword string) bool { // emitErrorf creates a new error node and attachs it as a child of the current // node. -func (p *sourceParser) emitErrorf(format string, args ...interface{}) { +func (p *sourceParser) emitErrorf(format string, args ...any) { errorNode := p.createErrorNodef(format, args...) if len(p.currentToken.Value) > 0 { errorNode.MustDecorate(dslshape.NodePredicateErrorSource, p.currentToken.Value) diff --git a/pkg/composableschemadsl/parser/parser_test.go b/pkg/composableschemadsl/parser/parser_test.go index c1a7f531f8..26c76bb35d 100644 --- a/pkg/composableschemadsl/parser/parser_test.go +++ b/pkg/composableschemadsl/parser/parser_test.go @@ -16,7 +16,7 @@ import ( type testNode struct { nodeType dslshape.NodeType - properties map[string]interface{} + properties map[string]any children map[string]*list.List } @@ -53,7 +53,7 @@ func (pt *parserTest) writeTree(value string) { func createAstNode(_ input.Source, kind dslshape.NodeType) AstNode { return &testNode{ nodeType: kind, - properties: make(map[string]interface{}), + properties: make(map[string]any), children: make(map[string]*list.List), } } diff --git a/pkg/datastore/credentials.go b/pkg/datastore/credentials.go index 9c4a093930..c084486716 100644 --- a/pkg/datastore/credentials.go +++ b/pkg/datastore/credentials.go @@ -3,13 +3,14 @@ package datastore import ( "context" "fmt" + "maps" + "slices" "sort" "strings" "github.com/aws/aws-sdk-go-v2/aws" awsconfig "github.com/aws/aws-sdk-go-v2/config" rdsauth "github.com/aws/aws-sdk-go-v2/feature/rds/auth" - "golang.org/x/exp/maps" log "github.com/authzed/spicedb/internal/logging" ) @@ -41,7 +42,7 @@ var BuilderForCredentialProvider = map[string]credentialsProviderBuilderFunc{ // CredentialsProviderOptions returns the full set of credential provider names, sorted and quoted into a string. func CredentialsProviderOptions() string { - ids := maps.Keys(BuilderForCredentialProvider) + ids := slices.Collect(maps.Keys(BuilderForCredentialProvider)) sort.Strings(ids) quoted := make([]string, 0, len(ids)) for _, id := range ids { diff --git a/pkg/datastore/test/caveat.go b/pkg/datastore/test/caveat.go index 312c45782c..155ce23f54 100644 --- a/pkg/datastore/test/caveat.go +++ b/pkg/datastore/test/caveat.go @@ -402,7 +402,7 @@ func skipIfNotCaveatStorer(t *testing.T, ds datastore.Datastore) { func createTestCaveatedRel(t *testing.T, relString string, caveatName string) tuple.Relationship { rel := tuple.MustParse(relString) - st, err := structpb.NewStruct(map[string]interface{}{"a": 1, "b": "test"}) + st, err := structpb.NewStruct(map[string]any{"a": 1, "b": "test"}) require.NoError(t, err) return rel.WithCaveat(&core.ContextualizedCaveat{ CaveatName: caveatName, diff --git a/pkg/datastore/test/counters.go b/pkg/datastore/test/counters.go index f883a2afb6..f3de2335b1 100644 --- a/pkg/datastore/test/counters.go +++ b/pkg/datastore/test/counters.go @@ -206,6 +206,48 @@ func RelationshipCountersTest(t *testing.T, tester DatastoreTester) { require.Contains(t, err.Error(), "counter with name `document` not found") } +func RelationshipCountersWithOddFilterTest(t *testing.T, tester DatastoreTester) { + rawDS, err := tester.New(0, veryLargeGCInterval, veryLargeGCWindow, 1) + require.NoError(t, err) + ds, _ := testfixtures.StandardDatastoreWithData(rawDS, require.New(t)) + + // Register the filter. + updatedRev, err := ds.ReadWriteTx(t.Context(), func(ctx context.Context, tx datastore.ReadWriteTransaction) error { + err := tx.RegisterCounter(ctx, "somefilter", &core.RelationshipFilter{ + ResourceType: testfixtures.DocumentNS.Name, + OptionalSubjectFilter: &core.SubjectFilter{ + SubjectType: testfixtures.UserNS.Name, + }, + }) + require.NoError(t, err) + return nil + }) + require.NoError(t, err) + + // Check the count using the filter. + reader := ds.SnapshotReader(updatedRev) + + expectedCount := 0 + iter, err := reader.QueryRelationships(t.Context(), datastore.RelationshipsFilter{ + OptionalResourceType: testfixtures.DocumentNS.Name, + OptionalSubjectsSelectors: []datastore.SubjectsSelector{ + { + OptionalSubjectType: testfixtures.UserNS.Name, + }, + }, + }, options.WithQueryShape(queryshape.Varying)) + require.NoError(t, err) + + for _, err := range iter { + expectedCount++ + require.NoError(t, err) + } + + count, err := reader.CountRelationships(t.Context(), "somefilter") + require.NoError(t, err) + require.Equal(t, expectedCount, count) +} + func UpdateRelationshipCounterTest(t *testing.T, tester DatastoreTester) { rawDS, err := tester.New(0, veryLargeGCInterval, veryLargeGCWindow, 1) require.NoError(t, err) diff --git a/pkg/datastore/test/datastore.go b/pkg/datastore/test/datastore.go index bebc646a4f..d5175ec448 100644 --- a/pkg/datastore/test/datastore.go +++ b/pkg/datastore/test/datastore.go @@ -215,6 +215,7 @@ func AllWithExceptions(t *testing.T, tester DatastoreTester, except Categories, t.Run("TestDeleteAllData", runner(tester, DeleteAllDataTest)) t.Run("TestRelationshipCounterOverExpired", runner(tester, RelationshipCounterOverExpiredTest)) t.Run("TestRegisterRelationshipCountersInParallel", runner(tester, RegisterRelationshipCountersInParallelTest)) + t.Run("TestRelationshipCountersWithOddFilter", runner(tester, RelationshipCountersWithOddFilterTest)) } func OnlyGCTests(t *testing.T, tester DatastoreTester, concurrent bool) { diff --git a/pkg/datastore/test/pagination.go b/pkg/datastore/test/pagination.go index 1f7fb526e5..54120f4326 100644 --- a/pkg/datastore/test/pagination.go +++ b/pkg/datastore/test/pagination.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/ccoveille/go-safecast" - "github.com/samber/lo" "github.com/stretchr/testify/require" "github.com/authzed/spicedb/internal/testfixtures" @@ -15,6 +14,7 @@ import ( "github.com/authzed/spicedb/pkg/datastore/options" "github.com/authzed/spicedb/pkg/datastore/queryshape" "github.com/authzed/spicedb/pkg/genutil/mapz" + "github.com/authzed/spicedb/pkg/genutil/slicez" "github.com/authzed/spicedb/pkg/tuple" ) @@ -406,11 +406,11 @@ func foreachTxType( } func sortedStandardData(resourceType string, order options.SortOrder) []tuple.Relationship { - asTuples := lo.Map(testfixtures.StandardRelationships, func(item string, _ int) tuple.Relationship { + asTuples := slicez.Map(testfixtures.StandardRelationships, func(item string) tuple.Relationship { return tuple.MustParse(item) }) - filteredToType := lo.Filter(asTuples, func(item tuple.Relationship, _ int) bool { + filteredToType := slicez.Filter(asTuples, func(item tuple.Relationship) bool { return item.Resource.ObjectType == resourceType }) @@ -433,11 +433,11 @@ func sortedStandardData(resourceType string, order options.SortOrder) []tuple.Re } func sortedStandardDataBySubject(subjectType string, order options.SortOrder) []tuple.Relationship { - asTuples := lo.Map(testfixtures.StandardRelationships, func(item string, _ int) tuple.Relationship { + asTuples := slicez.Map(testfixtures.StandardRelationships, func(item string) tuple.Relationship { return tuple.MustParse(item) }) - filteredToType := lo.Filter(asTuples, func(item tuple.Relationship, _ int) bool { + filteredToType := slicez.Filter(asTuples, func(item tuple.Relationship) bool { if subjectType == "" { return true } diff --git a/pkg/datastore/test/revisions.go b/pkg/datastore/test/revisions.go index f02a9899ad..5a16630fcb 100644 --- a/pkg/datastore/test/revisions.go +++ b/pkg/datastore/test/revisions.go @@ -46,7 +46,7 @@ func RevisionQuantizationTest(t *testing.T, tester DatastoreTester) { // Create some revisions var writtenAt datastore.Revision tpl := makeTestRel("first", "owner") - for i := 0; i < 10; i++ { + for range 10 { writtenAt, err = common.WriteRelationships(ctx, ds, tuple.UpdateOperationTouch, tpl) require.NoError(err) } @@ -272,7 +272,7 @@ func SequentialRevisionsTest(t *testing.T, tester DatastoreTester) { defer cancel() var previous datastore.Revision - for i := 0; i < 50; i++ { + for range 50 { head, err := ds.HeadRevision(ctx) require.NoError(err) require.NoError(ds.CheckRevision(ctx, head), "expected head revision to be valid in GC Window") diff --git a/pkg/datastore/test/transactions.go b/pkg/datastore/test/transactions.go index 67de6ae5a5..31cbf1eb3d 100644 --- a/pkg/datastore/test/transactions.go +++ b/pkg/datastore/test/transactions.go @@ -19,7 +19,7 @@ func RetryTest(t *testing.T, tester DatastoreTester) { name string returnRetryableError bool txOptions []options.RWTOptionsOption - countAssertion func(require.TestingT, interface{}, ...interface{}) + countAssertion func(require.TestingT, any, ...any) }{ {"retryable with retries", true, nil, require.Positive}, {"non-retryable with retries", false, nil, require.Zero}, diff --git a/pkg/datastore/test/watch.go b/pkg/datastore/test/watch.go index e485deec8c..80d7ba902e 100644 --- a/pkg/datastore/test/watch.go +++ b/pkg/datastore/test/watch.go @@ -10,7 +10,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/uuid" - "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/require" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/structpb" @@ -165,8 +164,8 @@ func VerifyUpdates( expectedChangeSet := setOfChanges(expected) actualChangeSet := setOfChanges(change.RelationshipChanges) - missingExpected := strset.Difference(expectedChangeSet, actualChangeSet) - unexpected := strset.Difference(actualChangeSet, expectedChangeSet) + missingExpected := expectedChangeSet.Difference(actualChangeSet) + unexpected := actualChangeSet.Difference(expectedChangeSet) require.True(missingExpected.IsEmpty(), "expected changes missing: %s", missingExpected) require.True(unexpected.IsEmpty(), "unexpected changes: %s", unexpected) @@ -207,8 +206,8 @@ func VerifyUpdatesWithMetadata( expectedChangeSet := setOfChanges(expected.updates) actualChangeSet := setOfChanges(change.RelationshipChanges) - missingExpected := strset.Difference(expectedChangeSet, actualChangeSet) - unexpected := strset.Difference(actualChangeSet, expectedChangeSet) + missingExpected := expectedChangeSet.Difference(actualChangeSet) + unexpected := actualChangeSet.Difference(expectedChangeSet) require.True(missingExpected.IsEmpty(), "expected changes missing: %s", missingExpected) require.True(unexpected.IsEmpty(), "unexpected changes: %s", unexpected) @@ -224,8 +223,8 @@ func VerifyUpdatesWithMetadata( require.False(expectDisconnect, "all changes verified without expected disconnect") } -func setOfChanges(changes []tuple.RelationshipUpdate) *strset.Set { - changeSet := strset.NewWithSize(len(changes)) +func setOfChanges(changes []tuple.RelationshipUpdate) *mapz.Set[string] { + changeSet := mapz.NewSet[string]() for _, change := range changes { changeSet.Add(change.DebugString()) } diff --git a/pkg/development/devcontext.go b/pkg/development/devcontext.go index 87ddfc0487..80302ca89b 100644 --- a/pkg/development/devcontext.go +++ b/pkg/development/devcontext.go @@ -173,6 +173,7 @@ func (dc *DevContext) RunV1InMemoryService() (*grpc.ClientConn, func(), error) { MaximumAPIDepth: 50, MaxCaveatContextSize: 0, ExpiringRelationshipsEnabled: true, + DeprecatedRelationshipsEnabled: true, CaveatTypeSet: caveattypes.Default.TypeSet, PerformanceInsightMetricsEnabled: false, }) @@ -180,6 +181,7 @@ func (dc *DevContext) RunV1InMemoryService() (*grpc.ClientConn, func(), error) { CaveatTypeSet: caveattypes.Default.TypeSet, AdditiveOnly: false, ExpiringRelsEnabled: true, + DeprecatedRelsEnabled: true, PerformanceInsightMetricsEnabled: false, }) diff --git a/pkg/diff/caveats/diff.go b/pkg/diff/caveats/diff.go index 74e196bb99..50beb71636 100644 --- a/pkg/diff/caveats/diff.go +++ b/pkg/diff/caveats/diff.go @@ -2,9 +2,8 @@ package caveats import ( "bytes" - - "golang.org/x/exp/maps" - "golang.org/x/exp/slices" + "maps" + "slices" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" "github.com/authzed/spicedb/pkg/genutil/mapz" @@ -108,8 +107,8 @@ func DiffCaveats(existing *core.CaveatDefinition, updated *core.CaveatDefinition }) } - existingParameterNames := mapz.NewSet(maps.Keys(existing.ParameterTypes)...) - updatedParameterNames := mapz.NewSet(maps.Keys(updated.ParameterTypes)...) + existingParameterNames := mapz.NewSet(slices.Collect(maps.Keys(existing.ParameterTypes))...) + updatedParameterNames := mapz.NewSet(slices.Collect(maps.Keys(updated.ParameterTypes))...) for _, removed := range existingParameterNames.Subtract(updatedParameterNames).AsSlice() { deltas = append(deltas, Delta{ diff --git a/pkg/genutil/mapz/multimap.go b/pkg/genutil/mapz/multimap.go index bc85f3207d..f19c089eda 100644 --- a/pkg/genutil/mapz/multimap.go +++ b/pkg/genutil/mapz/multimap.go @@ -1,7 +1,8 @@ package mapz import ( - "golang.org/x/exp/maps" + "maps" + "slices" ) // ReadOnlyMultimap is a read-only multimap. @@ -97,12 +98,12 @@ func (mm *MultiMap[T, Q]) IsEmpty() bool { return len(mm.items) == 0 } func (mm *MultiMap[T, Q]) Len() int { return len(mm.items) } // Keys returns the keys of the map. -func (mm *MultiMap[T, Q]) Keys() []T { return maps.Keys(mm.items) } +func (mm *MultiMap[T, Q]) Keys() []T { return slices.Collect(maps.Keys(mm.items)) } // Values returns all values in the map. func (mm MultiMap[T, Q]) Values() []Q { values := make([]Q, 0, len(mm.items)*2) - for _, valueSlice := range maps.Values(mm.items) { + for valueSlice := range maps.Values(mm.items) { values = append(values, valueSlice...) } return values @@ -169,12 +170,12 @@ func (mm readOnlyMultimap[T, Q]) IsEmpty() bool { return len(mm.items) == 0 } func (mm readOnlyMultimap[T, Q]) Len() int { return len(mm.items) } // Keys returns the keys of the map. -func (mm readOnlyMultimap[T, Q]) Keys() []T { return maps.Keys(mm.items) } +func (mm readOnlyMultimap[T, Q]) Keys() []T { return slices.Collect(maps.Keys(mm.items)) } // Values returns all values in the map. func (mm readOnlyMultimap[T, Q]) Values() []Q { values := make([]Q, 0, len(mm.items)*2) - for _, valueSlice := range maps.Values(mm.items) { + for valueSlice := range maps.Values(mm.items) { values = append(values, valueSlice...) } return values diff --git a/pkg/genutil/mapz/set.go b/pkg/genutil/mapz/set.go index e1d5e4c151..a817419050 100644 --- a/pkg/genutil/mapz/set.go +++ b/pkg/genutil/mapz/set.go @@ -2,9 +2,9 @@ package mapz import ( "maps" + "slices" "github.com/rs/zerolog" - expmaps "golang.org/x/exp/maps" ) // Set implements a very basic generic set. @@ -74,6 +74,18 @@ func (s *Set[T]) Union(other *Set[T]) *Set[T] { return cpy } +// Difference returns a new set with all of the values that not in the provided +// sets. +func (s *Set[T]) Difference(others ...*Set[T]) *Set[T] { + cp := s.Copy() + for _, other := range others { + for item := range other.values { + cp.Delete(item) + } + } + return cp +} + // IntersectionDifference removes any values from this set that // are not shared with the other set. Returns the same set. func (s *Set[T]) IntersectionDifference(other *Set[T]) *Set[T] { @@ -134,7 +146,7 @@ func (s *Set[T]) AsSlice() []T { return nil } - return expmaps.Keys(s.values) + return slices.Collect(maps.Keys(s.values)) } // Len returns the length of the set. diff --git a/pkg/genutil/mapz/set_test.go b/pkg/genutil/mapz/set_test.go index fb9f821bc9..1b10bd45c6 100644 --- a/pkg/genutil/mapz/set_test.go +++ b/pkg/genutil/mapz/set_test.go @@ -2,6 +2,7 @@ package mapz import ( "fmt" + "slices" "sort" "testing" @@ -87,7 +88,7 @@ func TestSetIntersect(t *testing.T) { require.True(t, set.Add("4")) // Subtract some items. - updated := set.Intersect(NewSet[string]("1", "2", "3", "5")) + updated := set.Intersect(NewSet("1", "2", "3", "5")) updatedSlice := updated.AsSlice() sort.Strings(updatedSlice) require.Equal(t, []string{"1", "2", "3"}, updatedSlice) @@ -97,7 +98,7 @@ func TestSetIntersect(t *testing.T) { require.Equal(t, []string{"1", "2", "3", "4"}, slice) // Perform in reverse. - updated = NewSet[string]("1", "2", "3", "5").Intersect(set) + updated = NewSet("1", "2", "3", "5").Intersect(set) updatedSlice = updated.AsSlice() sort.Strings(updatedSlice) require.Equal(t, []string{"1", "2", "3"}, updatedSlice) @@ -115,7 +116,7 @@ func TestSetSubtract(t *testing.T) { require.True(t, set.Add("4")) // Subtract some items. - updated := set.Subtract(NewSet[string]("1", "2", "3", "5")) + updated := set.Subtract(NewSet("1", "2", "3", "5")) require.Equal(t, []string{"4"}, updated.AsSlice()) slice := set.AsSlice() @@ -125,15 +126,15 @@ func TestSetSubtract(t *testing.T) { func TestEqual(t *testing.T) { require.True(t, NewSet[string]().Equal(NewSet[string]())) - require.True(t, NewSet[string]("2").Equal(NewSet[string]("2"))) - require.False(t, NewSet[string]("1", "2").Equal(NewSet[string]("1", "3"))) + require.True(t, NewSet("2").Equal(NewSet("2"))) + require.False(t, NewSet("1", "2").Equal(NewSet("1", "3"))) } func TestUnion(t *testing.T) { - u1 := NewSet[string]("1", "2").Union(NewSet[string]("2", "3")).AsSlice() + u1 := NewSet("1", "2").Union(NewSet("2", "3")).AsSlice() sort.Strings(u1) - u2 := NewSet[string]("2", "3").Union(NewSet[string]("1", "2")).AsSlice() + u2 := NewSet("2", "3").Union(NewSet("1", "2")).AsSlice() sort.Strings(u2) require.Equal(t, []string{"1", "2", "3"}, u1) @@ -141,8 +142,8 @@ func TestUnion(t *testing.T) { } func TestMerge(t *testing.T) { - u1 := NewSet[string]("1", "2") - u2 := NewSet[string]("2", "3") + u1 := NewSet("1", "2") + u2 := NewSet("2", "3") u1.Merge(u2) @@ -152,8 +153,8 @@ func TestMerge(t *testing.T) { require.Equal(t, []string{"1", "2", "3"}, slice) // Try the reverse. - u1 = NewSet[string]("1", "2") - u2 = NewSet[string]("2", "3") + u1 = NewSet("1", "2") + u2 = NewSet("2", "3") u2.Merge(u1) @@ -163,6 +164,142 @@ func TestMerge(t *testing.T) { require.Equal(t, []string{"1", "2", "3"}, slice) } +func TestSetDifference(t *testing.T) { + tests := []struct { + name string + original []int + others [][]int + expected []int + }{ + { + name: "empty set difference with empty set", + original: []int{}, + others: [][]int{{}}, + expected: []int{}, + }, + { + name: "empty set difference with non-empty set", + original: []int{}, + others: [][]int{{1, 2, 3}}, + expected: []int{}, + }, + { + name: "non-empty set difference with empty set", + original: []int{1, 2, 3}, + others: [][]int{{}}, + expected: []int{1, 2, 3}, + }, + { + name: "identical sets difference", + original: []int{1, 2, 3}, + others: [][]int{{1, 2, 3}}, + expected: []int{}, + }, + { + name: "completely disjoint sets", + original: []int{1, 2, 3}, + others: [][]int{{4, 5, 6}}, + expected: []int{1, 2, 3}, + }, + { + name: "partial overlap - some elements removed", + original: []int{1, 2, 3, 4, 5}, + others: [][]int{{2, 4, 6}}, + expected: []int{1, 3, 5}, + }, + { + name: "subset removal", + original: []int{1, 2, 3, 4, 5}, + others: [][]int{{2, 3}}, + expected: []int{1, 4, 5}, + }, + { + name: "superset removal - original is subset", + original: []int{2, 3}, + others: [][]int{{1, 2, 3, 4, 5}}, + expected: []int{}, + }, + { + name: "single element sets", + original: []int{1}, + others: [][]int{{1}}, + expected: []int{}, + }, + { + name: "single element different", + original: []int{1}, + others: [][]int{{2}}, + expected: []int{1}, + }, + { + name: "multiple other sets - all disjoint", + original: []int{1, 2, 3, 4, 5}, + others: [][]int{{6, 7}, {8, 9}, {10, 11}}, + expected: []int{1, 2, 3, 4, 5}, + }, + { + name: "multiple other sets - with overlaps", + original: []int{1, 2, 3, 4, 5, 6, 7, 8}, + others: [][]int{{1, 2}, {3, 4}, {5, 6}}, + expected: []int{7, 8}, + }, + { + name: "multiple other sets - complete removal", + original: []int{1, 2, 3}, + others: [][]int{{1}, {2}, {3}}, + expected: []int{}, + }, + { + name: "multiple other sets - overlapping removals", + original: []int{1, 2, 3, 4, 5}, + others: [][]int{{1, 2, 6}, {2, 3, 7}, {3, 4, 8}}, + expected: []int{5}, + }, + { + name: "no other sets provided", + original: []int{1, 2, 3}, + others: [][]int{}, + expected: []int{1, 2, 3}, + }, + { + name: "duplicate elements in original (shouldn't happen in real set, but testing robustness)", + original: []int{1, 2, 3}, + others: [][]int{{1}}, + expected: []int{2, 3}, + }, + { + name: "large set difference", + original: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + others: [][]int{{2, 4, 6, 8, 10, 12, 14}}, + expected: []int{1, 3, 5, 7, 9, 11, 13, 15}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + original := NewSet(tt.original...) + others := make([]*Set[int], len(tt.others)) + for i, otherSlice := range tt.others { + others[i] = NewSet(otherSlice...) + } + + result := original.Difference(others...) + + resultSlice := result.AsSlice() + if resultSlice == nil { + resultSlice = []int{} + } + slices.Sort(resultSlice) + + expectedSorted := make([]int, len(tt.expected)) + copy(expectedSorted, tt.expected) + slices.Sort(expectedSorted) + + require.Equal(t, expectedSorted, resultSlice) + }) + } +} + func TestSetIntersectionDifference(t *testing.T) { tcs := []struct { first []int diff --git a/pkg/genutil/slicez/slicez.go b/pkg/genutil/slicez/slicez.go new file mode 100644 index 0000000000..9c5f2a4097 --- /dev/null +++ b/pkg/genutil/slicez/slicez.go @@ -0,0 +1,41 @@ +package slicez + +// Filter iterates over elements of a slice, returning a new slice with all +// elements that the predicate returns truthy for. +func Filter[T any, Slice ~[]T](xs Slice, pred func(T) bool) Slice { + ys := make(Slice, 0, len(xs)) + for _, x := range xs { + if pred(x) { + ys = append(ys, x) + } + } + return ys +} + +// Map iterates over a slice and creates a new slice with each element +// transformed. +func Map[T any, R any](xs []T, fn func(T) R) []R { + ys := make([]R, len(xs)) + for i, x := range xs { + ys[i] = fn(x) + } + return ys +} + +// Unique returns a duplicate-free version of a slice, in which only the first +// occurrence of each element is kept. +// +// The order of result values is determined by the order they occur. +func Unique[T comparable, Slice ~[]T](xs Slice) Slice { + ys := make(Slice, 0, len(xs)) + seen := make(map[T]struct{}, len(xs)) + for _, x := range xs { + if _, ok := seen[x]; ok { + continue + } + + seen[x] = struct{}{} + ys = append(ys, x) + } + return ys +} diff --git a/pkg/genutil/slicez/slicez_test.go b/pkg/genutil/slicez/slicez_test.go new file mode 100644 index 0000000000..f4b3417cf8 --- /dev/null +++ b/pkg/genutil/slicez/slicez_test.go @@ -0,0 +1,282 @@ +package slicez + +import ( + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFilter(t *testing.T) { + tests := []struct { + name string + input []int + pred func(int) bool + expected []int + }{ + { + name: "filter even numbers", + input: []int{1, 2, 3, 4, 5, 6}, + pred: func(x int) bool { return x%2 == 0 }, + expected: []int{2, 4, 6}, + }, + { + name: "filter numbers greater than 3", + input: []int{1, 2, 3, 4, 5}, + pred: func(x int) bool { return x > 3 }, + expected: []int{4, 5}, + }, + { + name: "filter all elements (always true)", + input: []int{1, 2, 3}, + pred: func(x int) bool { return true }, + expected: []int{1, 2, 3}, + }, + { + name: "filter no elements (always false)", + input: []int{1, 2, 3}, + pred: func(x int) bool { return false }, + expected: []int{}, + }, + { + name: "empty slice", + input: []int{}, + pred: func(x int) bool { return x > 0 }, + expected: []int{}, + }, + { + name: "single element matching", + input: []int{5}, + pred: func(x int) bool { return x == 5 }, + expected: []int{5}, + }, + { + name: "single element not matching", + input: []int{5}, + pred: func(x int) bool { return x == 3 }, + expected: []int{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Filter(tt.input, tt.pred)) + }) + } +} + +func TestFilterStrings(t *testing.T) { + tests := []struct { + name string + input []string + pred func(string) bool + expected []string + }{ + { + name: "filter strings starting with 'a'", + input: []string{"apple", "banana", "apricot", "cherry"}, + pred: func(s string) bool { return strings.HasPrefix(s, "a") }, + expected: []string{"apple", "apricot"}, + }, + { + name: "filter strings longer than 4 characters", + input: []string{"cat", "dog", "elephant", "bird"}, + pred: func(s string) bool { return len(s) > 4 }, + expected: []string{"elephant"}, + }, + { + name: "empty string slice", + input: []string{}, + pred: func(s string) bool { return len(s) > 0 }, + expected: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Filter(tt.input, tt.pred)) + }) + } +} + +func TestMap(t *testing.T) { + tests := []struct { + name string + input []int + fn func(int) int + expected []int + }{ + { + name: "double each number", + input: []int{1, 2, 3, 4}, + fn: func(x int) int { return x * 2 }, + expected: []int{2, 4, 6, 8}, + }, + { + name: "add 10 to each number", + input: []int{1, 2, 3}, + fn: func(x int) int { return x + 10 }, + expected: []int{11, 12, 13}, + }, + { + name: "square each number", + input: []int{2, 3, 4}, + fn: func(x int) int { return x * x }, + expected: []int{4, 9, 16}, + }, + { + name: "identity function", + input: []int{1, 2, 3}, + fn: func(x int) int { return x }, + expected: []int{1, 2, 3}, + }, + { + name: "empty slice", + input: []int{}, + fn: func(x int) int { return x * 2 }, + expected: []int{}, + }, + { + name: "single element", + input: []int{5}, + fn: func(x int) int { return x * 3 }, + expected: []int{15}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Map(tt.input, tt.fn)) + }) + } +} + +func TestMapDifferentTypes(t *testing.T) { + tests := []struct { + name string + input []int + fn func(int) string + expected []string + }{ + { + name: "convert int to string", + input: []int{1, 2, 3}, + fn: func(x int) string { return strconv.Itoa(x) }, + expected: []string{"1", "2", "3"}, + }, + { + name: "convert int to formatted string", + input: []int{1, 2, 3}, + fn: func(x int) string { return "num:" + strconv.Itoa(x) }, + expected: []string{"num:1", "num:2", "num:3"}, + }, + { + name: "empty slice different types", + input: []int{}, + fn: func(x int) string { return strconv.Itoa(x) }, + expected: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Map(tt.input, tt.fn)) + }) + } +} + +func TestUnique(t *testing.T) { + tests := []struct { + name string + input []int + expected []int + }{ + { + name: "remove duplicates", + input: []int{1, 2, 2, 3, 3, 3, 4}, + expected: []int{1, 2, 3, 4}, + }, + { + name: "no duplicates", + input: []int{1, 2, 3, 4}, + expected: []int{1, 2, 3, 4}, + }, + { + name: "all duplicates", + input: []int{5, 5, 5, 5}, + expected: []int{5}, + }, + { + name: "empty slice", + input: []int{}, + expected: []int{}, + }, + { + name: "single element", + input: []int{42}, + expected: []int{42}, + }, + { + name: "duplicates at beginning", + input: []int{1, 1, 2, 3, 4}, + expected: []int{1, 2, 3, 4}, + }, + { + name: "duplicates at end", + input: []int{1, 2, 3, 4, 4}, + expected: []int{1, 2, 3, 4}, + }, + { + name: "duplicates scattered", + input: []int{1, 3, 2, 3, 1, 4, 2}, + expected: []int{1, 3, 2, 4}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Unique(tt.input)) + }) + } +} + +func TestUniqueStrings(t *testing.T) { + tests := []struct { + name string + input []string + expected []string + }{ + { + name: "remove duplicate strings", + input: []string{"apple", "banana", "apple", "cherry", "banana"}, + expected: []string{"apple", "banana", "cherry"}, + }, + { + name: "no duplicate strings", + input: []string{"apple", "banana", "cherry"}, + expected: []string{"apple", "banana", "cherry"}, + }, + { + name: "all same strings", + input: []string{"hello", "hello", "hello"}, + expected: []string{"hello"}, + }, + { + name: "empty string slice", + input: []string{}, + expected: []string{}, + }, + { + name: "single string", + input: []string{"unique"}, + expected: []string{"unique"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, Unique(tt.input)) + }) + } +} diff --git a/pkg/graph/walker.go b/pkg/graph/walker.go index 3ae8b6bddf..71b9457b10 100644 --- a/pkg/graph/walker.go +++ b/pkg/graph/walker.go @@ -7,12 +7,12 @@ import ( // WalkHandler is a function invoked for each node in the rewrite tree. If it returns non-nil, // that value is returned from the walk. Otherwise, the walk continues. -type WalkHandler func(childOneof *core.SetOperation_Child) (interface{}, error) +type WalkHandler func(childOneof *core.SetOperation_Child) (any, error) // WalkRewrite walks a userset rewrite tree, invoking the handler found on each node of the tree // until the handler returns a non-nil value, which is in turn returned from this function. Returns // nil if no valid value was found. If the rewrite is nil, returns nil. -func WalkRewrite(rewrite *core.UsersetRewrite, handler WalkHandler) (interface{}, error) { +func WalkRewrite(rewrite *core.UsersetRewrite, handler WalkHandler) (any, error) { if rewrite == nil { return nil, nil } @@ -32,7 +32,7 @@ func WalkRewrite(rewrite *core.UsersetRewrite, handler WalkHandler) (interface{} // HasThis returns true if there exists a `_this` node anywhere within the given rewrite. If // the rewrite is nil, returns false. func HasThis(rewrite *core.UsersetRewrite) (bool, error) { - result, err := WalkRewrite(rewrite, func(childOneof *core.SetOperation_Child) (interface{}, error) { + result, err := WalkRewrite(rewrite, func(childOneof *core.SetOperation_Child) (any, error) { switch childOneof.ChildType.(type) { case *core.SetOperation_Child_XThis: return true, nil @@ -43,7 +43,7 @@ func HasThis(rewrite *core.UsersetRewrite) (bool, error) { return result != nil && result.(bool), err } -func walkRewriteChildren(so *core.SetOperation, handler WalkHandler) (interface{}, error) { +func walkRewriteChildren(so *core.SetOperation, handler WalkHandler) (any, error) { for _, childOneof := range so.Child { vle, err := handler(childOneof) if err != nil { diff --git a/pkg/middleware/consistency/consistency.go b/pkg/middleware/consistency/consistency.go index 49349cd8c4..d0b448c29c 100644 --- a/pkg/middleware/consistency/consistency.go +++ b/pkg/middleware/consistency/consistency.go @@ -63,7 +63,7 @@ func RevisionFromContext(ctx context.Context) (datastore.Revision, *v1.ZedToken, // AddRevisionToContext adds a revision to the given context, based on the consistency block found // in the given request (if applicable). -func AddRevisionToContext(ctx context.Context, req interface{}, ds datastore.Datastore, serviceLabel string) error { +func AddRevisionToContext(ctx context.Context, req any, ds datastore.Datastore, serviceLabel string) error { switch req := req.(type) { case hasConsistency: return addRevisionToContextFromConsistency(ctx, req, ds, serviceLabel) @@ -187,7 +187,7 @@ var bypassServiceWhitelist = map[string]struct{}{ // UnaryServerInterceptor returns a new unary server interceptor that performs per-request exchange of // the specified consistency configuration for the revision at which to perform the request. func UnaryServerInterceptor(serviceLabel string) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { for bypass := range bypassServiceWhitelist { if strings.HasPrefix(info.FullMethod, bypass) { return handler(ctx, req) @@ -206,7 +206,7 @@ func UnaryServerInterceptor(serviceLabel string) grpc.UnaryServerInterceptor { // StreamServerInterceptor returns a new stream server interceptor that performs per-request exchange of // the specified consistency configuration for the revision at which to perform the request. func StreamServerInterceptor(serviceLabel string) grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { for bypass := range bypassServiceWhitelist { if strings.HasPrefix(info.FullMethod, bypass) { return handler(srv, stream) @@ -221,12 +221,12 @@ type recvWrapper struct { grpc.ServerStream ctx context.Context serviceLabel string - handler func(ctx context.Context, req interface{}, ds datastore.Datastore, serviceLabel string) error + handler func(ctx context.Context, req any, ds datastore.Datastore, serviceLabel string) error } func (s *recvWrapper) Context() context.Context { return s.ctx } -func (s *recvWrapper) RecvMsg(m interface{}) error { +func (s *recvWrapper) RecvMsg(m any) error { if err := s.ServerStream.RecvMsg(m); err != nil { return err } diff --git a/pkg/middleware/consistency/forcefull.go b/pkg/middleware/consistency/forcefull.go index 9234c4c66a..80a9304b74 100644 --- a/pkg/middleware/consistency/forcefull.go +++ b/pkg/middleware/consistency/forcefull.go @@ -13,7 +13,7 @@ import ( // ForceFullConsistencyUnaryServerInterceptor returns a new unary server interceptor that enforces full consistency // for all requests, except for those in the bypassServiceWhitelist. func ForceFullConsistencyUnaryServerInterceptor(serviceLabel string) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { for bypass := range bypassServiceWhitelist { if strings.HasPrefix(info.FullMethod, bypass) { return handler(ctx, req) @@ -32,7 +32,7 @@ func ForceFullConsistencyUnaryServerInterceptor(serviceLabel string) grpc.UnaryS // ForceFullConsistencyStreamServerInterceptor returns a new stream server interceptor that enforces full consistency // for all requests, except for those in the bypassServiceWhitelist. func ForceFullConsistencyStreamServerInterceptor(serviceLabel string) grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { for bypass := range bypassServiceWhitelist { if strings.HasPrefix(info.FullMethod, bypass) { return handler(srv, stream) @@ -43,7 +43,7 @@ func ForceFullConsistencyStreamServerInterceptor(serviceLabel string) grpc.Strea } } -func setFullConsistencyRevisionToContext(ctx context.Context, req interface{}, ds datastore.Datastore, serviceLabel string) error { +func setFullConsistencyRevisionToContext(ctx context.Context, req any, ds datastore.Datastore, serviceLabel string) error { handle := ctx.Value(revisionKey) if handle == nil { return nil diff --git a/pkg/middleware/nodeid/nodeid.go b/pkg/middleware/nodeid/nodeid.go index 3885036625..877d73de8a 100644 --- a/pkg/middleware/nodeid/nodeid.go +++ b/pkg/middleware/nodeid/nodeid.go @@ -75,7 +75,7 @@ func setInContext(ctx context.Context, nodeID string) error { // UnaryServerInterceptor returns a new unary server interceptor that adds the // node ID to the context. If empty, spicedb:$hostname is used. func UnaryServerInterceptor(nodeID string) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { newCtx := ContextWithHandle(ctx) if nodeID != "" { if err := setInContext(newCtx, nodeID); err != nil { @@ -89,7 +89,7 @@ func UnaryServerInterceptor(nodeID string) grpc.UnaryServerInterceptor { // StreamServerInterceptor returns a new stream server interceptor that adds the // node ID to the context. If empty, spicedb:$hostname is used. func StreamServerInterceptor(nodeID string) grpc.StreamServerInterceptor { - return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { wrapped := middleware.WrapServerStream(stream) wrapped.WrappedContext = ContextWithHandle(wrapped.WrappedContext) if nodeID != "" { diff --git a/pkg/namespace/metadata.go b/pkg/namespace/metadata.go index a82480b8ee..27cfa52557 100644 --- a/pkg/namespace/metadata.go +++ b/pkg/namespace/metadata.go @@ -107,3 +107,89 @@ func SetRelationKind(relation *core.Relation, kind iv1.RelationMetadata_Relation metadata.MetadataMessage = append(metadata.MetadataMessage, encoded) return nil } + +// GetTypeAnnotations returns the type annotations for a permission relation. +func GetTypeAnnotations(relation *core.Relation) []string { + if relation.Metadata == nil { + return nil + } + + for _, metadataAny := range relation.Metadata.MetadataMessage { + var relationMetadata iv1.RelationMetadata + if err := metadataAny.UnmarshalTo(&relationMetadata); err != nil { + // Skip if this metadata message is not RelationMetadata + continue + } + + if relationMetadata.Kind == iv1.RelationMetadata_PERMISSION { + if relationMetadata.TypeAnnotations != nil { + return relationMetadata.TypeAnnotations.Types + } + return nil + } + } + + return nil +} + +// SetTypeAnnotations sets the type annotations for a permission relation. +// If typeAnnotations is nil, removes any existing type annotations. +func SetTypeAnnotations(relation *core.Relation, typeAnnotations []string) error { + if relation.Metadata == nil { + if typeAnnotations == nil { + return nil // Nothing to remove + } + relation.Metadata = &core.Metadata{} + } + + // Find existing PERMISSION RelationMetadata and update it, or create new one + for i, metadataAny := range relation.Metadata.MetadataMessage { + var relationMetadata iv1.RelationMetadata + if err := metadataAny.UnmarshalTo(&relationMetadata); err != nil { + continue // Skip if this is not RelationMetadata + } + + // Only update if this is the PERMISSION metadata + if relationMetadata.Kind == iv1.RelationMetadata_PERMISSION { + if typeAnnotations == nil { + // Remove type annotations by setting to nil + relationMetadata.TypeAnnotations = nil + } else { + // Update existing RelationMetadata with type annotations + relationMetadata.TypeAnnotations = &iv1.TypeAnnotations{ + Types: typeAnnotations, + } + } + + // Re-encode and replace the existing message + updatedAny, err := anypb.New(&relationMetadata) + if err != nil { + return err + } + + relation.Metadata.MetadataMessage[i] = updatedAny + return nil + } + } + + // If no existing RelationMetadata found and typeAnnotations is nil, nothing to do + if typeAnnotations == nil { + return nil + } + + // If no existing RelationMetadata found, create new one + relationMetadata := &iv1.RelationMetadata{ + Kind: iv1.RelationMetadata_PERMISSION, + TypeAnnotations: &iv1.TypeAnnotations{ + Types: typeAnnotations, + }, + } + + metadataAny, err := anypb.New(relationMetadata) + if err != nil { + return err + } + + relation.Metadata.MetadataMessage = append(relation.Metadata.MetadataMessage, metadataAny) + return nil +} diff --git a/pkg/namespace/metadata_test.go b/pkg/namespace/metadata_test.go index a54b997005..f66dccc700 100644 --- a/pkg/namespace/metadata_test.go +++ b/pkg/namespace/metadata_test.go @@ -60,3 +60,159 @@ func TestMetadata(t *testing.T) { require.Equal(iv1.RelationMetadata_PERMISSION, GetRelationKind(ns.Relation[0])) } + +func TestTypeAnnotations(t *testing.T) { + tests := []struct { + name string + setupRelation func() *core.Relation + setAnnotations []string + expectedAnnotations []string + expectError bool + }{ + { + name: "get from relation with no metadata", + setupRelation: func() *core.Relation { + return &core.Relation{Name: "test"} + }, + expectedAnnotations: nil, + }, + { + name: "get from relation with empty metadata", + setupRelation: func() *core.Relation { + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{}, + } + }, + expectedAnnotations: nil, + }, + { + name: "get from non-permission relation", + setupRelation: func() *core.Relation { + relationMetadata := &iv1.RelationMetadata{Kind: iv1.RelationMetadata_RELATION} + metadataAny, _ := anypb.New(relationMetadata) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{metadataAny}, + }, + } + }, + expectedAnnotations: nil, + }, + { + name: "get from permission relation without type annotations", + setupRelation: func() *core.Relation { + relationMetadata := &iv1.RelationMetadata{Kind: iv1.RelationMetadata_PERMISSION} + metadataAny, _ := anypb.New(relationMetadata) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{metadataAny}, + }, + } + }, + expectedAnnotations: nil, + }, + { + name: "get from permission relation with type annotations", + setupRelation: func() *core.Relation { + relationMetadata := &iv1.RelationMetadata{ + Kind: iv1.RelationMetadata_PERMISSION, + TypeAnnotations: &iv1.TypeAnnotations{ + Types: []string{"user", "group"}, + }, + } + metadataAny, _ := anypb.New(relationMetadata) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{metadataAny}, + }, + } + }, + expectedAnnotations: []string{"user", "group"}, + }, + { + name: "set on relation with no metadata", + setupRelation: func() *core.Relation { + return &core.Relation{Name: "test"} + }, + setAnnotations: []string{"user", "group"}, + expectedAnnotations: []string{"user", "group"}, + }, + { + name: "set on relation with existing metadata", + setupRelation: func() *core.Relation { + docComment := &iv1.DocComment{Comment: "test comment"} + docAny, _ := anypb.New(docComment) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{docAny}, + }, + } + }, + setAnnotations: []string{"user"}, + expectedAnnotations: []string{"user"}, + }, + { + name: "update existing permission metadata", + setupRelation: func() *core.Relation { + relationMetadata := &iv1.RelationMetadata{ + Kind: iv1.RelationMetadata_PERMISSION, + TypeAnnotations: &iv1.TypeAnnotations{ + Types: []string{"user"}, + }, + } + metadataAny, _ := anypb.New(relationMetadata) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{metadataAny}, + }, + } + }, + setAnnotations: []string{"user", "group", "organization"}, + expectedAnnotations: []string{"user", "group", "organization"}, + }, + { + name: "remove annotations with nil", + setupRelation: func() *core.Relation { + relationMetadata := &iv1.RelationMetadata{ + Kind: iv1.RelationMetadata_PERMISSION, + TypeAnnotations: &iv1.TypeAnnotations{ + Types: []string{"user", "group"}, + }, + } + metadataAny, _ := anypb.New(relationMetadata) + return &core.Relation{ + Name: "test", + Metadata: &core.Metadata{ + MetadataMessage: []*anypb.Any{metadataAny}, + }, + } + }, + setAnnotations: nil, + expectedAnnotations: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + relation := tt.setupRelation() + + if tt.setAnnotations != nil || (tt.setAnnotations == nil && tt.name == "remove annotations with nil") { + err := SetTypeAnnotations(relation, tt.setAnnotations) + if tt.expectError { + require.Error(t, err) + return + } + require.NoError(t, err) + } + + annotations := GetTypeAnnotations(relation) + require.Equal(t, tt.expectedAnnotations, annotations) + }) + } +} diff --git a/pkg/proto/impl/v1/impl.pb.go b/pkg/proto/impl/v1/impl.pb.go index 67ee033f1d..e5b8bc198e 100644 --- a/pkg/proto/impl/v1/impl.pb.go +++ b/pkg/proto/impl/v1/impl.pb.go @@ -67,7 +67,7 @@ func (x RelationMetadata_RelationKind) Number() protoreflect.EnumNumber { // Deprecated: Use RelationMetadata_RelationKind.Descriptor instead. func (RelationMetadata_RelationKind) EnumDescriptor() ([]byte, []int) { - return file_impl_v1_impl_proto_rawDescGZIP(), []int{6, 0} + return file_impl_v1_impl_proto_rawDescGZIP(), []int{7, 0} } type DecodedCaveat struct { @@ -518,18 +518,66 @@ func (x *DocComment) GetComment() string { return "" } +type TypeAnnotations struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Types []string `protobuf:"bytes,1,rep,name=types,proto3" json:"types,omitempty"` +} + +func (x *TypeAnnotations) Reset() { + *x = TypeAnnotations{} + if protoimpl.UnsafeEnabled { + mi := &file_impl_v1_impl_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TypeAnnotations) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TypeAnnotations) ProtoMessage() {} + +func (x *TypeAnnotations) ProtoReflect() protoreflect.Message { + mi := &file_impl_v1_impl_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TypeAnnotations.ProtoReflect.Descriptor instead. +func (*TypeAnnotations) Descriptor() ([]byte, []int) { + return file_impl_v1_impl_proto_rawDescGZIP(), []int{6} +} + +func (x *TypeAnnotations) GetTypes() []string { + if x != nil { + return x.Types + } + return nil +} + type RelationMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Kind RelationMetadata_RelationKind `protobuf:"varint,1,opt,name=kind,proto3,enum=impl.v1.RelationMetadata_RelationKind" json:"kind,omitempty"` + Kind RelationMetadata_RelationKind `protobuf:"varint,1,opt,name=kind,proto3,enum=impl.v1.RelationMetadata_RelationKind" json:"kind,omitempty"` + TypeAnnotations *TypeAnnotations `protobuf:"bytes,2,opt,name=type_annotations,json=typeAnnotations,proto3" json:"type_annotations,omitempty"` } func (x *RelationMetadata) Reset() { *x = RelationMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[6] + mi := &file_impl_v1_impl_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -542,7 +590,7 @@ func (x *RelationMetadata) String() string { func (*RelationMetadata) ProtoMessage() {} func (x *RelationMetadata) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[6] + mi := &file_impl_v1_impl_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -555,7 +603,7 @@ func (x *RelationMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use RelationMetadata.ProtoReflect.Descriptor instead. func (*RelationMetadata) Descriptor() ([]byte, []int) { - return file_impl_v1_impl_proto_rawDescGZIP(), []int{6} + return file_impl_v1_impl_proto_rawDescGZIP(), []int{7} } func (x *RelationMetadata) GetKind() RelationMetadata_RelationKind { @@ -565,6 +613,13 @@ func (x *RelationMetadata) GetKind() RelationMetadata_RelationKind { return RelationMetadata_UNKNOWN_KIND } +func (x *RelationMetadata) GetTypeAnnotations() *TypeAnnotations { + if x != nil { + return x.TypeAnnotations + } + return nil +} + type NamespaceAndRevision struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -577,7 +632,7 @@ type NamespaceAndRevision struct { func (x *NamespaceAndRevision) Reset() { *x = NamespaceAndRevision{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[7] + mi := &file_impl_v1_impl_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -590,7 +645,7 @@ func (x *NamespaceAndRevision) String() string { func (*NamespaceAndRevision) ProtoMessage() {} func (x *NamespaceAndRevision) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[7] + mi := &file_impl_v1_impl_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -603,7 +658,7 @@ func (x *NamespaceAndRevision) ProtoReflect() protoreflect.Message { // Deprecated: Use NamespaceAndRevision.ProtoReflect.Descriptor instead. func (*NamespaceAndRevision) Descriptor() ([]byte, []int) { - return file_impl_v1_impl_proto_rawDescGZIP(), []int{7} + return file_impl_v1_impl_proto_rawDescGZIP(), []int{8} } func (x *NamespaceAndRevision) GetNamespaceName() string { @@ -631,7 +686,7 @@ type V1Alpha1Revision struct { func (x *V1Alpha1Revision) Reset() { *x = V1Alpha1Revision{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[8] + mi := &file_impl_v1_impl_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -644,7 +699,7 @@ func (x *V1Alpha1Revision) String() string { func (*V1Alpha1Revision) ProtoMessage() {} func (x *V1Alpha1Revision) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[8] + mi := &file_impl_v1_impl_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -657,7 +712,7 @@ func (x *V1Alpha1Revision) ProtoReflect() protoreflect.Message { // Deprecated: Use V1Alpha1Revision.ProtoReflect.Descriptor instead. func (*V1Alpha1Revision) Descriptor() ([]byte, []int) { - return file_impl_v1_impl_proto_rawDescGZIP(), []int{8} + return file_impl_v1_impl_proto_rawDescGZIP(), []int{9} } func (x *V1Alpha1Revision) GetNsRevisions() []*NamespaceAndRevision { @@ -678,7 +733,7 @@ type DecodedZookie_V1Zookie struct { func (x *DecodedZookie_V1Zookie) Reset() { *x = DecodedZookie_V1Zookie{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[9] + mi := &file_impl_v1_impl_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -691,7 +746,7 @@ func (x *DecodedZookie_V1Zookie) String() string { func (*DecodedZookie_V1Zookie) ProtoMessage() {} func (x *DecodedZookie_V1Zookie) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[9] + mi := &file_impl_v1_impl_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -725,7 +780,7 @@ type DecodedZookie_V2Zookie struct { func (x *DecodedZookie_V2Zookie) Reset() { *x = DecodedZookie_V2Zookie{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[10] + mi := &file_impl_v1_impl_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -738,7 +793,7 @@ func (x *DecodedZookie_V2Zookie) String() string { func (*DecodedZookie_V2Zookie) ProtoMessage() {} func (x *DecodedZookie_V2Zookie) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[10] + mi := &file_impl_v1_impl_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -772,7 +827,7 @@ type DecodedZedToken_V1Zookie struct { func (x *DecodedZedToken_V1Zookie) Reset() { *x = DecodedZedToken_V1Zookie{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[11] + mi := &file_impl_v1_impl_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -785,7 +840,7 @@ func (x *DecodedZedToken_V1Zookie) String() string { func (*DecodedZedToken_V1Zookie) ProtoMessage() {} func (x *DecodedZedToken_V1Zookie) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[11] + mi := &file_impl_v1_impl_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -819,7 +874,7 @@ type DecodedZedToken_V1ZedToken struct { func (x *DecodedZedToken_V1ZedToken) Reset() { *x = DecodedZedToken_V1ZedToken{} if protoimpl.UnsafeEnabled { - mi := &file_impl_v1_impl_proto_msgTypes[12] + mi := &file_impl_v1_impl_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -832,7 +887,7 @@ func (x *DecodedZedToken_V1ZedToken) String() string { func (*DecodedZedToken_V1ZedToken) ProtoMessage() {} func (x *DecodedZedToken_V1ZedToken) ProtoReflect() protoreflect.Message { - mi := &file_impl_v1_impl_proto_msgTypes[12] + mi := &file_impl_v1_impl_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -925,36 +980,43 @@ var file_impl_v1_impl_proto_rawDesc = []byte{ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x26, 0x0a, 0x0a, 0x44, 0x6f, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3a, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, - 0x6e, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x69, - 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4b, 0x49, - 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, - 0x10, 0x02, 0x22, 0x59, 0x0a, 0x14, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, - 0x6e, 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x54, 0x0a, - 0x10, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x40, 0x0a, 0x0c, 0x6e, 0x73, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x6e, 0x64, 0x52, 0x65, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x6e, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x42, 0x8a, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6d, 0x70, 0x6c, - 0x2e, 0x76, 0x31, 0x42, 0x09, 0x49, 0x6d, 0x70, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, - 0x68, 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x69, 0x6d, 0x70, 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x69, - 0x6d, 0x70, 0x6c, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x49, 0x6d, - 0x70, 0x6c, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x49, 0x6d, 0x70, 0x6c, 0x5c, 0x56, 0x31, 0xe2, - 0x02, 0x13, 0x49, 0x6d, 0x70, 0x6c, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x49, 0x6d, 0x70, 0x6c, 0x3a, 0x3a, 0x56, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x22, 0x27, 0x0a, 0x0f, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0xd3, 0x01, 0x0a, 0x10, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x3a, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, + 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x10, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x0f, 0x74, 0x79, 0x70, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x22, 0x3e, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x69, 0x6e, 0x64, + 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, + 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x02, + 0x22, 0x59, 0x0a, 0x14, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x6e, 0x64, + 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x54, 0x0a, 0x10, 0x56, + 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x40, 0x0a, 0x0c, 0x6e, 0x73, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x6e, 0x64, 0x52, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x6e, 0x73, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x42, 0x8a, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, + 0x31, 0x42, 0x09, 0x49, 0x6d, 0x70, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x7a, + 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x69, 0x6d, 0x70, 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6d, 0x70, + 0x6c, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x49, 0x6d, 0x70, 0x6c, + 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x49, 0x6d, 0x70, 0x6c, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x13, + 0x49, 0x6d, 0x70, 0x6c, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x49, 0x6d, 0x70, 0x6c, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -970,7 +1032,7 @@ func file_impl_v1_impl_proto_rawDescGZIP() []byte { } var file_impl_v1_impl_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_impl_v1_impl_proto_msgTypes = make([]protoimpl.MessageInfo, 14) +var file_impl_v1_impl_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_impl_v1_impl_proto_goTypes = []any{ (RelationMetadata_RelationKind)(0), // 0: impl.v1.RelationMetadata.RelationKind (*DecodedCaveat)(nil), // 1: impl.v1.DecodedCaveat @@ -979,31 +1041,33 @@ var file_impl_v1_impl_proto_goTypes = []any{ (*DecodedCursor)(nil), // 4: impl.v1.DecodedCursor (*V1Cursor)(nil), // 5: impl.v1.V1Cursor (*DocComment)(nil), // 6: impl.v1.DocComment - (*RelationMetadata)(nil), // 7: impl.v1.RelationMetadata - (*NamespaceAndRevision)(nil), // 8: impl.v1.NamespaceAndRevision - (*V1Alpha1Revision)(nil), // 9: impl.v1.V1Alpha1Revision - (*DecodedZookie_V1Zookie)(nil), // 10: impl.v1.DecodedZookie.V1Zookie - (*DecodedZookie_V2Zookie)(nil), // 11: impl.v1.DecodedZookie.V2Zookie - (*DecodedZedToken_V1Zookie)(nil), // 12: impl.v1.DecodedZedToken.V1Zookie - (*DecodedZedToken_V1ZedToken)(nil), // 13: impl.v1.DecodedZedToken.V1ZedToken - nil, // 14: impl.v1.V1Cursor.FlagsEntry - (*v1alpha1.CheckedExpr)(nil), // 15: google.api.expr.v1alpha1.CheckedExpr + (*TypeAnnotations)(nil), // 7: impl.v1.TypeAnnotations + (*RelationMetadata)(nil), // 8: impl.v1.RelationMetadata + (*NamespaceAndRevision)(nil), // 9: impl.v1.NamespaceAndRevision + (*V1Alpha1Revision)(nil), // 10: impl.v1.V1Alpha1Revision + (*DecodedZookie_V1Zookie)(nil), // 11: impl.v1.DecodedZookie.V1Zookie + (*DecodedZookie_V2Zookie)(nil), // 12: impl.v1.DecodedZookie.V2Zookie + (*DecodedZedToken_V1Zookie)(nil), // 13: impl.v1.DecodedZedToken.V1Zookie + (*DecodedZedToken_V1ZedToken)(nil), // 14: impl.v1.DecodedZedToken.V1ZedToken + nil, // 15: impl.v1.V1Cursor.FlagsEntry + (*v1alpha1.CheckedExpr)(nil), // 16: google.api.expr.v1alpha1.CheckedExpr } var file_impl_v1_impl_proto_depIdxs = []int32{ - 15, // 0: impl.v1.DecodedCaveat.cel:type_name -> google.api.expr.v1alpha1.CheckedExpr - 10, // 1: impl.v1.DecodedZookie.v1:type_name -> impl.v1.DecodedZookie.V1Zookie - 11, // 2: impl.v1.DecodedZookie.v2:type_name -> impl.v1.DecodedZookie.V2Zookie - 12, // 3: impl.v1.DecodedZedToken.deprecated_v1_zookie:type_name -> impl.v1.DecodedZedToken.V1Zookie - 13, // 4: impl.v1.DecodedZedToken.v1:type_name -> impl.v1.DecodedZedToken.V1ZedToken + 16, // 0: impl.v1.DecodedCaveat.cel:type_name -> google.api.expr.v1alpha1.CheckedExpr + 11, // 1: impl.v1.DecodedZookie.v1:type_name -> impl.v1.DecodedZookie.V1Zookie + 12, // 2: impl.v1.DecodedZookie.v2:type_name -> impl.v1.DecodedZookie.V2Zookie + 13, // 3: impl.v1.DecodedZedToken.deprecated_v1_zookie:type_name -> impl.v1.DecodedZedToken.V1Zookie + 14, // 4: impl.v1.DecodedZedToken.v1:type_name -> impl.v1.DecodedZedToken.V1ZedToken 5, // 5: impl.v1.DecodedCursor.v1:type_name -> impl.v1.V1Cursor - 14, // 6: impl.v1.V1Cursor.flags:type_name -> impl.v1.V1Cursor.FlagsEntry + 15, // 6: impl.v1.V1Cursor.flags:type_name -> impl.v1.V1Cursor.FlagsEntry 0, // 7: impl.v1.RelationMetadata.kind:type_name -> impl.v1.RelationMetadata.RelationKind - 8, // 8: impl.v1.V1Alpha1Revision.ns_revisions:type_name -> impl.v1.NamespaceAndRevision - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 7, // 8: impl.v1.RelationMetadata.type_annotations:type_name -> impl.v1.TypeAnnotations + 9, // 9: impl.v1.V1Alpha1Revision.ns_revisions:type_name -> impl.v1.NamespaceAndRevision + 10, // [10:10] is the sub-list for method output_type + 10, // [10:10] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_impl_v1_impl_proto_init() } @@ -1085,7 +1149,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*RelationMetadata); i { + switch v := v.(*TypeAnnotations); i { case 0: return &v.state case 1: @@ -1097,7 +1161,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*NamespaceAndRevision); i { + switch v := v.(*RelationMetadata); i { case 0: return &v.state case 1: @@ -1109,7 +1173,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*V1Alpha1Revision); i { + switch v := v.(*NamespaceAndRevision); i { case 0: return &v.state case 1: @@ -1121,7 +1185,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[9].Exporter = func(v any, i int) any { - switch v := v.(*DecodedZookie_V1Zookie); i { + switch v := v.(*V1Alpha1Revision); i { case 0: return &v.state case 1: @@ -1133,7 +1197,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[10].Exporter = func(v any, i int) any { - switch v := v.(*DecodedZookie_V2Zookie); i { + switch v := v.(*DecodedZookie_V1Zookie); i { case 0: return &v.state case 1: @@ -1145,7 +1209,7 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[11].Exporter = func(v any, i int) any { - switch v := v.(*DecodedZedToken_V1Zookie); i { + switch v := v.(*DecodedZookie_V2Zookie); i { case 0: return &v.state case 1: @@ -1157,6 +1221,18 @@ func file_impl_v1_impl_proto_init() { } } file_impl_v1_impl_proto_msgTypes[12].Exporter = func(v any, i int) any { + switch v := v.(*DecodedZedToken_V1Zookie); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_impl_v1_impl_proto_msgTypes[13].Exporter = func(v any, i int) any { switch v := v.(*DecodedZedToken_V1ZedToken); i { case 0: return &v.state @@ -1189,7 +1265,7 @@ func file_impl_v1_impl_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_impl_v1_impl_proto_rawDesc, NumEnums: 1, - NumMessages: 14, + NumMessages: 15, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/proto/impl/v1/impl.pb.validate.go b/pkg/proto/impl/v1/impl.pb.validate.go index dea8479bb2..f0c9db3eac 100644 --- a/pkg/proto/impl/v1/impl.pb.validate.go +++ b/pkg/proto/impl/v1/impl.pb.validate.go @@ -913,6 +913,106 @@ var _ interface { ErrorName() string } = DocCommentValidationError{} +// Validate checks the field values on TypeAnnotations with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *TypeAnnotations) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on TypeAnnotations with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// TypeAnnotationsMultiError, or nil if none found. +func (m *TypeAnnotations) ValidateAll() error { + return m.validate(true) +} + +func (m *TypeAnnotations) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return TypeAnnotationsMultiError(errors) + } + + return nil +} + +// TypeAnnotationsMultiError is an error wrapping multiple validation errors +// returned by TypeAnnotations.ValidateAll() if the designated constraints +// aren't met. +type TypeAnnotationsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m TypeAnnotationsMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m TypeAnnotationsMultiError) AllErrors() []error { return m } + +// TypeAnnotationsValidationError is the validation error returned by +// TypeAnnotations.Validate if the designated constraints aren't met. +type TypeAnnotationsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e TypeAnnotationsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e TypeAnnotationsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e TypeAnnotationsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e TypeAnnotationsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e TypeAnnotationsValidationError) ErrorName() string { return "TypeAnnotationsValidationError" } + +// Error satisfies the builtin error interface +func (e TypeAnnotationsValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sTypeAnnotations.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = TypeAnnotationsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = TypeAnnotationsValidationError{} + // Validate checks the field values on RelationMetadata with the rules defined // in the proto definition for this message. If any rules are violated, the // first error encountered is returned, or nil if there are no violations. @@ -937,6 +1037,35 @@ func (m *RelationMetadata) validate(all bool) error { // no validation rules for Kind + if all { + switch v := interface{}(m.GetTypeAnnotations()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RelationMetadataValidationError{ + field: "TypeAnnotations", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RelationMetadataValidationError{ + field: "TypeAnnotations", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetTypeAnnotations()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RelationMetadataValidationError{ + field: "TypeAnnotations", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return RelationMetadataMultiError(errors) } diff --git a/pkg/proto/impl/v1/impl_vtproto.pb.go b/pkg/proto/impl/v1/impl_vtproto.pb.go index 95e368513f..4815efe3e7 100644 --- a/pkg/proto/impl/v1/impl_vtproto.pb.go +++ b/pkg/proto/impl/v1/impl_vtproto.pb.go @@ -282,12 +282,34 @@ func (m *DocComment) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *TypeAnnotations) CloneVT() *TypeAnnotations { + if m == nil { + return (*TypeAnnotations)(nil) + } + r := new(TypeAnnotations) + if rhs := m.Types; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Types = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *TypeAnnotations) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *RelationMetadata) CloneVT() *RelationMetadata { if m == nil { return (*RelationMetadata)(nil) } r := new(RelationMetadata) r.Kind = m.Kind + r.TypeAnnotations = m.TypeAnnotations.CloneVT() if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -755,6 +777,31 @@ func (this *DocComment) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *TypeAnnotations) EqualVT(that *TypeAnnotations) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if len(this.Types) != len(that.Types) { + return false + } + for i, vx := range this.Types { + vy := that.Types[i] + if vx != vy { + return false + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *TypeAnnotations) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*TypeAnnotations) + if !ok { + return false + } + return this.EqualVT(that) +} func (this *RelationMetadata) EqualVT(that *RelationMetadata) bool { if this == that { return true @@ -764,6 +811,9 @@ func (this *RelationMetadata) EqualVT(that *RelationMetadata) bool { if this.Kind != that.Kind { return false } + if !this.TypeAnnotations.EqualVT(that.TypeAnnotations) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1435,6 +1485,48 @@ func (m *DocComment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TypeAnnotations) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TypeAnnotations) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TypeAnnotations) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Types) > 0 { + for iNdEx := len(m.Types) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Types[iNdEx]) + copy(dAtA[i:], m.Types[iNdEx]) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Types[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *RelationMetadata) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -1465,6 +1557,16 @@ func (m *RelationMetadata) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.TypeAnnotations != nil { + size, err := m.TypeAnnotations.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } if m.Kind != 0 { i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Kind)) i-- @@ -1817,6 +1919,22 @@ func (m *DocComment) SizeVT() (n int) { return n } +func (m *TypeAnnotations) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Types) > 0 { + for _, s := range m.Types { + l = len(s) + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + func (m *RelationMetadata) SizeVT() (n int) { if m == nil { return 0 @@ -1826,6 +1944,10 @@ func (m *RelationMetadata) SizeVT() (n int) { if m.Kind != 0 { n += 1 + protohelpers.SizeOfVarint(uint64(m.Kind)) } + if m.TypeAnnotations != nil { + l = m.TypeAnnotations.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -3063,6 +3185,89 @@ func (m *DocComment) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *TypeAnnotations) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TypeAnnotations: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TypeAnnotations: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Types", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Types = append(m.Types, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RelationMetadata) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -3111,6 +3316,42 @@ func (m *RelationMetadata) UnmarshalVT(dAtA []byte) error { break } } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TypeAnnotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TypeAnnotations == nil { + m.TypeAnnotations = &TypeAnnotations{} + } + if err := m.TypeAnnotations.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/releases/releases.go b/pkg/releases/releases.go index f51665201a..5a1f75f987 100644 --- a/pkg/releases/releases.go +++ b/pkg/releases/releases.go @@ -2,11 +2,10 @@ package releases import ( "context" + "encoding/json" "fmt" "net/http" "time" - - "github.com/google/go-github/v43/github" ) const ( @@ -37,19 +36,38 @@ func GetLatestRelease(ctx context.Context) (*Release, error) { } func getLatestReleaseWithClient(ctx context.Context, httpClient *http.Client) (*Release, error) { - client := github.NewClient(httpClient) - release, _, err := client.Repositories.GetLatestRelease(ctx, githubNamespace, githubRepository) + url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", githubNamespace, githubRepository) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/vnd.github+json") + + resp, err := httpClient.Do(req) if err != nil { return nil, err } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status: %s", resp.Status) + } - if release == nil { - return nil, fmt.Errorf("latest release not found") + var ghResp struct { + Name string `json:"name"` + PublishedAt time.Time `json:"published_at"` + HTMLURL string `json:"html_url"` + } + + if err := json.NewDecoder(resp.Body).Decode(&ghResp); err != nil { + return nil, err } return &Release{ - Version: *release.Name, - PublishedAt: (*release.PublishedAt).UTC(), - ViewURL: *release.HTMLURL, + Version: ghResp.Name, + PublishedAt: ghResp.PublishedAt.UTC(), + ViewURL: ghResp.HTMLURL, }, nil } diff --git a/pkg/schema/errors.go b/pkg/schema/errors.go index e81f315bf4..7cd9f64405 100644 --- a/pkg/schema/errors.go +++ b/pkg/schema/errors.go @@ -404,3 +404,11 @@ func NewTypeWithSourceError(wrapped error, withSource nspkg.WithSourcePosition, 0, )) } + +func backtickNames(names []string) []string { + out := make([]string, len(names)) + for i, n := range names { + out[i] = fmt.Sprintf("`%s`", n) + } + return out +} diff --git a/pkg/schema/reachabilitygraph.go b/pkg/schema/reachabilitygraph.go index b8b9b262a2..707b2026e0 100644 --- a/pkg/schema/reachabilitygraph.go +++ b/pkg/schema/reachabilitygraph.go @@ -3,12 +3,13 @@ package schema import ( "context" "fmt" + "maps" + "slices" "sort" "strconv" "sync" "github.com/cespare/xxhash/v2" - "golang.org/x/exp/maps" "github.com/authzed/spicedb/pkg/genutil/mapz" core "github.com/authzed/spicedb/pkg/proto/core/v1" @@ -194,7 +195,7 @@ func (rg *DefinitionReachability) computeEntrypoints( encounteredRelations := map[string]struct{}{} err := rg.collectEntrypoints(ctx, resourceType, optionalSubjectType, collected, encounteredRelations, reachabilityOption, entrypointLookupOption) if err != nil { - return nil, maps.Keys(encounteredRelations), err + return nil, slices.Collect(maps.Keys(encounteredRelations)), err } collectedEntrypoints := *collected @@ -211,7 +212,7 @@ func (rg *DefinitionReachability) computeEntrypoints( for _, entrypoint := range collectedEntrypoints { hash, err := entrypoint.Hash() if err != nil { - return nil, maps.Keys(encounteredRelations), err + return nil, slices.Collect(maps.Keys(encounteredRelations)), err } if _, ok := entrypointMap[hash]; !ok { @@ -220,7 +221,7 @@ func (rg *DefinitionReachability) computeEntrypoints( } } - return uniqueEntrypoints, maps.Keys(encounteredRelations), nil + return uniqueEntrypoints, slices.Collect(maps.Keys(encounteredRelations)), nil } func (rg *DefinitionReachability) getOrBuildGraph(ctx context.Context, resourceType *core.RelationReference, reachabilityOption reachabilityOption) (*core.ReachabilityGraph, error) { @@ -300,7 +301,7 @@ func (rg *DefinitionReachability) collectEntrypoints( } // Sort the keys to ensure a stable graph is produced. - keys := maps.Keys(rrg.EntrypointsBySubjectRelation) + keys := slices.Collect(maps.Keys(rrg.EntrypointsBySubjectRelation)) sort.Strings(keys) // Recursively collect over any reachability graphs for subjects with non-ellipsis relations. diff --git a/pkg/schema/type_check_test.go b/pkg/schema/type_check_test.go index 9d5313ea7a..aa538cd2c1 100644 --- a/pkg/schema/type_check_test.go +++ b/pkg/schema/type_check_test.go @@ -417,6 +417,123 @@ func TestTypecheckingWithSubrelations(t *testing.T) { } } +func TestTypeAnnotationsValidation(t *testing.T) { + t.Parallel() + type testcase struct { + name string + schemaText string + expectedError string + } + tcs := []testcase{ + { + name: "valid type annotation", + schemaText: `use typechecking + definition user {} + + definition document { + relation viewer: user + permission view: user = viewer + }`, + expectedError: "", + }, + { + name: "incomplete type annotation", + schemaText: `use typechecking + definition user {} + definition team {} + + definition document { + relation viewer: user | team + permission view: user = viewer + }`, + expectedError: "incomplete type annotation on relation `view` in definition `document`: `team` found as reachable type, but not contained in provided set [`user`]", + }, + { + name: "complete type annotation with multiple types", + schemaText: `use typechecking + definition user {} + definition team {} + + definition document { + relation viewer: user | team + permission view: user | team = viewer + }`, + expectedError: "", + }, + { + name: "type annotation with arrow operation", + schemaText: `use typechecking + definition user {} + + definition organization { + relation member: user + } + + definition document { + relation org: organization + permission view: user = org->member + }`, + expectedError: "", + }, + { + name: "incomplete type annotation with arrow operation", + schemaText: `use typechecking + definition user {} + definition admin {} + + definition organization { + relation member: user | admin + } + + definition document { + relation org: organization + permission view: user = org->member + }`, + expectedError: "incomplete type annotation on relation `view` in definition `document`: `admin` found as reachable type, but not contained in provided set [`user`]", + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + tc := tc + t.Parallel() + + schema, err := compiler.Compile(compiler.InputSchema{ + Source: "", + SchemaString: tc.schemaText, + }, compiler.AllowUnprefixedObjectType()) + require.NoError(t, err) + + res := ResolverForCompiledSchema(*schema) + ts := NewTypeSystem(res) + + var foundError error + for _, resource := range schema.ObjectDefinitions { + def, err := ts.GetDefinition(t.Context(), resource.Name) + if err != nil { + foundError = err + break + } + _, verr := def.Validate(t.Context()) + if verr != nil { + foundError = verr + break + } + } + + if tc.expectedError == "" { + require.NoError(t, foundError) + } else { + if foundError == nil { + t.Errorf("Expected error containing '%s' but got no error", tc.expectedError) + } else { + require.Contains(t, foundError.Error(), tc.expectedError) + } + } + }) + } +} + func TestIncompleteSchema(t *testing.T) { // This test is a little redundant, as doing this type checking requires one to have the full schema, but it _may_ be pulled dynamically and fail. // So until we operate in complete schema caching, there are fail points that can bubble up. diff --git a/pkg/schema/typesystem_validation.go b/pkg/schema/typesystem_validation.go index fa9315eb0c..908e62f936 100644 --- a/pkg/schema/typesystem_validation.go +++ b/pkg/schema/typesystem_validation.go @@ -3,6 +3,7 @@ package schema import ( "context" "fmt" + "slices" "github.com/authzed/spicedb/pkg/genutil/mapz" "github.com/authzed/spicedb/pkg/graph" @@ -35,9 +36,25 @@ func (ts *TypeSystem) GetValidatedDefinition(ctx context.Context, definition str func (def *Definition) Validate(ctx context.Context) (*ValidatedDefinition, error) { for _, relation := range def.relationMap { - relation := relation + // Validate type annotations first. + // If there's type annotation metadata, the annotated terminal types are a superset of the reachable ones. + if annotations := nspkg.GetTypeAnnotations(relation); len(annotations) != 0 { + tset, err := def.ts.GetRecursiveTerminalTypesForRelation(ctx, def.nsDef.GetName(), relation.GetName()) + if err != nil { + return nil, err + } + for _, typ := range tset { + if !slices.Contains(annotations, typ) { + return nil, NewTypeWithSourceError( + fmt.Errorf("incomplete type annotation on relation `%s` in definition `%s`: `%s` found as reachable type, but not contained in provided set %v", relation.GetName(), def.nsDef.GetName(), typ, backtickNames(annotations)), + relation, + relation.GetName(), + ) + } + } + } - // Validate the usersets's. + // Validate the usersets. usersetRewrite := relation.GetUsersetRewrite() rerr, err := graph.WalkRewrite(usersetRewrite, func(childOneof *core.SetOperation_Child) (any, error) { switch child := childOneof.ChildType.(type) { diff --git a/pkg/schemadsl/compiler/compiler.go b/pkg/schemadsl/compiler/compiler.go index d4ffea3de3..24c59f8728 100644 --- a/pkg/schemadsl/compiler/compiler.go +++ b/pkg/schemadsl/compiler/compiler.go @@ -5,9 +5,9 @@ import ( "fmt" "google.golang.org/protobuf/proto" - "k8s.io/utils/strings/slices" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" + "github.com/authzed/spicedb/pkg/genutil/slicez" core "github.com/authzed/spicedb/pkg/proto/core/v1" "github.com/authzed/spicedb/pkg/schemadsl/dslshape" "github.com/authzed/spicedb/pkg/schemadsl/input" @@ -76,16 +76,27 @@ func CaveatTypeSet(cts *caveattypes.TypeSet) Option { return func(cfg *config) { cfg.caveatTypeSet = cts } } -const expirationFlag = "expiration" +const ( + expirationFlag = "expiration" + deprecationFlag = "deprecation" +) func DisallowExpirationFlag() Option { return func(cfg *config) { - cfg.allowedFlags = slices.Filter([]string{}, cfg.allowedFlags, func(s string) bool { + cfg.allowedFlags = slicez.Filter(cfg.allowedFlags, func(s string) bool { return s != expirationFlag }) } } +func DisallowDeprecationFlag() Option { + return func(cfg *config) { + cfg.allowedFlags = slicez.Filter(cfg.allowedFlags, func(s string) bool { + return s != deprecationFlag + }) + } +} + type Option func(*config) type ObjectPrefixOption func(*config) @@ -98,6 +109,7 @@ func Compile(schema InputSchema, prefix ObjectPrefixOption, opts ...Option) (*Co // Enable `expiration` flag by default. cfg.allowedFlags = append(cfg.allowedFlags, expirationFlag) + cfg.allowedFlags = append(cfg.allowedFlags, deprecationFlag) prefix(cfg) // required option diff --git a/pkg/schemadsl/compiler/node.go b/pkg/schemadsl/compiler/node.go index b7e2a703dd..5f20ec53d3 100644 --- a/pkg/schemadsl/compiler/node.go +++ b/pkg/schemadsl/compiler/node.go @@ -11,14 +11,14 @@ import ( type dslNode struct { nodeType dslshape.NodeType - properties map[string]interface{} + properties map[string]any children map[string]*list.List } func createAstNode(_ input.Source, kind dslshape.NodeType) parser.AstNode { return &dslNode{ nodeType: kind, - properties: make(map[string]interface{}), + properties: make(map[string]any), children: make(map[string]*list.List), } } @@ -163,7 +163,7 @@ func (tn *dslNode) Lookup(predicateName string) (*dslNode, error) { return nil, fmt.Errorf("nothing in predicate %s", predicateName) } -func (tn *dslNode) Errorf(message string, args ...interface{}) error { +func (tn *dslNode) Errorf(message string, args ...any) error { return withNodeError{ error: fmt.Errorf(message, args...), errorSourceCode: "", @@ -171,7 +171,7 @@ func (tn *dslNode) Errorf(message string, args ...interface{}) error { } } -func (tn *dslNode) WithSourceErrorf(sourceCode string, message string, args ...interface{}) error { +func (tn *dslNode) WithSourceErrorf(sourceCode string, message string, args ...any) error { return withNodeError{ error: fmt.Errorf(message, args...), errorSourceCode: sourceCode, diff --git a/pkg/schemadsl/compiler/translator.go b/pkg/schemadsl/compiler/translator.go index 9f5ab01f23..681a20c5cb 100644 --- a/pkg/schemadsl/compiler/translator.go +++ b/pkg/schemadsl/compiler/translator.go @@ -11,7 +11,6 @@ import ( "github.com/authzed/spicedb/pkg/caveats" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" - "github.com/authzed/spicedb/pkg/genutil/mapz" "github.com/authzed/spicedb/pkg/namespace" core "github.com/authzed/spicedb/pkg/proto/core/v1" "github.com/authzed/spicedb/pkg/schemadsl/dslshape" @@ -54,7 +53,7 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) var objectDefinitions []*core.NamespaceDefinition var caveatDefinitions []*core.CaveatDefinition - names := mapz.NewSet[string]() + nodes := make(map[string]*dslNode) for _, definitionNode := range root.GetChildren() { var definition SchemaDefinition @@ -86,13 +85,27 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) objectDefinitions = append(objectDefinitions, def) } - if !names.Add(definition.GetName()) { + if _, ok := nodes[definition.GetName()]; ok { return nil, definitionNode.WithSourceErrorf(definition.GetName(), "found name reused between multiple definitions and/or caveats: %s", definition.GetName()) } + nodes[definition.GetName()] = definitionNode + orderedDefinitions = append(orderedDefinitions, definition) } + // Strip the type annotation metadata if typechecking isn't enabled. + if !slices.Contains(tctx.enabledFlags, "typechecking") { + for _, def := range objectDefinitions { + for _, rel := range def.GetRelation() { + err := namespace.SetTypeAnnotations(rel, nil) + if err != nil { + return nil, err + } + } + } + } + return &CompiledSchema{ CaveatDefinitions: caveatDefinitions, ObjectDefinitions: objectDefinitions, @@ -220,12 +233,16 @@ func translateObjectDefinition(tctx *translationContext, defNode *dslNode) (*cor continue } - if relationOrPermissionNode.GetType() == dslshape.NodeTypeDeprecated { + if relationOrPermissionNode.GetType() == dslshape.NodeTypeDeprecation { + if !slices.Contains(tctx.allowedFlags, "deprecation") || !slices.Contains(tctx.enabledFlags, "deprecation") { + return nil, relationOrPermissionNode.WithSourceErrorf(tctx.deprecatedType, "deprecation not enabled: %w", err) + } tctx.deprecatedRelation = true tctx.deprecatedType, err = relationOrPermissionNode.GetString(dslshape.NodeDeprecatedPredicateName) if err != nil { return nil, relationOrPermissionNode.WithSourceErrorf(tctx.deprecatedType, "invalid deprecation type: %w", err) } + continue } @@ -392,6 +409,17 @@ func translatePermission(tctx *translationContext, permissionNode *dslNode) (*co return nil, permissionNode.Errorf("invalid permission name: %w", err) } + // Check for optional type annotations + var typeAnnotations []string + typeAnnotationNode, err := permissionNode.Lookup(dslshape.NodePermissionPredicateTypeAnnotations) + if err == nil { + annotations, err := extractTypeAnnotations(typeAnnotationNode) + if err != nil { + return nil, permissionNode.Errorf("error extracting type annotations: %w", err) + } + typeAnnotations = annotations + } + expressionNode, err := permissionNode.Lookup(dslshape.NodePermissionPredicateComputeExpression) if err != nil { return nil, permissionNode.Errorf("invalid permission expression: %w", err) @@ -407,6 +435,14 @@ func translatePermission(tctx *translationContext, permissionNode *dslNode) (*co return nil, err } + // Store type annotations in metadata + if len(typeAnnotations) > 0 { + err = namespace.SetTypeAnnotations(permission, typeAnnotations) + if err != nil { + return nil, permissionNode.Errorf("error adding type annotations to metadata: %w", err) + } + } + if !tctx.skipValidate { if err := permission.Validate(); err != nil { return nil, permissionNode.Errorf("error in permission %s: %w", permissionName, err) @@ -416,6 +452,23 @@ func translatePermission(tctx *translationContext, permissionNode *dslNode) (*co return permission, nil } +// extractTypeAnnotations is a helper function to return the literal identifiers under the type annotation node +func extractTypeAnnotations(typeAnnotationNode *dslNode) ([]string, error) { + children := typeAnnotationNode.List(dslshape.NodeTypeAnnotationPredicateTypes) + + annotations := make([]string, 0, len(children)) + + for _, child := range children { + typeName, err := child.GetString(dslshape.NodeIdentiferPredicateValue) + if err != nil { + return nil, err + } + annotations = append(annotations, typeName) + } + + return annotations, nil +} + func translateBinary(tctx *translationContext, expressionNode *dslNode) (*core.SetOperation_Child, *core.SetOperation_Child, error) { leftChild, err := expressionNode.Lookup(dslshape.NodeExpressionPredicateLeftExpr) if err != nil { diff --git a/pkg/schemadsl/compiler/type_annotations_integration_test.go b/pkg/schemadsl/compiler/type_annotations_integration_test.go new file mode 100644 index 0000000000..8f9834cf11 --- /dev/null +++ b/pkg/schemadsl/compiler/type_annotations_integration_test.go @@ -0,0 +1,237 @@ +package compiler + +import ( + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/authzed/spicedb/pkg/namespace" + core "github.com/authzed/spicedb/pkg/proto/core/v1" + implv1 "github.com/authzed/spicedb/pkg/proto/impl/v1" + "github.com/authzed/spicedb/pkg/schemadsl/input" +) + +func TestTypeAnnotationsIntegration(t *testing.T) { + tests := []struct { + name string + schema string + expectedPermission string + expectedAnnotations []string + shouldContainMetadata bool + }{ + { + name: "single type annotation", + schema: `use typechecking +definition user {} +definition document { + permission view: user = user +}`, + expectedPermission: "view", + expectedAnnotations: []string{"user"}, + shouldContainMetadata: true, + }, + { + name: "multiple type annotations", + schema: `use typechecking +definition user {} +definition organization {} +definition document { + permission edit: user | organization = user +}`, + expectedPermission: "edit", + expectedAnnotations: []string{"user", "organization"}, + shouldContainMetadata: true, + }, + { + name: "permission without type annotation", + schema: `use typechecking +definition user {} +definition document { + permission read = user +}`, + expectedPermission: "read", + expectedAnnotations: nil, + shouldContainMetadata: false, + }, + { + name: "mixed permissions with and without annotations", + schema: `use typechecking +definition user {} +definition admin {} +definition document { + permission view: user = user + permission delete = admin +}`, + expectedPermission: "view", // We'll test the annotated one + expectedAnnotations: []string{"user"}, + shouldContainMetadata: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + compiled, err := Compile(InputSchema{ + Source: input.Source("test"), + SchemaString: tt.schema, + }, AllowUnprefixedObjectType()) + require.NoError(t, err) + require.NotNil(t, compiled) + + // Find the document definition and the expected permission + var foundPermission *core.Relation + for _, ns := range compiled.ObjectDefinitions { + if ns.Name == "document" { + for _, rel := range ns.Relation { + if rel.Name == tt.expectedPermission { + foundPermission = rel + break + } + } + break + } + } + + require.NotNil(t, foundPermission, "Permission %s not found", tt.expectedPermission) + + if !tt.shouldContainMetadata { + // For permissions without type annotations, PERMISSION metadata should still exist (created by namespace.Relation) + // but type annotations should be empty + require.NotNil(t, foundPermission.Metadata, "All permissions should have metadata") + + // Find the PERMISSION RelationMetadata + var foundMetadata *implv1.RelationMetadata + for _, metadataAny := range foundPermission.Metadata.MetadataMessage { + var relationMetadata implv1.RelationMetadata + if err := metadataAny.UnmarshalTo(&relationMetadata); err == nil { + if relationMetadata.Kind == implv1.RelationMetadata_PERMISSION { + foundMetadata = &relationMetadata + break + } + } + } + + require.NotNil(t, foundMetadata, "Should have PERMISSION RelationMetadata") + if foundMetadata.TypeAnnotations != nil { + require.Empty(t, foundMetadata.TypeAnnotations.Types, "Type annotations should be empty for permission without type annotations") + } + + // Test the helper function for retrieving type annotations + retrievedAnnotations := namespace.GetTypeAnnotations(foundPermission) + require.Empty(t, retrievedAnnotations, "Retrieved type annotations should be empty") + return + } + + // For permissions with type annotations, verify metadata exists + require.NotNil(t, foundPermission.Metadata, "Metadata should not be nil for permission with type annotations") + require.NotEmpty(t, foundPermission.Metadata.MetadataMessage, "MetadataMessage should not be empty") + + // Find the RelationMetadata with PERMISSION kind + var foundMetadata *implv1.RelationMetadata + for _, metadataAny := range foundPermission.Metadata.MetadataMessage { + var relationMetadata implv1.RelationMetadata + if err := metadataAny.UnmarshalTo(&relationMetadata); err == nil { + if relationMetadata.Kind == implv1.RelationMetadata_PERMISSION { + foundMetadata = &relationMetadata + break + } + } + } + + require.NotNil(t, foundMetadata, "Should have PERMISSION RelationMetadata") + require.Equal(t, implv1.RelationMetadata_PERMISSION, foundMetadata.Kind) + require.NotNil(t, foundMetadata.TypeAnnotations, "TypeAnnotations should not be nil") + require.Equal(t, tt.expectedAnnotations, foundMetadata.TypeAnnotations.Types) + + // Test the helper function for retrieving type annotations + retrievedAnnotations := namespace.GetTypeAnnotations(foundPermission) + require.Equal(t, tt.expectedAnnotations, retrievedAnnotations) + }) + } +} + +func TestTypeAnnotationsHelperFunctions(t *testing.T) { + tests := []struct { + name string + setupMetadata func() *core.Metadata + expectedAnnotations []string + expectError bool + }{ + { + name: "nil metadata", + setupMetadata: func() *core.Metadata { + return nil + }, + expectedAnnotations: nil, + expectError: false, + }, + { + name: "empty metadata messages", + setupMetadata: func() *core.Metadata { + return &core.Metadata{ + MetadataMessage: []*anypb.Any{}, + } + }, + expectedAnnotations: nil, + expectError: false, + }, + { + name: "metadata with non-RelationMetadata message", + setupMetadata: func() *core.Metadata { + docComment := &implv1.DocComment{Comment: "test comment"} + docAny, _ := anypb.New(docComment) + return &core.Metadata{ + MetadataMessage: []*anypb.Any{docAny}, + } + }, + expectedAnnotations: nil, + expectError: false, + }, + { + name: "metadata with RELATION kind (not PERMISSION)", + setupMetadata: func() *core.Metadata { + relationMetadata := &implv1.RelationMetadata{ + Kind: implv1.RelationMetadata_RELATION, + TypeAnnotations: &implv1.TypeAnnotations{ + Types: []string{"ignored"}, + }, + } + relAny, _ := anypb.New(relationMetadata) + return &core.Metadata{ + MetadataMessage: []*anypb.Any{relAny}, + } + }, + expectedAnnotations: nil, + expectError: false, + }, + { + name: "metadata with PERMISSION kind and type annotations", + setupMetadata: func() *core.Metadata { + relationMetadata := &implv1.RelationMetadata{ + Kind: implv1.RelationMetadata_PERMISSION, + TypeAnnotations: &implv1.TypeAnnotations{ + Types: []string{"user", "admin"}, + }, + } + relAny, _ := anypb.New(relationMetadata) + return &core.Metadata{ + MetadataMessage: []*anypb.Any{relAny}, + } + }, + expectedAnnotations: []string{"user", "admin"}, + expectError: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + relation := &core.Relation{ + Name: "test", + Metadata: tt.setupMetadata(), + } + + annotations := namespace.GetTypeAnnotations(relation) + require.Equal(t, tt.expectedAnnotations, annotations) + }) + } +} diff --git a/pkg/schemadsl/dslshape/dslshape.go b/pkg/schemadsl/dslshape/dslshape.go index ff9f85137b..54fd8baaaf 100644 --- a/pkg/schemadsl/dslshape/dslshape.go +++ b/pkg/schemadsl/dslshape/dslshape.go @@ -18,10 +18,11 @@ const ( NodeTypeCaveatParameter // A caveat parameter. NodeTypeCaveatExpression // A caveat expression. - NodeTypeRelation // A relation - NodeTypePermission // A permission + NodeTypeRelation // A relation + NodeTypePermission // A permission + NodeTypeTypeAnnotation // A type annotation for permissions - NodeTypeDeprecated // A deprecated relation. + NodeTypeDeprecation // A deprecated relation. NodeTypeTypeReference // A type reference NodeTypeSpecificTypeReference // A reference to a specific type. NodeTypeCaveatReference // A caveat reference under a type. @@ -185,9 +186,19 @@ const ( // NodeTypePermission // + // The type annotations for the permission. + NodePermissionPredicateTypeAnnotations = "type-annotations" + // The expression to compute the permission. NodePermissionPredicateComputeExpression = "compute-expression" + // + // NodeTypeTypeAnnotation + // + + // The type names in the type annotation. + NodeTypeAnnotationPredicateTypes = "annotation-types" + // // NodeTypeArrowExpression // @@ -211,5 +222,6 @@ const ( // // NodeTypeDeprecated // - NodeDeprecatedPredicateName = "deprecated-relation" + // The value of a deprecated node + NodeDeprecatedPredicateName = "deprecated-relation-value" ) diff --git a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go index 7b4b32021f..16e83c9ec6 100644 --- a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go +++ b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go @@ -18,23 +18,24 @@ func _() { _ = x[NodeTypeCaveatExpression-7] _ = x[NodeTypeRelation-8] _ = x[NodeTypePermission-9] - _ = x[NodeTypeDeprecated-10] - _ = x[NodeTypeTypeReference-11] - _ = x[NodeTypeSpecificTypeReference-12] - _ = x[NodeTypeCaveatReference-13] - _ = x[NodeTypeTraitReference-14] - _ = x[NodeTypeUnionExpression-15] - _ = x[NodeTypeIntersectExpression-16] - _ = x[NodeTypeExclusionExpression-17] - _ = x[NodeTypeArrowExpression-18] - _ = x[NodeTypeIdentifier-19] - _ = x[NodeTypeNilExpression-20] - _ = x[NodeTypeCaveatTypeReference-21] + _ = x[NodeTypeTypeAnnotation-10] + _ = x[NodeTypeDeprecation-11] + _ = x[NodeTypeTypeReference-12] + _ = x[NodeTypeSpecificTypeReference-13] + _ = x[NodeTypeCaveatReference-14] + _ = x[NodeTypeTraitReference-15] + _ = x[NodeTypeUnionExpression-16] + _ = x[NodeTypeIntersectExpression-17] + _ = x[NodeTypeExclusionExpression-18] + _ = x[NodeTypeArrowExpression-19] + _ = x[NodeTypeIdentifier-20] + _ = x[NodeTypeNilExpression-21] + _ = x[NodeTypeCaveatTypeReference-22] } -const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeDeprecatedNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" +const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeAnnotationNodeTypeDeprecationNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" -var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 196, 217, 246, 269, 291, 314, 341, 368, 391, 409, 430, 457} +var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 200, 219, 240, 269, 292, 314, 337, 364, 391, 414, 432, 453, 480} func (i NodeType) String() string { if i < 0 || i >= NodeType(len(_NodeType_index)-1) { diff --git a/pkg/schemadsl/generator/generator.go b/pkg/schemadsl/generator/generator.go index 3c8fdd95e3..79ae847d9d 100644 --- a/pkg/schemadsl/generator/generator.go +++ b/pkg/schemadsl/generator/generator.go @@ -3,11 +3,11 @@ package generator import ( "bufio" "fmt" + "maps" + "slices" "sort" "strings" - "golang.org/x/exp/maps" - "github.com/authzed/spicedb/pkg/caveats" caveattypes "github.com/authzed/spicedb/pkg/caveats/types" "github.com/authzed/spicedb/pkg/genutil/mapz" @@ -138,7 +138,7 @@ func (sg *sourceGenerator) emitCaveat(caveat *core.CaveatDefinition) error { sg.append(caveat.Name) sg.append("(") - parameterNames := maps.Keys(caveat.ParameterTypes) + parameterNames := slices.Collect(maps.Keys(caveat.ParameterTypes)) sort.Strings(parameterNames) for index, paramName := range parameterNames { @@ -202,6 +202,20 @@ func (sg *sourceGenerator) emitNamespace(namespace *core.NamespaceDefinition) er sg.markNewScope() for _, relation := range namespace.Relation { + if relation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + sg.flags.Add("deprecation") + sg.append("@deprecated(") + + switch relation.DeprecationType { + case core.DeprecationType_DEPRECATED_TYPE_WARNING: + sg.append("warn") + case core.DeprecationType_DEPRECATED_TYPE_ERROR: + sg.append("error") + } + sg.append(")") + sg.appendLine() + } + err := sg.emitRelation(relation) if err != nil { return err diff --git a/pkg/schemadsl/generator/generator_test.go b/pkg/schemadsl/generator/generator_test.go index d5e43cdc6e..8ab944ab55 100644 --- a/pkg/schemadsl/generator/generator_test.go +++ b/pkg/schemadsl/generator/generator_test.go @@ -395,6 +395,38 @@ definition document { relation viewer: user }`, }, + { + "deprecation test", + `use deprecation + + definition document { + + @deprecated(warn) + relation viewer: user + + @deprecated(error) + relation editor: user + }`, + `use deprecation + +definition document { + @deprecated(warn) + relation viewer: user + @deprecated(error) + relation editor: user +}`, + }, + { + "unused deprecation flag", + `use deprecation + + definition document{ + relation viewer: user + }`, + `definition document { + relation viewer: user +}`, + }, } for _, test := range tests { diff --git a/pkg/schemadsl/input/sourcepositionmapper.go b/pkg/schemadsl/input/sourcepositionmapper.go index 1bca03c81a..7dff70f871 100644 --- a/pkg/schemadsl/input/sourcepositionmapper.go +++ b/pkg/schemadsl/input/sourcepositionmapper.go @@ -50,7 +50,7 @@ type lineAndStart struct { startPosition int } -func inclusiveComparator(a, b interface{}) int { +func inclusiveComparator(a, b any) int { i1 := a.(inclusiveRange) i2 := b.(inclusiveRange) diff --git a/pkg/schemadsl/lexer/flaggablelexer_test.go b/pkg/schemadsl/lexer/flaggablelexer_test.go index 3ecc89bf11..330ab9c837 100644 --- a/pkg/schemadsl/lexer/flaggablelexer_test.go +++ b/pkg/schemadsl/lexer/flaggablelexer_test.go @@ -48,6 +48,12 @@ var flaggableLexerTests = []lexerTest{ {TokenTypeIdentifier, 0, "expiration", ""}, tEOF, }}, + {"use deprecation", "use deprecation", []Lexeme{ + {TokenTypeIdentifier, 0, "use", ""}, + {TokenTypeWhitespace, 0, " ", ""}, + {TokenTypeKeyword, 0, "deprecation", ""}, + tEOF, + }}, } func TestFlaggableLexer(t *testing.T) { diff --git a/pkg/schemadsl/lexer/flags.go b/pkg/schemadsl/lexer/flags.go index 3bfbbde775..0034495e51 100644 --- a/pkg/schemadsl/lexer/flags.go +++ b/pkg/schemadsl/lexer/flags.go @@ -1,8 +1,30 @@ package lexer -// FlagExpiration indicates that `expiration` is supported as a first-class -// feature in the schema. -const FlagExpiration = "expiration" +import ( + "maps" + "slices" +) + +const ( + // FlagExpiration indicates that `expiration` is supported as a first-class + // feature in the schema. + FlagExpiration = "expiration" + + // FlagTypeChecking indicates that `typechecking` is supported as a first-class + // feature in the schema. + FlagTypeChecking = "typechecking" + + // FlagDeprecation indicates that `deprecation` is supported as a first-class + // feature in the schema. + FlagDeprecation = "deprecation" +) + +var AllUseFlags []string + +func init() { + AllUseFlags = slices.Collect(maps.Keys(Flags)) + slices.Sort(AllUseFlags) +} type transformer func(lexeme Lexeme) (Lexeme, bool) @@ -23,4 +45,23 @@ var Flags = map[string]transformer{ return lexeme, false }, + + FlagDeprecation: func(lexeme Lexeme) (Lexeme, bool) { + if lexeme.Kind == TokenTypeIdentifier && lexeme.Value == "deprecation" { + lexeme.Kind = TokenTypeKeyword + return lexeme, true + } + + return lexeme, false + }, + + FlagTypeChecking: func(lexeme Lexeme) (Lexeme, bool) { + // `typechecking` becomes a keyword. + if lexeme.Kind == TokenTypeIdentifier && lexeme.Value == "typechecking" { + lexeme.Kind = TokenTypeKeyword + return lexeme, true + } + + return lexeme, false + }, } diff --git a/pkg/schemadsl/lexer/lex.go b/pkg/schemadsl/lexer/lex.go index a09df50fec..569def6420 100644 --- a/pkg/schemadsl/lexer/lex.go +++ b/pkg/schemadsl/lexer/lex.go @@ -155,7 +155,7 @@ func (l *Lexer) emit(t TokenType) { // errorf returns an error token and terminates the scan by passing // back a nil pointer that will be the next state, terminating l.nexttoken. -func (l *Lexer) errorf(currentRune rune, format string, args ...interface{}) stateFn { +func (l *Lexer) errorf(currentRune rune, format string, args ...any) stateFn { l.tokens <- Lexeme{TokenTypeError, l.start, string(currentRune), fmt.Sprintf(format, args...)} return nil } diff --git a/pkg/schemadsl/lexer/lex_def.go b/pkg/schemadsl/lexer/lex_def.go index cb090f9139..ec855359e5 100644 --- a/pkg/schemadsl/lexer/lex_def.go +++ b/pkg/schemadsl/lexer/lex_def.go @@ -156,11 +156,7 @@ Loop: case r == '%': l.emit(TokenTypePercent) case r == '@': - if l.acceptString("deprecated") { - l.emit(TokenTypeKeyword) - } else { - l.emit(TokenTypeAt) - } + l.emit(TokenTypeAt) case r == '<': if l.acceptString("=") { diff --git a/pkg/schemadsl/lexer/lex_test.go b/pkg/schemadsl/lexer/lex_test.go index c22a635964..33198ceec7 100644 --- a/pkg/schemadsl/lexer/lex_test.go +++ b/pkg/schemadsl/lexer/lex_test.go @@ -260,11 +260,13 @@ var lexerTests = []lexerTest{ tEOF, }}, {"deprecation test with keyword", "@deprecated", []Lexeme{ - {TokenTypeKeyword, 0, "@deprecated", ""}, + {TokenTypeAt, 0, "@", ""}, + {TokenTypeKeyword, 0, "deprecated", ""}, tEOF, }}, {"deprecation test with keyword and identifier", "@deprecated(something)", []Lexeme{ - {TokenTypeKeyword, 0, "@deprecated", ""}, + {TokenTypeAt, 0, "@", ""}, + {TokenTypeKeyword, 0, "deprecated", ""}, {TokenTypeLeftParen, 0, "(", ""}, {TokenTypeIdentifier, 0, "something", ""}, {TokenTypeRightParen, 0, ")", ""}, diff --git a/pkg/schemadsl/parser/parser.go b/pkg/schemadsl/parser/parser.go index 1c78628204..6c028df83c 100644 --- a/pkg/schemadsl/parser/parser.go +++ b/pkg/schemadsl/parser/parser.go @@ -4,8 +4,6 @@ package parser import ( "strings" - "golang.org/x/exp/maps" - "github.com/authzed/spicedb/pkg/schemadsl/dslshape" "github.com/authzed/spicedb/pkg/schemadsl/input" "github.com/authzed/spicedb/pkg/schemadsl/lexer" @@ -261,7 +259,7 @@ func (p *sourceParser) consumeUseFlag(afterDefinition bool) AstNode { } if _, ok := lexer.Flags[useFlag]; !ok { - p.emitErrorf("Unknown use flag: `%s`. Options are: %s", useFlag, strings.Join(maps.Keys(lexer.Flags), ", ")) + p.emitErrorf("Unknown use flag: `%s`. Options are: %s", useFlag, strings.Join(lexer.AllUseFlags, ", ")) return useNode } @@ -310,14 +308,14 @@ func (p *sourceParser) consumeDefinition() AstNode { // relation ... // permission ... switch { + case p.isToken(lexer.TokenTypeAt): + defNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) + case p.isKeyword("relation"): defNode.Connect(dslshape.NodePredicateChild, p.consumeRelation()) case p.isKeyword("permission"): defNode.Connect(dslshape.NodePredicateChild, p.consumePermission()) - - case p.isKeyword("@deprecated"): - defNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) } ok := p.consumeStatementTerminator() @@ -325,7 +323,6 @@ func (p *sourceParser) consumeDefinition() AstNode { break } } - return defNode } @@ -357,30 +354,33 @@ func (p *sourceParser) consumeRelation() AstNode { } func (p *sourceParser) consumeDeprecation() AstNode { - relNode := p.startNode(dslshape.NodeTypeDeprecated) + depNode := p.startNode(dslshape.NodeTypeDeprecation) defer p.mustFinishNode() - // deprecation - p.consumeKeyword("@deprecated") + p.consume(lexer.TokenTypeAt) - _, ok := p.consume(lexer.TokenTypeLeftParen) + ok := p.consumeKeyword("deprecated") if !ok { - return relNode + return depNode } - deprecationType, ok := p.consumeIdentifier() + _, ok = p.consume(lexer.TokenTypeLeftParen) if !ok { - return relNode + return depNode } - relNode.MustDecorate(dslshape.NodeDeprecatedPredicateName, deprecationType) + deprecationType, ok := p.consumeIdentifier() + if !ok { + return depNode + } + depNode.MustDecorate(dslshape.NodeDeprecatedPredicateName, deprecationType) _, ok = p.consume(lexer.TokenTypeRightParen) if !ok { - return relNode + return depNode } - return relNode + return depNode } // consumeTypeReference consumes a reference to a type or types of relations. @@ -516,7 +516,7 @@ func (p *sourceParser) consumeTypePath() (string, bool) { } // consumePermission consumes a permission. -// ```permission foo = bar + baz``` +// ```permission foo = bar + baz``` or ```permission foo: user = bar + baz``` func (p *sourceParser) consumePermission() AstNode { permNode := p.startNode(dslshape.NodeTypePermission) defer p.mustFinishNode() @@ -530,6 +530,12 @@ func (p *sourceParser) consumePermission() AstNode { permNode.MustDecorate(dslshape.NodePredicateName, permissionName) + // Check for optional type annotation: user | organization + if _, ok := p.tryConsume(lexer.TokenTypeColon); ok { + typeAnnotationNode := p.consumeTypeAnnotation() + permNode.Connect(dslshape.NodePermissionPredicateTypeAnnotations, typeAnnotationNode) + } + // = _, ok = p.consume(lexer.TokenTypeEquals) if !ok { @@ -540,6 +546,47 @@ func (p *sourceParser) consumePermission() AstNode { return permNode } +// consumeTypeAnnotation consumes a type annotation for permissions. +// ```user | organization``` +func (p *sourceParser) consumeTypeAnnotation() AstNode { + typeAnnotationNode := p.startNode(dslshape.NodeTypeTypeAnnotation) + defer p.mustFinishNode() + + // Consume the first type + firstType, ok := p.consumeIdentifier() + if !ok { + p.emitErrorf("Expected type identifier in type annotation") + return typeAnnotationNode + } + + // Create identifier node for the first type + firstTypeNode := p.startNode(dslshape.NodeTypeIdentifier) + firstTypeNode.MustDecorate(dslshape.NodeIdentiferPredicateValue, firstType) + p.mustFinishNode() + typeAnnotationNode.Connect(dslshape.NodeTypeAnnotationPredicateTypes, firstTypeNode) + + // Consume additional types separated by pipe operator + for { + if _, ok := p.tryConsume(lexer.TokenTypePipe); !ok { + break + } + + nextType, ok := p.consumeIdentifier() + if !ok { + p.emitErrorf("Expected type identifier after '|' in type annotation") + return typeAnnotationNode + } + + // Create identifier node for the additional type + nextTypeNode := p.startNode(dslshape.NodeTypeIdentifier) + nextTypeNode.MustDecorate(dslshape.NodeIdentiferPredicateValue, nextType) + p.mustFinishNode() + typeAnnotationNode.Connect(dslshape.NodeTypeAnnotationPredicateTypes, nextTypeNode) + } + + return typeAnnotationNode +} + // ComputeExpressionOperators defines the binary operators in precedence order. var ComputeExpressionOperators = []binaryOpDefinition{ {lexer.TokenTypeMinus, dslshape.NodeTypeExclusionExpression}, diff --git a/pkg/schemadsl/parser/parser_impl.go b/pkg/schemadsl/parser/parser_impl.go index ca02ca82ac..906c631f1c 100644 --- a/pkg/schemadsl/parser/parser_impl.go +++ b/pkg/schemadsl/parser/parser_impl.go @@ -77,7 +77,7 @@ func (p *sourceParser) createNode(kind dslshape.NodeType) AstNode { } // createErrorNodef creates a new error node and returns it. -func (p *sourceParser) createErrorNodef(format string, args ...interface{}) AstNode { +func (p *sourceParser) createErrorNodef(format string, args ...any) AstNode { message := fmt.Sprintf(format, args...) node := p.startNode(dslshape.NodeTypeError).MustDecorate(dslshape.NodePredicateErrorMessage, message) p.mustFinishNode() @@ -175,7 +175,7 @@ func (p *sourceParser) isKeyword(keyword string) bool { // emitErrorf creates a new error node and attachs it as a child of the current // node. -func (p *sourceParser) emitErrorf(format string, args ...interface{}) { +func (p *sourceParser) emitErrorf(format string, args ...any) { errorNode := p.createErrorNodef(format, args...) if len(p.currentToken.Value) > 0 { errorNode.MustDecorate(dslshape.NodePredicateErrorSource, p.currentToken.Value) diff --git a/pkg/schemadsl/parser/parser_test.go b/pkg/schemadsl/parser/parser_test.go index 7ef2931732..6b0f113765 100644 --- a/pkg/schemadsl/parser/parser_test.go +++ b/pkg/schemadsl/parser/parser_test.go @@ -16,7 +16,7 @@ import ( type testNode struct { nodeType dslshape.NodeType - properties map[string]interface{} + properties map[string]any children map[string]*list.List } @@ -53,7 +53,7 @@ func (pt *parserTest) writeTree(value string) { func createAstNode(_ input.Source, kind dslshape.NodeType) AstNode { return &testNode{ nodeType: kind, - properties: make(map[string]interface{}), + properties: make(map[string]any), children: make(map[string]*list.List), } } @@ -142,6 +142,18 @@ func TestParser(t *testing.T) { {"permission type annotation double colon test", "permission_type_annotation_double_colon"}, {"permission type annotation newline after colon test", "permission_type_annotation_newline_after_colon"}, {"permission type annotation just pipe test", "permission_type_annotation_just_pipe"}, + {"use typechecking test", "use_typechecking"}, + {"permission type annotation test", "permission_type_annotation"}, + {"permission mixed annotations test", "permission_mixed_annotations"}, + {"permission multiple types test", "permission_multiple_types"}, + {"permission mixed single multiple test", "permission_mixed_single_multiple"}, + {"permission edge cases test", "permission_edge_cases"}, + {"permission type annotation empty after colon test", "permission_type_annotation_empty_after_colon"}, + {"permission type annotation pipe no type before test", "permission_type_annotation_pipe_no_type_before"}, + {"permission type annotation trailing pipe no type after test", "permission_type_annotation_trailing_pipe_no_type_after"}, + {"permission type annotation double colon test", "permission_type_annotation_double_colon"}, + {"permission type annotation newline after colon test", "permission_type_annotation_newline_after_colon"}, + {"permission type annotation just pipe test", "permission_type_annotation_just_pipe"}, {"deprecated relation test", "deprecation"}, {"invalid deprecated relation test", "invalid-deprecation"}, } diff --git a/pkg/schemadsl/parser/tests/deprecation.zed b/pkg/schemadsl/parser/tests/deprecation.zed index 4b3206b954..f41bda7b8e 100644 --- a/pkg/schemadsl/parser/tests/deprecation.zed +++ b/pkg/schemadsl/parser/tests/deprecation.zed @@ -1,3 +1,5 @@ +use deprecation + definition deprecated_relation { @deprecated(warn) diff --git a/pkg/schemadsl/parser/tests/deprecation.zed.expected b/pkg/schemadsl/parser/tests/deprecation.zed.expected index 2dd10514a8..d64cde9d98 100644 --- a/pkg/schemadsl/parser/tests/deprecation.zed.expected +++ b/pkg/schemadsl/parser/tests/deprecation.zed.expected @@ -1,58 +1,63 @@ NodeTypeFile - end-rune = 152 + end-rune = 169 input-source = deprecated relation test start-rune = 0 child-node => + NodeTypeUseFlag + end-rune = 14 + input-source = deprecated relation test + start-rune = 0 + use-flag-name = deprecation NodeTypeDefinition definition-name = deprecated_relation - end-rune = 132 + end-rune = 149 input-source = deprecated relation test - start-rune = 0 + start-rune = 17 child-node => - NodeTypeDeprecated - deprecated-relation = warn - end-rune = 54 + NodeTypeDeprecation + deprecated-relation-value = warn + end-rune = 71 input-source = deprecated relation test - start-rune = 38 + start-rune = 55 NodeTypeRelation - end-rune = 80 + end-rune = 97 input-source = deprecated relation test relation-name = writer - start-rune = 60 + start-rune = 77 allowed-types => NodeTypeTypeReference - end-rune = 80 + end-rune = 97 input-source = deprecated relation test - start-rune = 77 + start-rune = 94 type-ref-type => NodeTypeSpecificTypeReference - end-rune = 80 + end-rune = 97 input-source = deprecated relation test - start-rune = 77 + start-rune = 94 type-name = user - NodeTypeDeprecated - deprecated-relation = error - end-rune = 104 + NodeTypeDeprecation + deprecated-relation-value = error + end-rune = 121 input-source = deprecated relation test - start-rune = 87 + start-rune = 104 NodeTypeRelation - end-rune = 130 + end-rune = 147 input-source = deprecated relation test relation-name = reader - start-rune = 110 + start-rune = 127 allowed-types => NodeTypeTypeReference - end-rune = 130 + end-rune = 147 input-source = deprecated relation test - start-rune = 127 + start-rune = 144 type-ref-type => NodeTypeSpecificTypeReference - end-rune = 130 + end-rune = 147 input-source = deprecated relation test - start-rune = 127 + start-rune = 144 type-name = user NodeTypeDefinition definition-name = user - end-rune = 152 + end-rune = 169 input-source = deprecated relation test - start-rune = 135 + start-rune = 152 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected index ca8158875d..74ce356b8c 100644 --- a/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected +++ b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected @@ -9,7 +9,7 @@ NodeTypeFile input-source = invalid deprecated relation test start-rune = 0 child-node => - NodeTypeDeprecated + NodeTypeDeprecation end-rune = 48 input-source = invalid deprecated relation test start-rune = 37 diff --git a/pkg/schemadsl/parser/tests/invaliduse.zed.expected b/pkg/schemadsl/parser/tests/invaliduse.zed.expected index f36654ba97..50f1468985 100644 --- a/pkg/schemadsl/parser/tests/invaliduse.zed.expected +++ b/pkg/schemadsl/parser/tests/invaliduse.zed.expected @@ -10,7 +10,7 @@ NodeTypeFile child-node => NodeTypeError end-rune = 12 - error-message = Unknown use flag: `something`. Options are: expiration + error-message = Unknown use flag: `something`. Options are: expiration, typechecking error-source = input-source = invalid use diff --git a/pkg/schemadsl/parser/tests/permission_edge_cases.zed b/pkg/schemadsl/parser/tests/permission_edge_cases.zed new file mode 100644 index 0000000000..c01abaa86d --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_edge_cases.zed @@ -0,0 +1,18 @@ +definition mydefinition { + relation viewer: user + + // Single type + permission single: user = viewer + + // Two types + permission double: user | admin = viewer + + // Three types + permission triple: user | admin | group = viewer + + // Complex expression with types + permission complex: user | admin = viewer + (viewer - viewer) + + // No type annotation + permission none = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_edge_cases.zed.expected b/pkg/schemadsl/parser/tests/permission_edge_cases.zed.expected new file mode 100644 index 0000000000..104caac027 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_edge_cases.zed.expected @@ -0,0 +1,183 @@ +NodeTypeFile + end-rune = 427 + input-source = permission edge cases test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 427 + input-source = permission edge cases test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 50 + input-source = permission edge cases test + relation-name = viewer + start-rune = 30 + allowed-types => + NodeTypeTypeReference + end-rune = 50 + input-source = permission edge cases test + start-rune = 47 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 50 + input-source = permission edge cases test + start-rune = 47 + type-name = user + NodeTypePermission + end-rune = 111 + input-source = permission edge cases test + relation-name = single + start-rune = 80 + child-node => + NodeTypeComment + comment-value = // Single type + compute-expression => + NodeTypeIdentifier + end-rune = 111 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 106 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 102 + input-source = permission edge cases test + start-rune = 99 + annotation-types => + NodeTypeIdentifier + end-rune = 102 + identifier-value = user + input-source = permission edge cases test + start-rune = 104 + NodeTypePermission + end-rune = 180 + input-source = permission edge cases test + relation-name = double + start-rune = 141 + child-node => + NodeTypeComment + comment-value = // Two types + compute-expression => + NodeTypeIdentifier + end-rune = 180 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 175 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 171 + input-source = permission edge cases test + start-rune = 160 + annotation-types => + NodeTypeIdentifier + end-rune = 163 + identifier-value = user + input-source = permission edge cases test + start-rune = 165 + NodeTypeIdentifier + end-rune = 171 + identifier-value = admin + input-source = permission edge cases test + start-rune = 173 + NodeTypePermission + end-rune = 257 + input-source = permission edge cases test + relation-name = triple + start-rune = 210 + child-node => + NodeTypeComment + comment-value = // Three types + compute-expression => + NodeTypeIdentifier + end-rune = 257 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 252 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 248 + input-source = permission edge cases test + start-rune = 229 + annotation-types => + NodeTypeIdentifier + end-rune = 232 + identifier-value = user + input-source = permission edge cases test + start-rune = 234 + NodeTypeIdentifier + end-rune = 240 + identifier-value = admin + input-source = permission edge cases test + start-rune = 242 + NodeTypeIdentifier + end-rune = 248 + identifier-value = group + input-source = permission edge cases test + start-rune = 250 + NodeTypePermission + end-rune = 365 + input-source = permission edge cases test + relation-name = complex + start-rune = 305 + child-node => + NodeTypeComment + comment-value = // Complex expression with types + compute-expression => + NodeTypeUnionExpression + end-rune = 365 + input-source = permission edge cases test + start-rune = 340 + left-expr => + NodeTypeIdentifier + end-rune = 345 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 340 + right-expr => + NodeTypeExclusionExpression + end-rune = 364 + input-source = permission edge cases test + start-rune = 350 + left-expr => + NodeTypeIdentifier + end-rune = 355 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 350 + right-expr => + NodeTypeIdentifier + end-rune = 364 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 359 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 336 + input-source = permission edge cases test + start-rune = 325 + annotation-types => + NodeTypeIdentifier + end-rune = 328 + identifier-value = user + input-source = permission edge cases test + start-rune = 330 + NodeTypeIdentifier + end-rune = 336 + identifier-value = admin + input-source = permission edge cases test + start-rune = 338 + NodeTypePermission + end-rune = 425 + input-source = permission edge cases test + relation-name = none + start-rune = 402 + child-node => + NodeTypeComment + comment-value = // No type annotation + compute-expression => + NodeTypeIdentifier + end-rune = 425 + identifier-value = viewer + input-source = permission edge cases test + start-rune = 420 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed b/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed new file mode 100644 index 0000000000..2bfa7efef8 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed @@ -0,0 +1,7 @@ +definition mydefinition { + relation viewer: user + + permission view: user = viewer + permission edit = viewer + permission admin: group = viewer + edit +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed.expected b/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed.expected new file mode 100644 index 0000000000..65ccb599d1 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_mixed_annotations.zed.expected @@ -0,0 +1,93 @@ +NodeTypeFile + end-rune = 165 + input-source = permission mixed annotations test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 165 + input-source = permission mixed annotations test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 50 + input-source = permission mixed annotations test + relation-name = viewer + start-rune = 30 + allowed-types => + NodeTypeTypeReference + end-rune = 50 + input-source = permission mixed annotations test + start-rune = 47 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 50 + input-source = permission mixed annotations test + start-rune = 47 + type-name = user + NodeTypePermission + end-rune = 90 + input-source = permission mixed annotations test + relation-name = view + start-rune = 61 + compute-expression => + NodeTypeIdentifier + end-rune = 90 + identifier-value = viewer + input-source = permission mixed annotations test + start-rune = 85 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 81 + input-source = permission mixed annotations test + start-rune = 78 + annotation-types => + NodeTypeIdentifier + end-rune = 81 + identifier-value = user + input-source = permission mixed annotations test + start-rune = 83 + NodeTypePermission + end-rune = 119 + input-source = permission mixed annotations test + relation-name = edit + start-rune = 96 + compute-expression => + NodeTypeIdentifier + end-rune = 119 + identifier-value = viewer + input-source = permission mixed annotations test + start-rune = 114 + NodeTypePermission + end-rune = 163 + input-source = permission mixed annotations test + relation-name = admin + start-rune = 125 + compute-expression => + NodeTypeUnionExpression + end-rune = 163 + input-source = permission mixed annotations test + start-rune = 151 + left-expr => + NodeTypeIdentifier + end-rune = 156 + identifier-value = viewer + input-source = permission mixed annotations test + start-rune = 151 + right-expr => + NodeTypeIdentifier + end-rune = 163 + identifier-value = edit + input-source = permission mixed annotations test + start-rune = 160 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 147 + input-source = permission mixed annotations test + start-rune = 143 + annotation-types => + NodeTypeIdentifier + end-rune = 147 + identifier-value = group + input-source = permission mixed annotations test + start-rune = 149 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed b/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed new file mode 100644 index 0000000000..7789418e0e --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed @@ -0,0 +1,8 @@ +definition mydefinition { + relation viewer: user + + permission view: user = viewer + permission edit: user | organization = viewer + permission admin = viewer + permission super: admin | user | group = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed.expected b/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed.expected new file mode 100644 index 0000000000..fa49d2f69d --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_mixed_single_multiple.zed.expected @@ -0,0 +1,119 @@ +NodeTypeFile + end-rune = 224 + input-source = permission mixed single multiple test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 224 + input-source = permission mixed single multiple test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 50 + input-source = permission mixed single multiple test + relation-name = viewer + start-rune = 30 + allowed-types => + NodeTypeTypeReference + end-rune = 50 + input-source = permission mixed single multiple test + start-rune = 47 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 50 + input-source = permission mixed single multiple test + start-rune = 47 + type-name = user + NodeTypePermission + end-rune = 90 + input-source = permission mixed single multiple test + relation-name = view + start-rune = 61 + compute-expression => + NodeTypeIdentifier + end-rune = 90 + identifier-value = viewer + input-source = permission mixed single multiple test + start-rune = 85 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 81 + input-source = permission mixed single multiple test + start-rune = 78 + annotation-types => + NodeTypeIdentifier + end-rune = 81 + identifier-value = user + input-source = permission mixed single multiple test + start-rune = 83 + NodeTypePermission + end-rune = 140 + input-source = permission mixed single multiple test + relation-name = edit + start-rune = 96 + compute-expression => + NodeTypeIdentifier + end-rune = 140 + identifier-value = viewer + input-source = permission mixed single multiple test + start-rune = 135 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 131 + input-source = permission mixed single multiple test + start-rune = 113 + annotation-types => + NodeTypeIdentifier + end-rune = 116 + identifier-value = user + input-source = permission mixed single multiple test + start-rune = 118 + NodeTypeIdentifier + end-rune = 131 + identifier-value = organization + input-source = permission mixed single multiple test + start-rune = 133 + NodeTypePermission + end-rune = 170 + input-source = permission mixed single multiple test + relation-name = admin + start-rune = 146 + compute-expression => + NodeTypeIdentifier + end-rune = 170 + identifier-value = viewer + input-source = permission mixed single multiple test + start-rune = 165 + NodeTypePermission + end-rune = 222 + input-source = permission mixed single multiple test + relation-name = super + start-rune = 176 + compute-expression => + NodeTypeIdentifier + end-rune = 222 + identifier-value = viewer + input-source = permission mixed single multiple test + start-rune = 217 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 213 + input-source = permission mixed single multiple test + start-rune = 194 + annotation-types => + NodeTypeIdentifier + end-rune = 198 + identifier-value = admin + input-source = permission mixed single multiple test + start-rune = 200 + NodeTypeIdentifier + end-rune = 205 + identifier-value = user + input-source = permission mixed single multiple test + start-rune = 207 + NodeTypeIdentifier + end-rune = 213 + identifier-value = group + input-source = permission mixed single multiple test + start-rune = 215 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_multiple_types.zed b/pkg/schemadsl/parser/tests/permission_multiple_types.zed new file mode 100644 index 0000000000..0323d97699 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_multiple_types.zed @@ -0,0 +1,7 @@ +definition mydefinition { + relation viewer: user + + permission view: user | organization = viewer + permission edit: user | organization | group = viewer + permission admin: group = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_multiple_types.zed.expected b/pkg/schemadsl/parser/tests/permission_multiple_types.zed.expected new file mode 100644 index 0000000000..70b4305938 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_multiple_types.zed.expected @@ -0,0 +1,108 @@ +NodeTypeFile + end-rune = 202 + input-source = permission multiple types test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 202 + input-source = permission multiple types test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 50 + input-source = permission multiple types test + relation-name = viewer + start-rune = 30 + allowed-types => + NodeTypeTypeReference + end-rune = 50 + input-source = permission multiple types test + start-rune = 47 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 50 + input-source = permission multiple types test + start-rune = 47 + type-name = user + NodeTypePermission + end-rune = 105 + input-source = permission multiple types test + relation-name = view + start-rune = 61 + compute-expression => + NodeTypeIdentifier + end-rune = 105 + identifier-value = viewer + input-source = permission multiple types test + start-rune = 100 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 96 + input-source = permission multiple types test + start-rune = 78 + annotation-types => + NodeTypeIdentifier + end-rune = 81 + identifier-value = user + input-source = permission multiple types test + start-rune = 83 + NodeTypeIdentifier + end-rune = 96 + identifier-value = organization + input-source = permission multiple types test + start-rune = 98 + NodeTypePermission + end-rune = 163 + input-source = permission multiple types test + relation-name = edit + start-rune = 111 + compute-expression => + NodeTypeIdentifier + end-rune = 163 + identifier-value = viewer + input-source = permission multiple types test + start-rune = 158 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 154 + input-source = permission multiple types test + start-rune = 128 + annotation-types => + NodeTypeIdentifier + end-rune = 131 + identifier-value = user + input-source = permission multiple types test + start-rune = 133 + NodeTypeIdentifier + end-rune = 146 + identifier-value = organization + input-source = permission multiple types test + start-rune = 148 + NodeTypeIdentifier + end-rune = 154 + identifier-value = group + input-source = permission multiple types test + start-rune = 156 + NodeTypePermission + end-rune = 200 + input-source = permission multiple types test + relation-name = admin + start-rune = 169 + compute-expression => + NodeTypeIdentifier + end-rune = 200 + identifier-value = viewer + input-source = permission multiple types test + start-rune = 195 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 191 + input-source = permission multiple types test + start-rune = 187 + annotation-types => + NodeTypeIdentifier + end-rune = 191 + identifier-value = group + input-source = permission multiple types test + start-rune = 193 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation.zed b/pkg/schemadsl/parser/tests/permission_type_annotation.zed new file mode 100644 index 0000000000..1398d0f300 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation.zed @@ -0,0 +1,7 @@ +definition mydefinition { + relation viewer: user + + permission view: user = viewer + permission edit: user = viewer + permission admin: group = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation.zed.expected new file mode 100644 index 0000000000..b362474d6d --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation.zed.expected @@ -0,0 +1,93 @@ +NodeTypeFile + end-rune = 164 + input-source = permission type annotation test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 164 + input-source = permission type annotation test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 50 + input-source = permission type annotation test + relation-name = viewer + start-rune = 30 + allowed-types => + NodeTypeTypeReference + end-rune = 50 + input-source = permission type annotation test + start-rune = 47 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 50 + input-source = permission type annotation test + start-rune = 47 + type-name = user + NodeTypePermission + end-rune = 90 + input-source = permission type annotation test + relation-name = view + start-rune = 61 + compute-expression => + NodeTypeIdentifier + end-rune = 90 + identifier-value = viewer + input-source = permission type annotation test + start-rune = 85 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 81 + input-source = permission type annotation test + start-rune = 78 + annotation-types => + NodeTypeIdentifier + end-rune = 81 + identifier-value = user + input-source = permission type annotation test + start-rune = 83 + NodeTypePermission + end-rune = 125 + input-source = permission type annotation test + relation-name = edit + start-rune = 96 + compute-expression => + NodeTypeIdentifier + end-rune = 125 + identifier-value = viewer + input-source = permission type annotation test + start-rune = 120 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 116 + input-source = permission type annotation test + start-rune = 113 + annotation-types => + NodeTypeIdentifier + end-rune = 116 + identifier-value = user + input-source = permission type annotation test + start-rune = 118 + NodeTypePermission + end-rune = 162 + input-source = permission type annotation test + relation-name = admin + start-rune = 131 + compute-expression => + NodeTypeIdentifier + end-rune = 162 + identifier-value = viewer + input-source = permission type annotation test + start-rune = 157 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 153 + input-source = permission type annotation test + start-rune = 149 + annotation-types => + NodeTypeIdentifier + end-rune = 153 + identifier-value = group + input-source = permission type annotation test + start-rune = 155 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed new file mode 100644 index 0000000000..af1dd24946 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed @@ -0,0 +1,4 @@ +definition mydefinition { + relation viewer: user + permission view:: user = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed.expected new file mode 100644 index 0000000000..2e73d46750 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_double_colon.zed.expected @@ -0,0 +1,69 @@ +NodeTypeFile + end-rune = 65 + input-source = permission type annotation double colon test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 65 + input-source = permission type annotation double colon test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation double colon test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation double colon test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation double colon test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 65 + input-source = permission type annotation double colon test + relation-name = view + start-rune = 50 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected one of: [TokenTypeEquals], found: TokenTypeColon + error-source = : + input-source = permission type annotation double colon test + start-rune = 66 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 65 + input-source = permission type annotation double colon test + start-rune = 66 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected identifier, found token TokenTypeColon + error-source = : + input-source = permission type annotation double colon test + start-rune = 66 + NodeTypeError + end-rune = 65 + error-message = Expected type identifier in type annotation + error-source = : + input-source = permission type annotation double colon test + start-rune = 66 + NodeTypeError + end-rune = 65 + error-message = Expected end of statement or definition, found: TokenTypeColon + error-source = : + input-source = permission type annotation double colon test + start-rune = 66 + NodeTypeError + end-rune = 65 + error-message = Unexpected token at root level: TokenTypeColon + error-source = : + input-source = permission type annotation double colon test + start-rune = 66 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed new file mode 100644 index 0000000000..7407655aa5 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed @@ -0,0 +1,4 @@ +definition mydefinition { + relation viewer: user + permission view: = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed.expected new file mode 100644 index 0000000000..046f655854 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_empty_after_colon.zed.expected @@ -0,0 +1,56 @@ +NodeTypeFile + end-rune = 76 + input-source = permission type annotation empty after colon test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 76 + input-source = permission type annotation empty after colon test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation empty after colon test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation empty after colon test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation empty after colon test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 74 + input-source = permission type annotation empty after colon test + relation-name = view + start-rune = 50 + compute-expression => + NodeTypeIdentifier + end-rune = 74 + identifier-value = viewer + input-source = permission type annotation empty after colon test + start-rune = 69 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 65 + input-source = permission type annotation empty after colon test + start-rune = 67 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected identifier, found token TokenTypeEquals + error-source = = + input-source = permission type annotation empty after colon test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Expected type identifier in type annotation + error-source = = + input-source = permission type annotation empty after colon test + start-rune = 67 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed new file mode 100644 index 0000000000..5f5a194f3d --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed @@ -0,0 +1,4 @@ +definition mydefinition { + relation viewer: user + permission view: | = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed.expected new file mode 100644 index 0000000000..16229409b6 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_just_pipe.zed.expected @@ -0,0 +1,69 @@ +NodeTypeFile + end-rune = 65 + input-source = permission type annotation just pipe test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 65 + input-source = permission type annotation just pipe test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation just pipe test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation just pipe test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation just pipe test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 65 + input-source = permission type annotation just pipe test + relation-name = view + start-rune = 50 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected one of: [TokenTypeEquals], found: TokenTypePipe + error-source = | + input-source = permission type annotation just pipe test + start-rune = 67 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 65 + input-source = permission type annotation just pipe test + start-rune = 67 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected identifier, found token TokenTypePipe + error-source = | + input-source = permission type annotation just pipe test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Expected type identifier in type annotation + error-source = | + input-source = permission type annotation just pipe test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Expected end of statement or definition, found: TokenTypePipe + error-source = | + input-source = permission type annotation just pipe test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Unexpected token at root level: TokenTypePipe + error-source = | + input-source = permission type annotation just pipe test + start-rune = 67 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed new file mode 100644 index 0000000000..50f1829e9f --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed @@ -0,0 +1,5 @@ +definition mydefinition { + relation viewer: user + permission view: + = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed.expected new file mode 100644 index 0000000000..b2d94e3f62 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_newline_after_colon.zed.expected @@ -0,0 +1,56 @@ +NodeTypeFile + end-rune = 78 + input-source = permission type annotation newline after colon test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 78 + input-source = permission type annotation newline after colon test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation newline after colon test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation newline after colon test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation newline after colon test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 76 + input-source = permission type annotation newline after colon test + relation-name = view + start-rune = 50 + compute-expression => + NodeTypeIdentifier + end-rune = 76 + identifier-value = viewer + input-source = permission type annotation newline after colon test + start-rune = 71 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 65 + input-source = permission type annotation newline after colon test + start-rune = 69 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected identifier, found token TokenTypeEquals + error-source = = + input-source = permission type annotation newline after colon test + start-rune = 69 + NodeTypeError + end-rune = 65 + error-message = Expected type identifier in type annotation + error-source = = + input-source = permission type annotation newline after colon test + start-rune = 69 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed new file mode 100644 index 0000000000..db78445100 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed @@ -0,0 +1,4 @@ +definition mydefinition { + relation viewer: user + permission view: | user = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed.expected new file mode 100644 index 0000000000..303ad994de --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_pipe_no_type_before.zed.expected @@ -0,0 +1,69 @@ +NodeTypeFile + end-rune = 65 + input-source = permission type annotation pipe no type before test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 65 + input-source = permission type annotation pipe no type before test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation pipe no type before test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation pipe no type before test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation pipe no type before test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 65 + input-source = permission type annotation pipe no type before test + relation-name = view + start-rune = 50 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected one of: [TokenTypeEquals], found: TokenTypePipe + error-source = | + input-source = permission type annotation pipe no type before test + start-rune = 67 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 65 + input-source = permission type annotation pipe no type before test + start-rune = 67 + child-node => + NodeTypeError + end-rune = 65 + error-message = Expected identifier, found token TokenTypePipe + error-source = | + input-source = permission type annotation pipe no type before test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Expected type identifier in type annotation + error-source = | + input-source = permission type annotation pipe no type before test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Expected end of statement or definition, found: TokenTypePipe + error-source = | + input-source = permission type annotation pipe no type before test + start-rune = 67 + NodeTypeError + end-rune = 65 + error-message = Unexpected token at root level: TokenTypePipe + error-source = | + input-source = permission type annotation pipe no type before test + start-rune = 67 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed b/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed new file mode 100644 index 0000000000..5678326f6c --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed @@ -0,0 +1,4 @@ +definition mydefinition { + relation viewer: user + permission view: user | = viewer +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed.expected b/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed.expected new file mode 100644 index 0000000000..57e2b8db62 --- /dev/null +++ b/pkg/schemadsl/parser/tests/permission_type_annotation_trailing_pipe_no_type_after.zed.expected @@ -0,0 +1,62 @@ +NodeTypeFile + end-rune = 83 + input-source = permission type annotation trailing pipe no type after test + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = mydefinition + end-rune = 83 + input-source = permission type annotation trailing pipe no type after test + start-rune = 0 + child-node => + NodeTypeRelation + end-rune = 47 + input-source = permission type annotation trailing pipe no type after test + relation-name = viewer + start-rune = 27 + allowed-types => + NodeTypeTypeReference + end-rune = 47 + input-source = permission type annotation trailing pipe no type after test + start-rune = 44 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 47 + input-source = permission type annotation trailing pipe no type after test + start-rune = 44 + type-name = user + NodeTypePermission + end-rune = 81 + input-source = permission type annotation trailing pipe no type after test + relation-name = view + start-rune = 50 + compute-expression => + NodeTypeIdentifier + end-rune = 81 + identifier-value = viewer + input-source = permission type annotation trailing pipe no type after test + start-rune = 76 + type-annotations => + NodeTypeTypeAnnotation + end-rune = 72 + input-source = permission type annotation trailing pipe no type after test + start-rune = 67 + annotation-types => + NodeTypeIdentifier + end-rune = 70 + identifier-value = user + input-source = permission type annotation trailing pipe no type after test + start-rune = 72 + child-node => + NodeTypeError + end-rune = 72 + error-message = Expected identifier, found token TokenTypeEquals + error-source = = + input-source = permission type annotation trailing pipe no type after test + start-rune = 74 + NodeTypeError + end-rune = 72 + error-message = Expected type identifier after '|' in type annotation + error-source = = + input-source = permission type annotation trailing pipe no type after test + start-rune = 74 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/use_typechecking.zed b/pkg/schemadsl/parser/tests/use_typechecking.zed new file mode 100644 index 0000000000..88c07f9d34 --- /dev/null +++ b/pkg/schemadsl/parser/tests/use_typechecking.zed @@ -0,0 +1,2 @@ +use typechecking +definition resource {} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/use_typechecking.zed.expected b/pkg/schemadsl/parser/tests/use_typechecking.zed.expected new file mode 100644 index 0000000000..68152e866d --- /dev/null +++ b/pkg/schemadsl/parser/tests/use_typechecking.zed.expected @@ -0,0 +1,15 @@ +NodeTypeFile + end-rune = 38 + input-source = use typechecking test + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 15 + input-source = use typechecking test + start-rune = 0 + use-flag-name = typechecking + NodeTypeDefinition + definition-name = resource + end-rune = 38 + input-source = use typechecking test + start-rune = 17 \ No newline at end of file diff --git a/pkg/spiceerrors/assert_off.go b/pkg/spiceerrors/assert_off.go index 20ac7ef717..96e9b8d76c 100644 --- a/pkg/spiceerrors/assert_off.go +++ b/pkg/spiceerrors/assert_off.go @@ -16,6 +16,6 @@ func DebugAssertNotNil(obj any, format string, args ...any) { } // SetFinalizerForDebugging is a no-op in non-CI builds -func SetFinalizerForDebugging[T any](obj interface{}, finalizer func(obj T)) { +func SetFinalizerForDebugging[T any](obj any, finalizer func(obj T)) { // Do nothing on purpose } diff --git a/pkg/spiceerrors/assert_on.go b/pkg/spiceerrors/assert_on.go index a21414791e..8ba98749a0 100644 --- a/pkg/spiceerrors/assert_on.go +++ b/pkg/spiceerrors/assert_on.go @@ -26,6 +26,6 @@ func DebugAssertNotNil(obj any, format string, args ...any) { // SetFinalizerForDebugging sets a finalizer on the object for debugging purposes // in CI builds. -func SetFinalizerForDebugging[T any](obj interface{}, finalizer func(obj T)) { +func SetFinalizerForDebugging[T any](obj any, finalizer func(obj T)) { runtime.SetFinalizer(obj, finalizer) } diff --git a/pkg/testutil/require.go b/pkg/testutil/require.go index 98591f67a1..5649128226 100644 --- a/pkg/testutil/require.go +++ b/pkg/testutil/require.go @@ -15,7 +15,7 @@ import ( // RequireEqualEmptyNil is a version of require.Equal, but considers nil // slices/maps to be equal to empty slices/maps. -func RequireEqualEmptyNil(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) { +func RequireEqualEmptyNil(t *testing.T, expected, actual any, msgAndArgs ...any) { opts := []cmp.Option{ cmpopts.IgnoreUnexported( v0.RelationTuple{}, @@ -23,9 +23,6 @@ func RequireEqualEmptyNil(t *testing.T, expected, actual interface{}, msgAndArgs v0.RelationReference{}, v0.User_Userset{}, v0.User{}, - v0.EditCheckResult{}, - v0.EditCheckResultValidationError{}, - v0.DeveloperError{}, core.RelationTuple{}, core.ObjectAndRelation{}, core.RelationReference{}, diff --git a/pkg/tuple/parsing.go b/pkg/tuple/parsing.go index 0fd8c6e53e..d185aa23ab 100644 --- a/pkg/tuple/parsing.go +++ b/pkg/tuple/parsing.go @@ -1,6 +1,7 @@ package tuple import ( + "cmp" "encoding/json" "fmt" "maps" @@ -8,7 +9,6 @@ import ( "slices" "time" - "github.com/jzelinskie/stringz" "google.golang.org/protobuf/types/known/structpb" core "github.com/authzed/spicedb/pkg/proto/core/v1" @@ -112,7 +112,7 @@ func Parse(relString string) (Relationship, error) { subjectRelation := Ellipsis if len(groups[subjectRelIndex]) > 0 { - subjectRelation = stringz.DefaultEmpty(groups[subjectRelIndex], Ellipsis) + subjectRelation = cmp.Or(groups[subjectRelIndex], Ellipsis) } caveatName := groups[caveatNameIndex] diff --git a/proto/internal/impl/v1/impl.proto b/proto/internal/impl/v1/impl.proto index 836d833910..31f2fa4428 100644 --- a/proto/internal/impl/v1/impl.proto +++ b/proto/internal/impl/v1/impl.proto @@ -69,6 +69,10 @@ message DocComment { string comment = 1; } +message TypeAnnotations { + repeated string types = 1; +} + message RelationMetadata { enum RelationKind { UNKNOWN_KIND = 0; @@ -77,6 +81,7 @@ message RelationMetadata { } RelationKind kind = 1; + TypeAnnotations type_annotations = 2; } message NamespaceAndRevision { diff --git a/tools.go b/tools.go deleted file mode 100644 index 2db332725a..0000000000 --- a/tools.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build tools -// +build tools - -package tools - -// Most tools are managed in the magefiles module. These tools are just -// the ones that can't run from a submodule at the moment. -import ( - // support running mage with go run mage.go - _ "github.com/magefile/mage/mage" - // optgen is used directly in go:generate directives. - _ "github.com/ecordell/optgen" - // golangci-lint always uses the current directory's go.mod. - _ "github.com/golangci/golangci-lint/v2/cmd/golangci-lint" - // vulncheck always uses the current directory's go.mod. - _ "golang.org/x/vuln/cmd/govulncheck" -) diff --git a/tools/analyzers/go.work.sum b/tools/analyzers/go.work.sum index 08a2b5fed2..dd2c06976c 100644 --- a/tools/analyzers/go.work.sum +++ b/tools/analyzers/go.work.sum @@ -2,6 +2,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-2023080216373 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-20230802163732-1c33ebd9ecfa.1/go.mod h1:xafc+XIsTxTy76GJQ1TKgvJWsSugFBqMaN27WhUblew= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1 h1:4erM3WLgEG/HIBrpBDmRbs1puhd7p0z7kNXDuhHthwM= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20250130201111-63bb56e20495.1/go.mod h1:novQBstnxcGpfKf8qGRATqn1anQKwMJIbH5Q581jibU= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250425153114-8976f5be98c1.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= +buf.build/go/protovalidate v0.12.0/go.mod h1:q3PFfbzI05LeqxSwq+begW2syjy2Z6hLxZSkP1OH/D0= cloud.google.com/go/accessapproval v1.7.1 h1:/5YjNhR6lzCvmJZAnByYkfEgWjfAKwYP6nkuTk6nKFE= cloud.google.com/go/accessapproval v1.7.2 h1:W55SFrY6EVlcmmRGUk0rGhuy3j4fn7UtEocib/zADVE= cloud.google.com/go/accessapproval v1.7.4 h1:ZvLvJ952zK8pFHINjpMBY5k7LTAp/6pBf50RDMRgBUI= @@ -20,6 +22,7 @@ cloud.google.com/go/accessapproval v1.8.2 h1:h4u1MypgeYXTGvnNc1luCBLDN4Kb9Re/gw0 cloud.google.com/go/accessapproval v1.8.2/go.mod h1:aEJvHZtpjqstffVwF/2mCXXSQmpskyzvw6zKLvLutZM= cloud.google.com/go/accessapproval v1.8.3 h1:axlU03FRiXDNupsmPG7LKzuS4Enk1gf598M62lWVB74= cloud.google.com/go/accessapproval v1.8.3/go.mod h1:3speETyAv63TDrDmo5lIkpVueFkQcQchkiw/TAMbBo4= +cloud.google.com/go/accessapproval v1.8.6/go.mod h1:FfmTs7Emex5UvfnnpMkhuNkRCP85URnBFt5ClLxhZaQ= cloud.google.com/go/accesscontextmanager v1.8.1 h1:WIAt9lW9AXtqw/bnvrEUaE8VG/7bAAeMzRCBGMkc4+w= cloud.google.com/go/accesscontextmanager v1.8.2 h1:jcOXen2u13aHgOHibUjxyPI+fZzVhElxy2gzJJlOOHg= cloud.google.com/go/accesscontextmanager v1.8.4 h1:Yo4g2XrBETBCqyWIibN3NHNPQKUfQqti0lI+70rubeE= @@ -38,6 +41,7 @@ cloud.google.com/go/accesscontextmanager v1.9.2 h1:P0uVixQft8aacbZ7VDZStNZdrftF2 cloud.google.com/go/accesscontextmanager v1.9.2/go.mod h1:T0Sw/PQPyzctnkw1pdmGAKb7XBA84BqQzH0fSU7wzJU= cloud.google.com/go/accesscontextmanager v1.9.3 h1:8zVoeiBa4erMCLEXltOcqVEsZhS26JZ5/Vrgs59eQiI= cloud.google.com/go/accesscontextmanager v1.9.3/go.mod h1:S1MEQV5YjkAKBoMekpGrkXKfrBdsi4x6Dybfq6gZ8BU= +cloud.google.com/go/accesscontextmanager v1.9.6/go.mod h1:884XHwy1AQpCX5Cj2VqYse77gfLaq9f8emE2bYriilk= cloud.google.com/go/ai v0.8.0 h1:rXUEz8Wp2OlrM8r1bfmpF2+VKqc1VJpafE3HgzRnD/w= cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE= cloud.google.com/go/aiplatform v1.45.0 h1:FLTOQdXDqigyOPYrGGE5AiTpDyRROIZrPU1eXfKzKTY= @@ -55,6 +59,7 @@ cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhR cloud.google.com/go/aiplatform v1.70.0 h1:vnqsPkgcwlDEpWl9t6C3/HLfHeweuGXs2gcYTzH6dMs= cloud.google.com/go/aiplatform v1.70.0/go.mod h1:1cewyC4h+yvRs0qVvlCuU3V6j1pJ41doIcroYX3uv8o= cloud.google.com/go/aiplatform v1.74.0/go.mod h1:hVEw30CetNut5FrblYd1AJUWRVSIjoyIvp0EVUh51HA= +cloud.google.com/go/aiplatform v1.85.0/go.mod h1:S4DIKz3TFLSt7ooF2aCRdAqsUR4v/YDXUoHqn5P0EFc= cloud.google.com/go/analytics v0.21.2 h1:T400N/hkELka6OsgK20JYoit0xvKnZtWoe36ft4wGBs= cloud.google.com/go/analytics v0.21.3 h1:TFBC1ZAqX9/jL56GEXdLrVe5vT3I22bDVWyDwZX4IEg= cloud.google.com/go/analytics v0.21.4 h1:SScWR8i/M8h7h3lFKtOYcj0r4272aL+KvRRrsu39Vec= @@ -76,6 +81,7 @@ cloud.google.com/go/analytics v0.25.2/go.mod h1:th0DIunqrhI1ZWVlT3PH2Uw/9ANX8YHf cloud.google.com/go/analytics v0.25.3 h1:hX6JAsNbXd2uVjqjIuMcKpmhIybKrEunBiGxK4SwEFI= cloud.google.com/go/analytics v0.25.3/go.mod h1:pWoYg4yEr0iYg83LZRAicjDDdv54+Z//RyhzWwKbavI= cloud.google.com/go/analytics v0.26.0/go.mod h1:KZWJfs8uX/+lTjdIjvT58SFa86V9KM6aPXwZKK6uNVI= +cloud.google.com/go/analytics v0.28.0/go.mod h1:hNT09bdzGB3HsL7DBhZkoPi4t5yzZPZROoFv+JzGR7I= cloud.google.com/go/apigateway v1.6.1 h1:aBSwCQPcp9rZ0zVEUeJbR623palnqtvxJlUyvzsKGQc= cloud.google.com/go/apigateway v1.6.2 h1:I46jVrhr2M1JJ1lK7JGn2BvybN44muEh+LSjBQ1l9hw= cloud.google.com/go/apigateway v1.6.4 h1:VVIxCtVerchHienSlaGzV6XJGtEM9828Erzyr3miUGs= @@ -94,6 +100,7 @@ cloud.google.com/go/apigateway v1.7.2 h1:TRB5q0vvbT5Yx4bNSCWlqLJFJnhc7tDlCR9ccpo cloud.google.com/go/apigateway v1.7.2/go.mod h1:+weId+9aR9J6GRwDka7jIUSrKEX60XGcikX7dGU8O7M= cloud.google.com/go/apigateway v1.7.3 h1:Mn7cC5iWJz+cSMS/Hb+N2410CpZ6c8XpJKaexBl0Gxs= cloud.google.com/go/apigateway v1.7.3/go.mod h1:uK0iRHdl2rdTe79bHW/bTsKhhXPcFihjUdb7RzhTPf4= +cloud.google.com/go/apigateway v1.7.6/go.mod h1:SiBx36VPjShaOCk8Emf63M2t2c1yF+I7mYZaId7OHiA= cloud.google.com/go/apigeeconnect v1.6.1 h1:6u/jj0P2c3Mcm+H9qLsXI7gYcTiG9ueyQL3n6vCmFJM= cloud.google.com/go/apigeeconnect v1.6.2 h1:7LzOTW34EH2julg0MQVt+U9ZdmiCKcg6fef/ugKL2Xo= cloud.google.com/go/apigeeconnect v1.6.4 h1:jSoGITWKgAj/ssVogNE9SdsTqcXnryPzsulENSRlusI= @@ -112,6 +119,7 @@ cloud.google.com/go/apigeeconnect v1.7.2 h1:GHg0ddEQUZ08C1qC780P5wwY/jaIW8UtxuRQ cloud.google.com/go/apigeeconnect v1.7.2/go.mod h1:he/SWi3A63fbyxrxD6jb67ak17QTbWjva1TFbT5w8Kw= cloud.google.com/go/apigeeconnect v1.7.3 h1:Wlr+30Tha0SMCvQYZKdrh+HkpOyl0CQFSlzeY/Gg1gs= cloud.google.com/go/apigeeconnect v1.7.3/go.mod h1:2ZkT5VCAqhYrDqf4dz7lGp4N/+LeNBSfou8Qs5bIuSg= +cloud.google.com/go/apigeeconnect v1.7.6/go.mod h1:zqDhHY99YSn2li6OeEjFpAlhXYnXKl6DFb/fGu0ye2w= cloud.google.com/go/apigeeregistry v0.7.1 h1:hgq0ANLDx7t2FDZDJQrCMtCtddR/pjCqVuvQWGrQbXw= cloud.google.com/go/apigeeregistry v0.7.2 h1:MESEjKSfz4TvLAzT2KPimDDvhOyQlcq7aFFREG2PRt4= cloud.google.com/go/apigeeregistry v0.8.2 h1:DSaD1iiqvELag+lV4VnnqUUFd8GXELu01tKVdWZrviE= @@ -130,6 +138,7 @@ cloud.google.com/go/apigeeregistry v0.9.2 h1:fC3ZXEk2QsBxUlZZDZpbBGXC/ZQglCBmHDG cloud.google.com/go/apigeeregistry v0.9.2/go.mod h1:A5n/DwpG5NaP2fcLYGiFA9QfzpQhPRFNATO1gie8KM8= cloud.google.com/go/apigeeregistry v0.9.3 h1:j9CJg/oC884OX5cDpiwNt1ZlDXNV6Zb9Mp1YmRrOG0k= cloud.google.com/go/apigeeregistry v0.9.3/go.mod h1:oNCP2VjOeI6U8yuOuTmU4pkffdcXzR5KxeUD71gF+Dg= +cloud.google.com/go/apigeeregistry v0.9.6/go.mod h1:AFEepJBKPtGDfgabG2HWaLH453VVWWFFs3P4W00jbPs= cloud.google.com/go/apikeys v0.6.0 h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ= cloud.google.com/go/appengine v1.8.1 h1:J+aaUZ6IbTpBegXbmEsh8qZZy864ZVnOoWyfa1XSNbI= cloud.google.com/go/appengine v1.8.2 h1:0/OFV0FQKgi0AB4E8NuYN0JY3hJzND4ftRpK7P26uaw= @@ -149,6 +158,7 @@ cloud.google.com/go/appengine v1.9.2 h1:pxAQ//FsyEQsaF9HJduPCOEvj9GV4fvnLARGz1+K cloud.google.com/go/appengine v1.9.2/go.mod h1:bK4dvmMG6b5Tem2JFZcjvHdxco9g6t1pwd3y/1qr+3s= cloud.google.com/go/appengine v1.9.3 h1:jrcanSzj9J1erevZuxldvsDwY+0k/DeFFzlnSfPGfL8= cloud.google.com/go/appengine v1.9.3/go.mod h1:DtLsE/z3JufM/pCEIyVYebJ0h9UNPpN64GZQrYgOSyM= +cloud.google.com/go/appengine v1.9.6/go.mod h1:jPp9T7Opvzl97qytaRGPwoH7pFI3GAcLDaui1K8PNjY= cloud.google.com/go/area120 v0.8.1 h1:wiOq3KDpdqXmaHzvZwKdpoM+3lDcqsI2Lwhyac7stss= cloud.google.com/go/area120 v0.8.2 h1:h/wMtPPsgFJfMce1b9M24Od8RuKt8CWENwr+X24tBhE= cloud.google.com/go/area120 v0.8.4 h1:YnSO8m02pOIo6AEOgiOoUDVbw4pf+bg2KLHi4rky320= @@ -167,6 +177,7 @@ cloud.google.com/go/area120 v0.9.2 h1:LODm6TjW27/LJ4z4fBNJHRb+tlvy0gSu6Vb8j2lflu cloud.google.com/go/area120 v0.9.2/go.mod h1:Ar/KPx51UbrTWGVGgGzFnT7hFYQuk/0VOXkvHdTbQMI= cloud.google.com/go/area120 v0.9.3 h1:dPQ07rW4eku8OgNWDOaQaVGcE4+XfhH8BSbVwdVQ+wU= cloud.google.com/go/area120 v0.9.3/go.mod h1:F3vxS/+hqzrjJo55Xvda3Jznjjbd+4Foo43SN5eMd8M= +cloud.google.com/go/area120 v0.9.6/go.mod h1:qKSokqe0iTmwBDA3tbLWonMEnh0pMAH4YxiceiHUed4= cloud.google.com/go/artifactregistry v1.14.1 h1:k6hNqab2CubhWlGcSzunJ7kfxC7UzpAfQ1UPb9PDCKI= cloud.google.com/go/artifactregistry v1.14.2 h1:xJIxeBs9ZYH2j8Wg/K/aCkroNUnDXgIhSHgz5FUE/Q4= cloud.google.com/go/artifactregistry v1.14.3 h1:Ssv6f+jgfhDdhu43AaHUaSosIYpQ+TPCJNwqYSJT1AE= @@ -186,6 +197,7 @@ cloud.google.com/go/artifactregistry v1.16.0 h1:BZpz0x8HCG7hwTkD+GlUwPQVFGOo9w84 cloud.google.com/go/artifactregistry v1.16.0/go.mod h1:LunXo4u2rFtvJjrGjO0JS+Gs9Eco2xbZU6JVJ4+T8Sk= cloud.google.com/go/artifactregistry v1.16.1 h1:ZNXGB6+T7VmWdf6//VqxLdZ/sk0no8W0ujanHeJwDRw= cloud.google.com/go/artifactregistry v1.16.1/go.mod h1:sPvFPZhfMavpiongKwfg93EOwJ18Tnj9DIwTU9xWUgs= +cloud.google.com/go/artifactregistry v1.17.1/go.mod h1:06gLv5QwQPWtaudI2fWO37gfwwRUHwxm3gA8Fe568Hc= cloud.google.com/go/asset v1.14.1 h1:vlHdznX70eYW4V1y1PxocvF6tEwxJTTarwIGwOhFF3U= cloud.google.com/go/asset v1.15.0 h1:4SdWreholqB0ZOHjBO+K+RSsW9TcZBbfpfXtFir23R0= cloud.google.com/go/asset v1.15.1 h1:+9f5/s/U0AGZSPLTOMcXSZ5NDB5jQ2Szr+WQPgPA8bk= @@ -207,6 +219,7 @@ cloud.google.com/go/asset v1.20.3 h1:/jQBAkZVUbsIczRepDkwaf/K5NcRYvQ6MBiWg5i20fU cloud.google.com/go/asset v1.20.3/go.mod h1:797WxTDwdnFAJzbjZ5zc+P5iwqXc13yO9DHhmS6wl+o= cloud.google.com/go/asset v1.20.4 h1:6oNgjcs5KCPGBD71G0IccK6TfeFsEtBTyQ3Q+Dn09bs= cloud.google.com/go/asset v1.20.4/go.mod h1:DP09pZ+SoFWUZyPZx26xVroHk+6+9umnQv+01yfJxbM= +cloud.google.com/go/asset v1.21.0/go.mod h1:0lMJ0STdyImZDSCB8B3i/+lzIquLBpJ9KZ4pyRvzccM= cloud.google.com/go/assuredworkloads v1.11.1 h1:yaO0kwS+SnhVSTF7BqTyVGt3DTocI6Jqo+S3hHmCwNk= cloud.google.com/go/assuredworkloads v1.11.2 h1:EbPyk3fC8sTxSIPoFrCR9P1wRTVdXcRxvPqFK8/wdso= cloud.google.com/go/assuredworkloads v1.11.4 h1:FsLSkmYYeNuzDm8L4YPfLWV+lQaUrJmH5OuD37t1k20= @@ -225,6 +238,7 @@ cloud.google.com/go/assuredworkloads v1.12.2 h1:6Y6a4V7CD50qtjvayhu7f5o35UFJP8ad cloud.google.com/go/assuredworkloads v1.12.2/go.mod h1:/WeRr/q+6EQYgnoYrqCVgw7boMoDfjXZZev3iJxs2Iw= cloud.google.com/go/assuredworkloads v1.12.3 h1:RU1WhF1zMggdXAZ+ezYTn4Eh/FdiX7sz8lLXGERn4Po= cloud.google.com/go/assuredworkloads v1.12.3/go.mod h1:iGBkyMGdtlsxhCi4Ys5SeuvIrPTeI6HeuEJt7qJgJT8= +cloud.google.com/go/assuredworkloads v1.12.6/go.mod h1:QyZHd7nH08fmZ+G4ElihV1zoZ7H0FQCpgS0YWtwjCKo= cloud.google.com/go/automl v1.13.1 h1:iP9iQurb0qbz+YOOMfKSEjhONA/WcoOIjt6/m+6pIgo= cloud.google.com/go/automl v1.13.2 h1:kUN4Y6N61AsNdXsdZIug1c+2pTJ5tg9xUA6+yn0Wf8Y= cloud.google.com/go/automl v1.13.4 h1:i9tOKXX+1gE7+rHpWKjiuPfGBVIYoWvLNIGpWgPtF58= @@ -243,6 +257,7 @@ cloud.google.com/go/automl v1.14.2 h1:RzR5Nx78iaF2FNAfaaQ/7o2b4VuQ17YbOaeK/DLYSW cloud.google.com/go/automl v1.14.2/go.mod h1:mIat+Mf77W30eWQ/vrhjXsXaRh8Qfu4WiymR0hR6Uxk= cloud.google.com/go/automl v1.14.4 h1:vkD+hQ75SMINMgJBT/KDpFYvfQLzJbtIQZdw0AWq8Rs= cloud.google.com/go/automl v1.14.4/go.mod h1:sVfsJ+g46y7QiQXpVs9nZ/h8ntdujHm5xhjHW32b3n4= +cloud.google.com/go/automl v1.14.7/go.mod h1:8a4XbIH5pdvrReOU72oB+H3pOw2JBxo9XTk39oljObE= cloud.google.com/go/baremetalsolution v1.1.1 h1:0Ge9PQAy6cZ1tRrkc44UVgYV15nw2TVnzJzYsMHXF+E= cloud.google.com/go/baremetalsolution v1.2.0 h1:3zztyuQHjfU0C0qEsI9LkC3kf5/TQQ3jUJhbmetUoRA= cloud.google.com/go/baremetalsolution v1.2.1 h1:uRpZsKiWFDyT1sARZVRKqnOmf2mpRfVas7KMC3/MA4I= @@ -262,6 +277,7 @@ cloud.google.com/go/baremetalsolution v1.3.2 h1:rhawlI+9gy/i1ZQbN/qL6FXHGXusWbfr cloud.google.com/go/baremetalsolution v1.3.2/go.mod h1:3+wqVRstRREJV/puwaKAH3Pnn7ByreZG2aFRsavnoBQ= cloud.google.com/go/baremetalsolution v1.3.3 h1:OL+KT+wCumdDhG44aeqGAdkwdT8Wa4Lh+o4INM+CQjw= cloud.google.com/go/baremetalsolution v1.3.3/go.mod h1:uF9g08RfmXTF6ZKbXxixy5cGMGFcG6137Z99XjxLOUI= +cloud.google.com/go/baremetalsolution v1.3.6/go.mod h1:7/CS0LzpLccRGO0HL3q2Rofxas2JwjREKut414sE9iM= cloud.google.com/go/batch v1.3.1 h1:uE0Q//W7FOGPjf7nuPiP0zoE8wOT3ngoIO2HIet0ilY= cloud.google.com/go/batch v1.4.1 h1:/4ADpZKoKH300HN2SB6aI7lXX/0hnnbR74wxjLHkyQo= cloud.google.com/go/batch v1.5.0 h1:xjhQeEcBXJDxW2cBZEQgCKlGeXRlVJildU67rtoBY6A= @@ -284,6 +300,7 @@ cloud.google.com/go/batch v1.11.2/go.mod h1:ehsVs8Y86Q4K+qhEStxICqQnNqH8cqgpCxx8 cloud.google.com/go/batch v1.11.5 h1:TLfFZJXu+89CGbDK2mMql8f6HHFXarr8uUsaQ6wKatU= cloud.google.com/go/batch v1.11.5/go.mod h1:HUxnmZqnkG7zIZuF3NYCfUIrOMU3+SPArR5XA6NGu5s= cloud.google.com/go/batch v1.12.0/go.mod h1:CATSBh/JglNv+tEU/x21Z47zNatLQ/gpGnpyKOzbbcM= +cloud.google.com/go/batch v1.12.2/go.mod h1:tbnuTN/Iw59/n1yjAYKV2aZUjvMM2VJqAgvUgft6UEU= cloud.google.com/go/beyondcorp v1.0.0 h1:VPg+fZXULQjs8LiMeWdLaB5oe8G9sEoZ0I0j6IMiG1Q= cloud.google.com/go/beyondcorp v1.0.1 h1:uQpsXwttlV0+AXHdB5qaZl1mz2SsyYV1PKgTR74noaQ= cloud.google.com/go/beyondcorp v1.0.3 h1:VXf9SnrnSmj2BF2cHkoTHvOUp8gjsz1KJFOMW7czdsY= @@ -302,6 +319,7 @@ cloud.google.com/go/beyondcorp v1.1.2 h1:hzKZf9ScvqTWqR8xGKVvD35ScQuxbMySELvJ0OW cloud.google.com/go/beyondcorp v1.1.2/go.mod h1:q6YWSkEsSZTU2WDt1qtz6P5yfv79wgktGtNbd0FJTLI= cloud.google.com/go/beyondcorp v1.1.3 h1:ezavJc0Gzh4N8zBskO/DnUVMWPa8lqH/tmQSyaknmCA= cloud.google.com/go/beyondcorp v1.1.3/go.mod h1:3SlVKnlczNTSQFuH5SSyLuRd4KaBSc8FH/911TuF/Cc= +cloud.google.com/go/beyondcorp v1.1.6/go.mod h1:V1PigSWPGh5L/vRRmyutfnjAbkxLI2aWqJDdxKbwvsQ= cloud.google.com/go/bigquery v1.52.0 h1:JKLNdxI0N+TIUWD6t9KN646X27N5dQWq9dZbbTWZ8hc= cloud.google.com/go/bigquery v1.53.0 h1:K3wLbjbnSlxhuG5q4pntHv5AEbQM1QqHKGYgwFIqOTg= cloud.google.com/go/bigquery v1.55.0 h1:hs44Xxov3XLWQiCx2J8lK5U/ihLqnpm4RVVl5fdtLLI= @@ -322,6 +340,7 @@ cloud.google.com/go/bigquery v1.64.0/go.mod h1:gy8Ooz6HF7QmA+TRtX8tZmXBKH5mCFBwU cloud.google.com/go/bigquery v1.66.0 h1:cDM3xEUUTf6RDepFEvNZokCysGFYoivHHTIZOWXbV2E= cloud.google.com/go/bigquery v1.66.0/go.mod h1:Cm1hMRzZ8teV4Nn8KikgP8bT9jd54ivP8fvXWZREmG4= cloud.google.com/go/bigquery v1.66.2/go.mod h1:+Yd6dRyW8D/FYEjUGodIbu0QaoEmgav7Lwhotup6njo= +cloud.google.com/go/bigquery v1.67.0/go.mod h1:HQeP1AHFuAz0Y55heDSb0cjZIhnEkuwFRBGo6EEKHug= cloud.google.com/go/bigtable v1.31.0 h1:/uVLxGVRbK4mxK/iO89VqXcL/zoTSmkltVfIDYVBluQ= cloud.google.com/go/bigtable v1.31.0/go.mod h1:N/mwZO+4TSHOeyiE1JxO+sRPnW4bnR7WLn9AEaiJqew= cloud.google.com/go/bigtable v1.33.0 h1:2BDaWLRAwXO14DJL/u8crbV2oUbMZkIa2eGq8Yao1bk= @@ -329,6 +348,7 @@ cloud.google.com/go/bigtable v1.33.0/go.mod h1:HtpnH4g25VT1pejHRtInlFPnN5sjTxbQl cloud.google.com/go/bigtable v1.34.0 h1:eIgi3QLcN4aq8p6n9U/zPgmHeBP34sm9FiKq4ik/ZoY= cloud.google.com/go/bigtable v1.34.0/go.mod h1:p94uLf6cy6D73POkudMagaFF3x9c7ktZjRnOUVGjZAw= cloud.google.com/go/bigtable v1.35.0/go.mod h1:EabtwwmTcOJFXp+oMZAT/jZkyDIjNwrv53TrS4DGrrM= +cloud.google.com/go/bigtable v1.37.0/go.mod h1:HXqddP6hduwzrtiTCqZPpj9ij4hGZb4Zy1WF/dT+yaU= cloud.google.com/go/billing v1.16.0 h1:1iktEAIZ2uA6KpebC235zi/rCXDdDYQ0bTXTNetSL80= cloud.google.com/go/billing v1.17.0 h1:CpagWXb/+QNye+vouomndbc4Gsr0uo+AGR24V16uk8Q= cloud.google.com/go/billing v1.17.1 h1:YSu8a17uJ6sOnlrnJVOBWkimmHZGtSpSkyElv9+JjRM= @@ -350,6 +370,7 @@ cloud.google.com/go/billing v1.19.2 h1:shcyz1UkrUxbPsqHL6L84ZdtBZ7yocaFFCxMInTsr cloud.google.com/go/billing v1.19.2/go.mod h1:AAtih/X2nka5mug6jTAq8jfh1nPye0OjkHbZEZgU59c= cloud.google.com/go/billing v1.20.1 h1:xMlO3hc5BI0s23tRB40bL40xSpxUR1x3E07Y5/VWcjU= cloud.google.com/go/billing v1.20.1/go.mod h1:DhT80hUZ9gz5UqaxtK/LNoDELfxH73704VTce+JZqrY= +cloud.google.com/go/billing v1.20.4/go.mod h1:hBm7iUmGKGCnBm6Wp439YgEdt+OnefEq/Ib9SlJYxIU= cloud.google.com/go/binaryauthorization v1.6.1 h1:cAkOhf1ic92zEN4U1zRoSupTmwmxHfklcp1X7CCBKvE= cloud.google.com/go/binaryauthorization v1.7.0 h1:7L6uUWo/xNCfdVNnnzh2M4x5YA732YPgqRdCG8aKVAU= cloud.google.com/go/binaryauthorization v1.7.1 h1:i2S+/G36VA1UG8gdcQLpq5I58/w/RzAnjQ65scKozFg= @@ -370,6 +391,7 @@ cloud.google.com/go/binaryauthorization v1.9.2 h1:zZX4cvtYSXc5ogOar1w5KA1BLz3j46 cloud.google.com/go/binaryauthorization v1.9.2/go.mod h1:T4nOcRWi2WX4bjfSRXJkUnpliVIqjP38V88Z10OvEv4= cloud.google.com/go/binaryauthorization v1.9.3 h1:X8JRfmk0/vyRqLusEyAPr0nZCK6RKae9omB4lrit0XI= cloud.google.com/go/binaryauthorization v1.9.3/go.mod h1:f3xcb/7vWklDoF+q2EaAIS+/A/e1278IgiYxonRX+Jk= +cloud.google.com/go/binaryauthorization v1.9.5/go.mod h1:CV5GkS2eiY461Bzv+OH3r5/AsuB6zny+MruRju3ccB8= cloud.google.com/go/certificatemanager v1.7.1 h1:uKsohpE0hiobx1Eak9jNcPCznwfB6gvyQCcS28Ah9E8= cloud.google.com/go/certificatemanager v1.7.2 h1:Xytp8O0/EDh2nVscHhFQpicY9YAT3f3R7D7pv/z29uE= cloud.google.com/go/certificatemanager v1.7.4 h1:5YMQ3Q+dqGpwUZ9X5sipsOQ1fLPsxod9HNq0+nrqc6I= @@ -388,6 +410,7 @@ cloud.google.com/go/certificatemanager v1.9.2 h1:/lO1ejN415kRaiO6DNNCHj0UvQujKP7 cloud.google.com/go/certificatemanager v1.9.2/go.mod h1:PqW+fNSav5Xz8bvUnJpATIRo1aaABP4mUg/7XIeAn6c= cloud.google.com/go/certificatemanager v1.9.3 h1:2UP31fg7b+y3F0OmNbPHOKPEJ+6LOMfxAXX4p8xGCy4= cloud.google.com/go/certificatemanager v1.9.3/go.mod h1:O5T4Lg/dHbDHLFFooV2Mh/VsT3Mj2CzPEWRo4qw5prc= +cloud.google.com/go/certificatemanager v1.9.5/go.mod h1:kn7gxT/80oVGhjL8rurMUYD36AOimgtzSBPadtAeffs= cloud.google.com/go/channel v1.16.0 h1:dqRkK2k7Ll/HHeYGxv18RrfhozNxuTJRkspW0iaFZoY= cloud.google.com/go/channel v1.17.0 h1:Hy2EaOiOB7BS1IJmg2lLilEo8uMfFWTy7RgjTzbUqjM= cloud.google.com/go/channel v1.17.1 h1:+1B+Gj/3SJSLGJZXCp3dWiseMVHoSZ7Xo6Klg1fqM64= @@ -408,6 +431,7 @@ cloud.google.com/go/channel v1.19.1 h1:l4XcnfzJ5UGmqZQls0atcpD6ERDps4PLd5hXSyTWF cloud.google.com/go/channel v1.19.1/go.mod h1:ungpP46l6XUeuefbA/XWpWWnAY3897CSRPXUbDstwUo= cloud.google.com/go/channel v1.19.2 h1:oHyO3QAZ6kdf6SwqnUTBz50ND6Nk2rxZtboUiF4dgLE= cloud.google.com/go/channel v1.19.2/go.mod h1:syX5opXGXFt17DHCyCdbdlM464Tx0gHMi46UlEWY9Gg= +cloud.google.com/go/channel v1.19.5/go.mod h1:vevu+LK8Oy1Yuf7lcpDbkQQQm5I7oiY5fFTn3uwfQLY= cloud.google.com/go/cloudbuild v1.10.1 h1:N6Tl7Xhi0+GWGdt0i2WwaLZKgKeGP4m9A/cERzZcU5k= cloud.google.com/go/cloudbuild v1.13.0 h1:YBbAWcvE4x6xPWTyS+OU4eiUpz5rCS3VCM/aqmfddPA= cloud.google.com/go/cloudbuild v1.14.0 h1:YTMxmFra7eIjKFgnyQUxOwWNseNqeO38kGh7thy7v4s= @@ -430,6 +454,7 @@ cloud.google.com/go/cloudbuild v1.19.0/go.mod h1:ZGRqbNMrVGhknIIjwASa6MqoRTOpXIV cloud.google.com/go/cloudbuild v1.20.0 h1:0BRKyrCnWMHlnkwtNKdEwcvpgPm3OA3NqQhzDS5c7ek= cloud.google.com/go/cloudbuild v1.20.0/go.mod h1:TgSGCsKojPj2JZuYNw5Ur6Pw7oCJ9iK60PuMnaUps7s= cloud.google.com/go/cloudbuild v1.22.0/go.mod h1:p99MbQrzcENHb/MqU3R6rpqFRk/X+lNG3PdZEIhM95Y= +cloud.google.com/go/cloudbuild v1.22.2/go.mod h1:rPyXfINSgMqMZvuTk1DbZcbKYtvbYF/i9IXQ7eeEMIM= cloud.google.com/go/clouddms v1.6.1 h1:rjR1nV6oVf2aNNB7B5uz1PDIlBjlOiBgR+q5n7bbB7M= cloud.google.com/go/clouddms v1.7.0 h1:vTcaFaFZTZZ11gXB6aZHdAx+zn30P8YJw4X/S3NC+VQ= cloud.google.com/go/clouddms v1.7.1 h1:LrtqeR2xKV3juG5N7eeUgW+PqdMClOWH2U9PN3EpfFw= @@ -450,6 +475,7 @@ cloud.google.com/go/clouddms v1.8.2/go.mod h1:pe+JSp12u4mYOkwXpSMouyCCuQHL3a6xvW cloud.google.com/go/clouddms v1.8.3 h1:T/rkkKE0KhQFMcO3+QWL82xakA9kRumLXY1lq5adIts= cloud.google.com/go/clouddms v1.8.3/go.mod h1:wn8O2KhhJWcOlQk0pMC7F/4TaJRS5sN6KdNWM8A7o6c= cloud.google.com/go/clouddms v1.8.4/go.mod h1:RadeJ3KozRwy4K/gAs7W74ZU3GmGgVq5K8sRqNs3HfA= +cloud.google.com/go/clouddms v1.8.7/go.mod h1:DhWLd3nzHP8GoHkA6hOhso0R9Iou+IGggNqlVaq/KZ4= cloud.google.com/go/cloudtasks v1.11.1 h1:zyF35LjQyVQQnWbglmVDbsgOHqkbkaxTeRDisEJsXtE= cloud.google.com/go/cloudtasks v1.12.1 h1:cMh9Q6dkvh+Ry5LAPbD/U2aw6KAqdiU6FttwhbTo69w= cloud.google.com/go/cloudtasks v1.12.2 h1:IoJI49JClvv2+NYvcABRgTO9y4veAUFlaOTigm+xXqE= @@ -469,6 +495,7 @@ cloud.google.com/go/cloudtasks v1.13.2 h1:x6Qw5JyNbH3reL0arUtlYf77kK6OVjZZ//8JCv cloud.google.com/go/cloudtasks v1.13.2/go.mod h1:2pyE4Lhm7xY8GqbZKLnYk7eeuh8L0JwAvXx1ecKxYu8= cloud.google.com/go/cloudtasks v1.13.3 h1:rXdznKjCa7WpzmvR2plrn2KJ+RZC1oYxPiRWNQjjf3k= cloud.google.com/go/cloudtasks v1.13.3/go.mod h1:f9XRvmuFTm3VhIKzkzLCPyINSU3rjjvFUsFVGR5wi24= +cloud.google.com/go/cloudtasks v1.13.6/go.mod h1:/IDaQqGKMixD+ayM43CfsvWF2k36GeomEuy9gL4gLmU= cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute v1.27.0 h1:EGawh2RUnfHT5g8f/FX3Ds6KZuIBC77hZoDrBvEZw94= cloud.google.com/go/compute v1.27.0/go.mod h1:LG5HwRmWFKM2C5XxHRiNzkLLXW48WwvyVC0mfWsYPOM= @@ -485,6 +512,8 @@ cloud.google.com/go/compute v1.31.1 h1:SObuy8Fs6woazArpXp1fsHCw+ZH4iJ/8dGGTxUhHZ cloud.google.com/go/compute v1.31.1/go.mod h1:hyOponWhXviDptJCJSoEh89XO1cfv616wbwbkde1/+8= cloud.google.com/go/compute v1.34.0 h1:+k/kmViu4TEi97NGaxAATYtpYBviOWJySPZ+ekA95kk= cloud.google.com/go/compute v1.34.0/go.mod h1:zWZwtLwZQyonEvIQBuIa0WvraMYK69J5eDCOw9VZU4g= +cloud.google.com/go/compute v1.37.0 h1:XxtZlXYkZXub3LNaLu90TTemcFqIU1yZ4E4q9VlR39A= +cloud.google.com/go/compute v1.37.0/go.mod h1:AsK4VqrSyXBo4SMbRtfAO1VfaMjUEjEwv1UB/AwVp5Q= cloud.google.com/go/contactcenterinsights v1.9.1 h1:hy4L0bc3fQNZZrhPjuoH62RiisD5B71/S1OZNunsTRk= cloud.google.com/go/contactcenterinsights v1.10.0 h1:YR2aPedGVQPpFBZXJnPkqRj8M//8veIZZH5ZvICoXnI= cloud.google.com/go/contactcenterinsights v1.11.0 h1:u3GlrTrchHF91z58TBSdQ80G6UbVvF6Egb4utrjSvtI= @@ -506,6 +535,7 @@ cloud.google.com/go/contactcenterinsights v1.15.1 h1:cR/gQMweaG8RIWAlS5Jo1ARi8LU cloud.google.com/go/contactcenterinsights v1.15.1/go.mod h1:cFGxDVm/OwEVAHbU9UO4xQCtQFn0RZSrSUcF/oJ0Bbs= cloud.google.com/go/contactcenterinsights v1.17.1 h1:xJoZbX0HM1zht8KxAB38hs2v4Hcl+vXGLo454LrdwxA= cloud.google.com/go/contactcenterinsights v1.17.1/go.mod h1:n8OiNv7buLA2AkGVkfuvtW3HU13AdTmEwAlAu46bfxY= +cloud.google.com/go/contactcenterinsights v1.17.3/go.mod h1:7Uu2CpxS3f6XxhRdlEzYAkrChpR5P5QfcdGAFEdHOG8= cloud.google.com/go/container v1.22.1 h1:WKBegIfJJc+CL2PIgNpQuvLgGW/CoGJjge5Yjpc0YuU= cloud.google.com/go/container v1.24.0 h1:N51t/cgQJFqDD/W7Mb+IvmAPHrf8AbPx7Bb7aF4lROE= cloud.google.com/go/container v1.26.0 h1:SszQdI0qlyKsImz8/l26rpTZMyqvaH9yfua7rirDZvY= @@ -528,6 +558,7 @@ cloud.google.com/go/container v1.41.0/go.mod h1:YL6lDgCUi3frIWNIFU9qrmF7/6K1EYrt cloud.google.com/go/container v1.42.1 h1:eaMrgOl6NCk+Blhh29GgUVe3QGo7IiJQlP0w/EwLoV0= cloud.google.com/go/container v1.42.1/go.mod h1:5huIxYuOD8Ocuj0KbcyRq9MzB3J1mQObS0KSWHTYceY= cloud.google.com/go/container v1.42.2/go.mod h1:y71YW7uR5Ck+9Vsbst0AF2F3UMgqmsN4SP8JR9xEsR8= +cloud.google.com/go/container v1.42.4/go.mod h1:wf9lKc3ayWVbbV/IxKIDzT7E+1KQgzkzdxEJpj1pebE= cloud.google.com/go/containeranalysis v0.10.1 h1:SM/ibWHWp4TYyJMwrILtcBtYKObyupwOVeceI9pNblw= cloud.google.com/go/containeranalysis v0.11.0 h1:/EsoP+UTIjvl4yqrLA4WgUG83kwQhqZmbXEfqirT2LM= cloud.google.com/go/containeranalysis v0.11.1 h1:PHh4KTcMpCjYgxfV+TzvP24wolTGP9lGbqh9sBNHxjs= @@ -547,6 +578,7 @@ cloud.google.com/go/containeranalysis v0.13.2 h1:AG2gOcfZJFRiz+3SZCPnxU+gwbzKe++ cloud.google.com/go/containeranalysis v0.13.2/go.mod h1:AiKvXJkc3HiqkHzVIt6s5M81wk+q7SNffc6ZlkTDgiE= cloud.google.com/go/containeranalysis v0.13.3 h1:1D8U75BeotZxrG4jR6NYBtOt+uAeBsWhpBZmSYLakQw= cloud.google.com/go/containeranalysis v0.13.3/go.mod h1:0SYnagA1Ivb7qPqKNYPkCtphhkJn3IzgaSp3mj+9XAY= +cloud.google.com/go/containeranalysis v0.14.1/go.mod h1:28e+tlZgauWGHmEbnI5UfIsjMmrkoR1tFN0K2i71jBI= cloud.google.com/go/datacatalog v1.14.1 h1:cFPBt8V5V2T3mu/96tc4nhcMB+5cYcpwjBfn79bZDI8= cloud.google.com/go/datacatalog v1.16.0 h1:qVeQcw1Cz93/cGu2E7TYUPh8Lz5dn5Ws2siIuQ17Vng= cloud.google.com/go/datacatalog v1.17.1 h1:qGWrlYvWtK+8jD1jhwq5BsGoSr7S4/LOroV7LwXi00g= @@ -570,6 +602,7 @@ cloud.google.com/go/datacatalog v1.22.2 h1:9Bi8YO+WBE0YSSQL1tX62Gy/KcdNGLufyVlEJ cloud.google.com/go/datacatalog v1.22.2/go.mod h1:9Wamq8TDfL2680Sav7q3zEhBJSPBrDxJU8WtPJ25dBM= cloud.google.com/go/datacatalog v1.24.3 h1:3bAfstDB6rlHyK0TvqxEwaeOvoN9UgCs2bn03+VXmss= cloud.google.com/go/datacatalog v1.24.3/go.mod h1:Z4g33XblDxWGHngDzcpfeOU0b1ERlDPTuQoYG6NkF1s= +cloud.google.com/go/datacatalog v1.26.0/go.mod h1:bLN2HLBAwB3kLTFT5ZKLHVPj/weNz6bR0c7nYp0LE14= cloud.google.com/go/dataflow v0.9.1 h1:VzG2tqsk/HbmOtq/XSfdF4cBvUWRK+S+oL9k4eWkENQ= cloud.google.com/go/dataflow v0.9.2 h1:cpu2OeNxnYVadAIXETLRS5riz3KUR8ErbTojAQTFJVg= cloud.google.com/go/dataflow v0.9.4 h1:7VmCNWcPJBS/srN2QnStTB6nu4Eb5TMcpkmtaPVhRt4= @@ -588,6 +621,7 @@ cloud.google.com/go/dataflow v0.10.2 h1:o9P5/zR2mOYJmCnfp9/7RprKFZCwmSu3TvemQSmC cloud.google.com/go/dataflow v0.10.2/go.mod h1:+HIb4HJxDCZYuCqDGnBHZEglh5I0edi/mLgVbxDf0Ag= cloud.google.com/go/dataflow v0.10.3 h1:+7IfIXzYWSybIIDGK9FN2uqBsP/5b/Y0pBYzNhcmKSU= cloud.google.com/go/dataflow v0.10.3/go.mod h1:5EuVGDh5Tg4mDePWXMMGAG6QYAQhLNyzxdNQ0A1FfW4= +cloud.google.com/go/dataflow v0.10.6/go.mod h1:Vi0pTYCVGPnM2hWOQRyErovqTu2xt2sr8Rp4ECACwUI= cloud.google.com/go/dataform v0.8.1 h1:xcWso0hKOoxeW72AjBSIp/UfkvpqHNzzS0/oygHlcqY= cloud.google.com/go/dataform v0.8.2 h1:l155O3DS7pfyR91maS4l92bEjKbkbWie3dpgltZ1Q68= cloud.google.com/go/dataform v0.9.1 h1:jV+EsDamGX6cE127+QAcCR/lergVeeZdEQ6DdrxW3sQ= @@ -606,6 +640,7 @@ cloud.google.com/go/dataform v0.10.2 h1:t16DoejuOHoxJR88qrpdmFFlCXA9+x5PKrqI9qiD cloud.google.com/go/dataform v0.10.2/go.mod h1:oZHwMBxG6jGZCVZqqMx+XWXK+dA/ooyYiyeRbUxI15M= cloud.google.com/go/dataform v0.10.3 h1:ZpGkZV8OyhUhvN/tfLffU2ki5ERTtqOunkIaiVAhmw0= cloud.google.com/go/dataform v0.10.3/go.mod h1:8SruzxHYCxtvG53gXqDZvZCx12BlsUchuV/JQFtyTCw= +cloud.google.com/go/dataform v0.11.2/go.mod h1:IMmueJPEKpptT2ZLWlvIYjw6P/mYHHxA7/SUBiXqZUY= cloud.google.com/go/datafusion v1.7.1 h1:eX9CZoyhKQW6g1Xj7+RONeDj1mV8KQDKEB9KLELX9/8= cloud.google.com/go/datafusion v1.7.2 h1:CIIXp4bbwck49ZTV/URabJaV48jVB86THyVBWGgeDjw= cloud.google.com/go/datafusion v1.7.4 h1:Q90alBEYlMi66zL5gMSGQHfbZLB55mOAg03DhwTTfsk= @@ -624,6 +659,7 @@ cloud.google.com/go/datafusion v1.8.2 h1:RPoHvIeXexXwlWhEU6DNgrYCh+C+FR2EXbrnMs2 cloud.google.com/go/datafusion v1.8.2/go.mod h1:XernijudKtVG/VEvxtLv08COyVuiYPraSxm+8hd4zXA= cloud.google.com/go/datafusion v1.8.3 h1:FTMtsf2nfGGlDCuE84/RvVaCcTIYE7WQSB0noeO0cwI= cloud.google.com/go/datafusion v1.8.3/go.mod h1:hyglMzE57KRf0Rf/N2VRPcHCwKfZAAucx+LATY6Jc6Q= +cloud.google.com/go/datafusion v1.8.6/go.mod h1:fCyKJF2zUKC+O3hc2F9ja5EUCAbT4zcH692z8HiFZFw= cloud.google.com/go/datalabeling v0.8.1 h1:zxsCD/BLKXhNuRssen8lVXChUj8VxF3ofN06JfdWOXw= cloud.google.com/go/datalabeling v0.8.2 h1:4N5mbjauemzaatxGOFVpV2i8HiXSUUhyNRBU+dCBHl0= cloud.google.com/go/datalabeling v0.8.4 h1:zrq4uMmunf2KFDl/7dS6iCDBBAxBnKVDyw6+ajz3yu0= @@ -642,6 +678,7 @@ cloud.google.com/go/datalabeling v0.9.2 h1:UesbU2kYIUWhHUcnFS86ANPbugEq98X9k1whT cloud.google.com/go/datalabeling v0.9.2/go.mod h1:8me7cCxwV/mZgYWtRAd3oRVGFD6UyT7hjMi+4GRyPpg= cloud.google.com/go/datalabeling v0.9.3 h1:PqoA3gnOWaLcHCnqoZe4jh3jmiv6+Z7W2xUUkw/j4jE= cloud.google.com/go/datalabeling v0.9.3/go.mod h1:3LDFUgOx+EuNUzDyjU7VElO8L+b5LeaZEFA/ZU1O1XU= +cloud.google.com/go/datalabeling v0.9.6/go.mod h1:n7o4x0vtPensZOoFwFa4UfZgkSZm8Qs0Pg/T3kQjXSM= cloud.google.com/go/dataplex v1.8.1 h1:RvUH/k3Qi5AOXUAmQVsNCcND9qwJJq3biMSPngO0TQY= cloud.google.com/go/dataplex v1.9.0 h1:yoBWuuUZklYp7nx26evIhzq8+i/nvKYuZr1jka9EqLs= cloud.google.com/go/dataplex v1.9.1 h1:wqPAP1vRskOoWwNka1yey2wxxCrxRrcxJf78MyFvrbs= @@ -665,6 +702,7 @@ cloud.google.com/go/dataplex v1.19.2/go.mod h1:vsxxdF5dgk3hX8Ens9m2/pMNhQZklUhSg cloud.google.com/go/dataplex v1.21.0 h1:oswf105Cr2EwHrW2n7wk3nRZQf7hCe3apE/GqJ8yjvY= cloud.google.com/go/dataplex v1.21.0/go.mod h1:KXALVHwHdMBhz90IJAUSKh2gK0fEKB6CRjs4f6MrbMU= cloud.google.com/go/dataplex v1.22.0/go.mod h1:g166QMCGHvwc3qlTG4p34n+lHwu7JFfaNpMfI2uO7b8= +cloud.google.com/go/dataplex v1.25.2/go.mod h1:AH2/a7eCYvFP58scJGR7YlSY9qEhM8jq5IeOA/32IZ0= cloud.google.com/go/dataproc v1.8.0 h1:gVOqNmElfa6n/ccG/QDlfurMWwrK3ezvy2b2eDoCmS0= cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU= cloud.google.com/go/dataproc/v2 v2.0.1 h1:4OpSiPMMGV3XmtPqskBU/RwYpj3yMFjtMLj/exi425Q= @@ -688,6 +726,7 @@ cloud.google.com/go/dataproc/v2 v2.10.0/go.mod h1:HD16lk4rv2zHFhbm8gGOtrRaFohMDr cloud.google.com/go/dataproc/v2 v2.10.1 h1:2vOv471LrcSn91VNzijcH+OkDRLa3kdyymOfKqbwZ4c= cloud.google.com/go/dataproc/v2 v2.10.1/go.mod h1:fq+LSN/HYUaaV2EnUPFVPxfe1XpzGVqFnL0TTXs8juk= cloud.google.com/go/dataproc/v2 v2.11.0/go.mod h1:9vgGrn57ra7KBqz+B2KD+ltzEXvnHAUClFgq/ryU99g= +cloud.google.com/go/dataproc/v2 v2.11.2/go.mod h1:xwukBjtfiO4vMEa1VdqyFLqJmcv7t3lo+PbLDcTEw+g= cloud.google.com/go/dataqna v0.8.1 h1:ITpUJep04hC9V7C+gcK390HO++xesQFSUJ7S4nSnF3U= cloud.google.com/go/dataqna v0.8.2 h1:vJ9JVKDgDG7AQMbTD8pdWaogJ4c/yHn0qer+q0nFIaw= cloud.google.com/go/dataqna v0.8.4 h1:NJnu1kAPamZDs/if3bJ3+Wb6tjADHKL83NUWsaIp2zg= @@ -706,6 +745,7 @@ cloud.google.com/go/dataqna v0.9.2 h1:hrEcid5jK5fEdlYZ0eS8HJoq+ZCTRWSV7Av42V/G99 cloud.google.com/go/dataqna v0.9.2/go.mod h1:WCJ7pwD0Mi+4pIzFQ+b2Zqy5DcExycNKHuB+VURPPgs= cloud.google.com/go/dataqna v0.9.3 h1:lGUj2FYs650EUPDMV6plWBAoh8qH9Bu1KCz1PUYF2VY= cloud.google.com/go/dataqna v0.9.3/go.mod h1:PiAfkXxa2LZYxMnOWVYWz3KgY7txdFg9HEMQPb4u1JA= +cloud.google.com/go/dataqna v0.9.6/go.mod h1:rjnNwjh8l3ZsvrANy6pWseBJL2/tJpCcBwJV8XCx4kU= cloud.google.com/go/datastore v1.12.1 h1:i8HMKsqg/Sl3ZlOTGl471Z8j2uKtbRDT9VXJUIVlMik= cloud.google.com/go/datastore v1.13.0 h1:ktbC66bOQB3HJPQe8qNI1/aiQ77PMu7hD4mzE6uxe3w= cloud.google.com/go/datastore v1.14.0 h1:Mq0ApTRdLW3/dyiw+DkjTk0+iGIUvkbzaC8sfPwWTH4= @@ -736,6 +776,7 @@ cloud.google.com/go/datastream v1.11.2/go.mod h1:RnFWa5zwR5SzHxeZGJOlQ4HKBQPcjGf cloud.google.com/go/datastream v1.12.1 h1:j5cIRYJHjx/058aHa4Slip7fl62UTGHCJc4GL9bxQLQ= cloud.google.com/go/datastream v1.12.1/go.mod h1:GxPeRBsokZ8ylxVJBp9Q39QG+z4Iri5QIBRJrKuzJVQ= cloud.google.com/go/datastream v1.13.0/go.mod h1:GrL2+KC8mV4GjbVG43Syo5yyDXp3EH+t6N2HnZb1GOQ= +cloud.google.com/go/datastream v1.14.1/go.mod h1:JqMKXq/e0OMkEgfYe0nP+lDye5G2IhIlmencWxmesMo= cloud.google.com/go/deploy v1.11.0 h1:rp+Sf2bWuqJYBuygQl6diFAdvlR8kklhD+stDvyl1zM= cloud.google.com/go/deploy v1.13.0 h1:A+w/xpWgz99EYzB6e31gMGAI/P5jTZ2UO7veQK5jQ8o= cloud.google.com/go/deploy v1.13.1 h1:eV5MdoQJGdac/k7D97SDjD8iLE4jCzL42UCAgG6j0iE= @@ -758,6 +799,7 @@ cloud.google.com/go/deploy v1.24.0/go.mod h1:h9uVCWxSDanXUereI5WR+vlZdbPJ6XGy+gc cloud.google.com/go/deploy v1.26.1 h1:Hm3pXBzMFJFPOdwtDkg5e/LP53bXqIpwQpjwsVasjhU= cloud.google.com/go/deploy v1.26.1/go.mod h1:PwF9RP0Jh30Qd+I71wb52oM42LgfRKXRMSg87wKpK3I= cloud.google.com/go/deploy v1.26.2/go.mod h1:XpS3sG/ivkXCfzbzJXY9DXTeCJ5r68gIyeOgVGxGNEs= +cloud.google.com/go/deploy v1.27.1/go.mod h1:il2gxiMgV3AMlySoQYe54/xpgVDoEh185nj4XjJ+GRk= cloud.google.com/go/dialogflow v1.38.0 h1:kP0t9SX0w3Fbs1q36mSZ3GQuyOgauVhdNXw0wK4cmOI= cloud.google.com/go/dialogflow v1.40.0 h1:sCJbaXt6ogSbxWQnERKAzos57f02PP6WkGbOZvXUdwc= cloud.google.com/go/dialogflow v1.43.0 h1:0hBV5ipVbhYNKCyiBoM47bUt+43Kd8eWXhBr+pwUSTw= @@ -782,6 +824,7 @@ cloud.google.com/go/dialogflow v1.59.0/go.mod h1:PjsrI+d2FI4BlGThxL0+Rua/g9vLI+2 cloud.google.com/go/dialogflow v1.64.1 h1:6fU4IKLpvgpXqiUCE8gUp8eV5u629SCtiyXMudXtZSg= cloud.google.com/go/dialogflow v1.64.1/go.mod h1:jkv4vTiGhEUPBzmk1sJ+S1Duu2epCOBNHoWUImHkO5U= cloud.google.com/go/dialogflow v1.66.0/go.mod h1:BPiRTnnXP/tHLot5h/U62Xcp+i6ekRj/bq6uq88p+Lw= +cloud.google.com/go/dialogflow v1.68.2/go.mod h1:E0Ocrhf5/nANZzBju8RX8rONf0PuIvz2fVj3XkbAhiY= cloud.google.com/go/dlp v1.10.1 h1:tF3wsJ2QulRhRLWPzWVkeDz3FkOGVoMl6cmDUHtfYxw= cloud.google.com/go/dlp v1.10.2 h1:sWOATigjZOKmA2rVOSjIcKLCtL2ifdawaukx+H9iffk= cloud.google.com/go/dlp v1.11.1 h1:OFlXedmPP/5//X1hBEeq3D9kUVm9fb6ywYANlpv/EsQ= @@ -801,6 +844,7 @@ cloud.google.com/go/dlp v1.20.0/go.mod h1:nrGsA3r8s7wh2Ct9FWu69UjBObiLldNyQda2RC cloud.google.com/go/dlp v1.20.1 h1:qAEGTTtC97zuDm6YPBozNvy4BLBszVCJah3efNytl3g= cloud.google.com/go/dlp v1.20.1/go.mod h1:NO0PLy43RQV0QI6vZcPiNTR9eiKu9pFzawaueBlDwz8= cloud.google.com/go/dlp v1.21.0/go.mod h1:Y9HOVtPoArpL9sI1O33aN/vK9QRwDERU9PEJJfM8DvE= +cloud.google.com/go/dlp v1.22.1/go.mod h1:Gc7tGo1UJJTBRt4OvNQhm8XEQ0i9VidAiGXBVtsftjM= cloud.google.com/go/documentai v1.20.0 h1:DK9nDulPQgdy3pJIYjMIRrFSAe/Ch3TpfHVn83aV/Gk= cloud.google.com/go/documentai v1.22.0 h1:dW8ex9yb3oT9s1yD2+yLcU8Zq15AquRZ+wd0U+TkxFw= cloud.google.com/go/documentai v1.22.1 h1:cBndyac7kPWwSuhUcgdbnqzszfZ57HBEHfD33DIwsBM= @@ -824,6 +868,7 @@ cloud.google.com/go/documentai v1.35.0/go.mod h1:ZotiWUlDE8qXSUqkJsGMQqVmfTMYATw cloud.google.com/go/documentai v1.35.1 h1:52RfiUsoblXcE57CfKJGnITWLxRM30BcqNk/BKZl2LI= cloud.google.com/go/documentai v1.35.1/go.mod h1:WJjwUAQfwQPJORW8fjz7RODprMULDzEGLA2E6WxenFw= cloud.google.com/go/documentai v1.35.2/go.mod h1:oh/0YXosgEq3hVhyH4ZQ7VNXPaveRO4eLVM3tBSZOsI= +cloud.google.com/go/documentai v1.37.0/go.mod h1:qAf3ewuIUJgvSHQmmUWvM3Ogsr5A16U2WPHmiJldvLA= cloud.google.com/go/domains v0.9.1 h1:rqz6KY7mEg7Zs/69U6m6LMbB7PxFDWmT3QWNXIqhHm0= cloud.google.com/go/domains v0.9.2 h1:SjpTtaTNRPPajrGiZEtxz9dpElO4PxuDWFvU4JpV1gk= cloud.google.com/go/domains v0.9.4 h1:ua4GvsDztZ5F3xqjeLKVRDeOvJshf5QFgWGg1CKti3A= @@ -842,6 +887,7 @@ cloud.google.com/go/domains v0.10.2 h1:ekJCkuzbciXyPKkwPwvI+2Ov1GcGJtMXj/fbgilPF cloud.google.com/go/domains v0.10.2/go.mod h1:oL0Wsda9KdJvvGNsykdalHxQv4Ri0yfdDkIi3bzTUwk= cloud.google.com/go/domains v0.10.3 h1:wnqN5YwMrtLSjn+HB2sChgmZ6iocOta4Q41giQsiRjY= cloud.google.com/go/domains v0.10.3/go.mod h1:m7sLe18p0PQab56bVH3JATYOJqyRHhmbye6gz7isC7o= +cloud.google.com/go/domains v0.10.6/go.mod h1:3xzG+hASKsVBA8dOPc4cIaoV3OdBHl1qgUpAvXK7pGY= cloud.google.com/go/edgecontainer v1.1.1 h1:zhHWnLzg6AqzE+I3gzJqiIwHfjEBhWctNQEzqb+FaRo= cloud.google.com/go/edgecontainer v1.1.2 h1:B+Acb/0frXUxc60i6lC0JtXrBFAKoS7ZELmet9+ySo8= cloud.google.com/go/edgecontainer v1.1.4 h1:Szy3Q/N6bqgQGyxqjI+6xJZbmvPvnFHp3UZr95DKcQ0= @@ -860,6 +906,7 @@ cloud.google.com/go/edgecontainer v1.4.0 h1:vpKTEkQPpkl55d6aUU2rzDFvTkMUATvBXfZS cloud.google.com/go/edgecontainer v1.4.0/go.mod h1:Hxj5saJT8LMREmAI9tbNTaBpW5loYiWFyisCjDhzu88= cloud.google.com/go/edgecontainer v1.4.1 h1:SwQuHQiheVfL7b5ar/AXDberiaqr/yiue8X55AdWnZU= cloud.google.com/go/edgecontainer v1.4.1/go.mod h1:ubMQvXSxsvtEjJLyqcPFrdWrHfvjQxdoyt+SUrAi5ek= +cloud.google.com/go/edgecontainer v1.4.3/go.mod h1:q9Ojw2ox0uhAvFisnfPRAXFTB1nfRIOIXVWzdXMZLcE= cloud.google.com/go/errorreporting v0.3.0 h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0= cloud.google.com/go/errorreporting v0.3.1 h1:E/gLk+rL7u5JZB9oq72iL1bnhVlLrnfslrgcptjJEUE= cloud.google.com/go/errorreporting v0.3.1/go.mod h1:6xVQXU1UuntfAf+bVkFk6nld41+CPyF2NSPCyXE3Ztk= @@ -883,6 +930,7 @@ cloud.google.com/go/essentialcontacts v1.7.2 h1:a/reGTn7WblM5DgieiLbX6CswHgTneWr cloud.google.com/go/essentialcontacts v1.7.2/go.mod h1:NoCBlOIVteJFJU+HG9dIG/Cc9kt1K9ys9mbOaGPUmPc= cloud.google.com/go/essentialcontacts v1.7.3 h1:Paw495vxVyKuAgcQ2NQk09iRZBhPYRytknydEnvzcv4= cloud.google.com/go/essentialcontacts v1.7.3/go.mod h1:uimfZgDbhWNCmBpwUUPHe4vcMY2azsq/axC9f7vZFKI= +cloud.google.com/go/essentialcontacts v1.7.6/go.mod h1:/Ycn2egr4+XfmAfxpLYsJeJlVf9MVnq9V7OMQr9R4lA= cloud.google.com/go/eventarc v1.12.1 h1:8ZAkv7MTnAhix5kSw+Cm/xVzG8+OhC+flZGL9iRdpQA= cloud.google.com/go/eventarc v1.13.0 h1:xIP3XZi0Xawx8DEfh++mE2lrIi5kQmCr/KcWhJ1q0J4= cloud.google.com/go/eventarc v1.13.1 h1:FmEcxG5rX3LaUB2nRjf2Pas5J5TtVrVznaHN5rxYxnQ= @@ -902,6 +950,7 @@ cloud.google.com/go/eventarc v1.15.0 h1:IVU2EOR8P2f6N8eneuwspN122LR87v9G54B+7ihd cloud.google.com/go/eventarc v1.15.0/go.mod h1:PAd/pPIZdJtJQFJI1yDEUms1mqohdNuM1BFEVHHlVFg= cloud.google.com/go/eventarc v1.15.1 h1:RMymT7R87LaxKugOKwooOoheWXUm1NMeOfh3CVU9g54= cloud.google.com/go/eventarc v1.15.1/go.mod h1:K2luolBpwaVOujZQyx6wdG4n2Xum4t0q1cMBmY1xVyI= +cloud.google.com/go/eventarc v1.15.5/go.mod h1:vDCqGqyY7SRiickhEGt1Zhuj81Ya4F/NtwwL3OZNskg= cloud.google.com/go/filestore v1.7.1 h1:Eiz8xZzMJc5ppBWkuaod/PUdUZGCFR8ku0uS+Ah2fRw= cloud.google.com/go/filestore v1.7.2 h1:/Nnk5pOoY1Lx6A42hJ2eBYcBfqKvLcnh8fV4egopvY4= cloud.google.com/go/filestore v1.7.4 h1:twtI5/89kf9QW7MqDic9fsUbH5ZLIDV1MVsRmu9iu2E= @@ -921,6 +970,7 @@ cloud.google.com/go/filestore v1.9.2 h1:DYwMNAcF5bELHHMxRdkIWWZ3XicKp+ZpEBy+c6Gt cloud.google.com/go/filestore v1.9.2/go.mod h1:I9pM7Hoetq9a7djC1xtmtOeHSUYocna09ZP6x+PG1Xw= cloud.google.com/go/filestore v1.9.3 h1:vTXQI5qYKZ8dmCyHN+zVfaMyXCYbyZNM0CkPzpPUn7Q= cloud.google.com/go/filestore v1.9.3/go.mod h1:Me0ZRT5JngT/aZPIKpIK6N4JGMzrFHRtGHd9ayUS4R4= +cloud.google.com/go/filestore v1.10.2/go.mod h1:w0Pr8uQeSRQfCPRsL0sYKW6NKyooRgixCkV9yyLykR4= cloud.google.com/go/firestore v1.11.0 h1:PPgtwcYUOXV2jFe1bV3nda3RCrOa8cvBjTOn2MQVfW8= cloud.google.com/go/firestore v1.13.0 h1:/3S4RssUV4GO/kvgJZB+tayjhOfyAHs+KcpJgRVu/Qk= cloud.google.com/go/firestore v1.14.0 h1:8aLcKnMPoldYU3YHgu4t2exrKhLQkqaXAGqT0ljrFVw= @@ -950,6 +1000,7 @@ cloud.google.com/go/functions v1.19.2 h1:Cu2Gj1JBBJv9gi89r8LrZNsJhGwePnhttn4Blqw cloud.google.com/go/functions v1.19.2/go.mod h1:SBzWwWuaFDLnUyStDAMEysVN1oA5ECLbP3/PfJ9Uk7Y= cloud.google.com/go/functions v1.19.3 h1:V0vCHSgFTUqKn57+PUXp1UfQY0/aMkveAw7wXeM3Lq0= cloud.google.com/go/functions v1.19.3/go.mod h1:nOZ34tGWMmwfiSJjoH/16+Ko5106x+1Iji29wzrBeOo= +cloud.google.com/go/functions v1.19.6/go.mod h1:0G0RnIlbM4MJEycfbPZlCzSf2lPOjL7toLDwl+r0ZBw= cloud.google.com/go/gaming v1.8.0 h1:97OAEQtDazAJD7yh/kvQdSCQuTKdR0O+qWAJBZJ4xiA= cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc= cloud.google.com/go/gaming v1.10.1 h1:5qZmZEWzMf8GEFgm9NeC3bjFRpt7x4S6U7oLbxaf7N8= @@ -972,6 +1023,7 @@ cloud.google.com/go/gkebackup v1.6.2 h1:lWaSgjSonOXe41UhwQjts6lhDZdr5e882LNUTtnj cloud.google.com/go/gkebackup v1.6.2/go.mod h1:WsTSWqKJkGan1pkp5dS30oxb+Eaa6cLvxEUxKTUALwk= cloud.google.com/go/gkebackup v1.6.3 h1:djdExe/QgoKdp1gnIO1G5BoO1o/yGQOQJJEZ4QKTEXQ= cloud.google.com/go/gkebackup v1.6.3/go.mod h1:JJzGsA8/suXpTDtqI7n9RZW97PXa2CIp+n8aRC/y57k= +cloud.google.com/go/gkebackup v1.7.0/go.mod h1:oPHXUc6X6tg6Zf/7QmKOfXOFaVzBEgMWpLDb4LqngWA= cloud.google.com/go/gkeconnect v0.8.1 h1:a1ckRvVznnuvDWESM2zZDzSVFvggeBaVY5+BVB8tbT0= cloud.google.com/go/gkeconnect v0.8.2 h1:AuR3YNK0DgLVrmcc8o4sBrU0dVs/SULSuLh4Gmn1e10= cloud.google.com/go/gkeconnect v0.8.4 h1:1JLpZl31YhQDQeJ98tK6QiwTpgHFYRJwpntggpQQWis= @@ -990,6 +1042,7 @@ cloud.google.com/go/gkeconnect v0.11.2 h1:OvAiFt5fJxwqZdV0syFLuwImQ6L6nHh2cW4sCG cloud.google.com/go/gkeconnect v0.11.2/go.mod h1:+Sj47chrbFMON1wjG6DA4KJKi85/7ON7GQZXEo0cbaQ= cloud.google.com/go/gkeconnect v0.12.1 h1:YVpR0vlHSP/wD74PXEbKua4Aamud+wiYm4TiewNjD3M= cloud.google.com/go/gkeconnect v0.12.1/go.mod h1:L1dhGY8LjINmWfR30vneozonQKRSIi5DWGIHjOqo58A= +cloud.google.com/go/gkeconnect v0.12.4/go.mod h1:bvpU9EbBpZnXGo3nqJ1pzbHWIfA9fYqgBMJ1VjxaZdk= cloud.google.com/go/gkehub v0.14.1 h1:2BLSb8i+Co1P05IYCKATXy5yaaIw/ZqGvVSBTLdzCQo= cloud.google.com/go/gkehub v0.14.2 h1:7rddjV52z0RbToFYj1B39R9dsn+6IXgx4DduEH7N25Q= cloud.google.com/go/gkehub v0.14.4 h1:J5tYUtb3r0cl2mM7+YHvV32eL+uZQ7lONyUZnPikCEo= @@ -1008,6 +1061,7 @@ cloud.google.com/go/gkehub v0.15.2 h1:CR5MPEP/Ogk5IahCq3O2fKS6TJZQi8mrnrysGHCs0g cloud.google.com/go/gkehub v0.15.2/go.mod h1:8YziTOpwbM8LM3r9cHaOMy2rNgJHXZCrrmGgcau9zbQ= cloud.google.com/go/gkehub v0.15.3 h1:yZ6lNJ9rNIoQmWrG14dB3+BFjS/EIRBf7Bo6jc5QWlE= cloud.google.com/go/gkehub v0.15.3/go.mod h1:nzFT/Q+4HdQES/F+FP1QACEEWR9Hd+Sh00qgiH636cU= +cloud.google.com/go/gkehub v0.15.6/go.mod h1:sRT0cOPAgI1jUJrS3gzwdYCJ1NEzVVwmnMKEwrS2QaM= cloud.google.com/go/gkemulticloud v0.6.1 h1:vg81EW3GQ4RO4PT1MdNHE8aF87EiohZp/WwMWfUTTR0= cloud.google.com/go/gkemulticloud v1.0.0 h1:MluqhtPVZReoriP5+adGIw+ij/RIeRik8KApCW2WMTw= cloud.google.com/go/gkemulticloud v1.0.1 h1:V82LxEvFIGJnebn7BBdOUKcVlNQqBaubbKtLgRicHow= @@ -1028,6 +1082,7 @@ cloud.google.com/go/gkemulticloud v1.4.1 h1:SvVD2nJTGScEDYygIQ5dI14oFYhgtJx8Hazk cloud.google.com/go/gkemulticloud v1.4.1/go.mod h1:KRvPYcx53bztNwNInrezdfNF+wwUom8Y3FuJBwhvFpQ= cloud.google.com/go/gkemulticloud v1.5.1 h1:JWe6PDNpNU88ZYvQkTd7w28fgeIs/gg6i0hcjUkgZ3M= cloud.google.com/go/gkemulticloud v1.5.1/go.mod h1:OdmhfSPXuJ0Kn9dQ2I3Ou7XZ3QK8caV4XVOJZwrIa3s= +cloud.google.com/go/gkemulticloud v1.5.3/go.mod h1:KPFf+/RcfvmuScqwS9/2MF5exZAmXSuoSLPuaQ98Xlk= cloud.google.com/go/grafeas v0.2.0 h1:CYjC+xzdPvbV65gi6Dr4YowKcmLo045pm18L0DhdELM= cloud.google.com/go/grafeas v0.3.4 h1:D4x32R/cHX3MTofKwirz015uEdVk4uAxvZkZCZkOrF4= cloud.google.com/go/gsuiteaddons v1.6.1 h1:mi9jxZpzVjLQibTS/XfPZvl+Jr6D5Bs8pGqUjllRb00= @@ -1049,6 +1104,7 @@ cloud.google.com/go/gsuiteaddons v1.7.2/go.mod h1:GD32J2rN/4APilqZw4JKmwV84+jowY cloud.google.com/go/gsuiteaddons v1.7.3 h1:QafYhVhyFGpidBUUlVhy6lUHFogFOycVYm9DV7MinhA= cloud.google.com/go/gsuiteaddons v1.7.3/go.mod h1:0rR+LC21v1Sx1Yb6uohHI/F8DF3h2arSJSHvfi3GmyQ= cloud.google.com/go/gsuiteaddons v1.7.4/go.mod h1:gpE2RUok+HUhuK7RPE/fCOEgnTffS0lCHRaAZLxAMeE= +cloud.google.com/go/gsuiteaddons v1.7.7/go.mod h1:zTGmmKG/GEBCONsvMOY2ckDiEsq3FN+lzWGUiXccF9o= cloud.google.com/go/iap v1.8.1 h1:X1tcp+EoJ/LGX6cUPt3W2D4H2Kbqq0pLAsldnsCjLlE= cloud.google.com/go/iap v1.9.0 h1:RNhVq/6OMI99/wjPVhqFxjlBxYOBRdaG6rLpBvyaqYY= cloud.google.com/go/iap v1.9.1 h1:J5r6CL6EakRmsMRIm2yV0PF5zfIm4sMQbQfPhSTnRzA= @@ -1068,6 +1124,7 @@ cloud.google.com/go/iap v1.10.2 h1:rvM+FNIF2wIbwUU8299FhhVGak2f7oOvbW8J/I5oflE= cloud.google.com/go/iap v1.10.2/go.mod h1:cClgtI09VIfazEK6VMJr6bX8KQfuQ/D3xqX+d0wrUlI= cloud.google.com/go/iap v1.10.3 h1:OWNYFHPyIBNHEAEFdVKOltYWe0g3izSrpFJW6Iidovk= cloud.google.com/go/iap v1.10.3/go.mod h1:xKgn7bocMuCFYhzRizRWP635E2LNPnIXT7DW0TlyPJ8= +cloud.google.com/go/iap v1.11.1/go.mod h1:qFipMJ4nOIv4yDHZxn31PiS8QxJJH2FlxgH9aFauejw= cloud.google.com/go/ids v1.4.1 h1:khXYmSoDDhWGEVxHl4c4IgbwSRR+qE/L4hzP3vaU9Hc= cloud.google.com/go/ids v1.4.2 h1:KqvR28pAnIss6d2pmGOQ+Fcsi3FOWDVhqdr6QaVvqsI= cloud.google.com/go/ids v1.4.4 h1:VuFqv2ctf/A7AyKlNxVvlHTzjrEvumWaZflUzBPz/M4= @@ -1086,6 +1143,7 @@ cloud.google.com/go/ids v1.5.2 h1:EDYZQraE+Eq6BewUQxVRY8b3VUUo/MnjMfzSh1NGjx8= cloud.google.com/go/ids v1.5.2/go.mod h1:P+ccDD96joXlomfonEdCnyrHvE68uLonc7sJBPVM5T0= cloud.google.com/go/ids v1.5.3 h1:wbFF7twu0XScFr+dtsVxTTttbFIRYt/SJjZiHFidtYE= cloud.google.com/go/ids v1.5.3/go.mod h1:a2MX8g18Eqs7yxD/pnEdid42SyBUm9LIzSWf8Jux9OY= +cloud.google.com/go/ids v1.5.6/go.mod h1:y3SGLmEf9KiwKsH7OHvYYVNIJAtXybqsD2z8gppsziQ= cloud.google.com/go/iot v1.7.1 h1:yrH0OSmicD5bqGBoMlWG8UltzdLkYzNUwNVUVz7OT54= cloud.google.com/go/iot v1.7.2 h1:qFNv3teWkONIPmuY2mzodEnHb6E67ch2OZ6216ycUiU= cloud.google.com/go/iot v1.7.4 h1:m1WljtkZnvLTIRYW1YTOv5A6H1yKgLHR6nU7O8yf27w= @@ -1104,6 +1162,7 @@ cloud.google.com/go/iot v1.8.2 h1:KMN0wujrPV7q0yfs4rt5CUl9Di8sQhJ0uohJn1h6yaI= cloud.google.com/go/iot v1.8.2/go.mod h1:UDwVXvRD44JIcMZr8pzpF3o4iPsmOO6fmbaIYCAg1ww= cloud.google.com/go/iot v1.8.3 h1:aPWYQ+A1NX6ou/5U0nFAiXWdVT8OBxZYVZt2fBl2gWA= cloud.google.com/go/iot v1.8.3/go.mod h1:dYhrZh+vUxIQ9m3uajyKRSW7moF/n0rYmA2PhYAkMFE= +cloud.google.com/go/iot v1.8.6/go.mod h1:MThnkiihNkMysWNeNje2Hp0GSOpEq2Wkb/DkBCVYa0U= cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U= cloud.google.com/go/kms v1.15.0 h1:xYl5WEaSekKYN5gGRyhjvZKM22GVBBCzegGNVPy+aIs= cloud.google.com/go/kms v1.15.2 h1:lh6qra6oC4AyWe5fUUUBe/S27k12OHAleOOOw6KakdE= @@ -1125,6 +1184,7 @@ cloud.google.com/go/kms v1.20.1/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzD cloud.google.com/go/kms v1.20.5 h1:aQQ8esAIVZ1atdJRxihhdxGQ64/zEbJoJnCz/ydSmKg= cloud.google.com/go/kms v1.20.5/go.mod h1:C5A8M1sv2YWYy1AE6iSrnddSG9lRGdJq5XEdBy28Lmw= cloud.google.com/go/kms v1.21.0/go.mod h1:zoFXMhVVK7lQ3JC9xmhHMoQhnjEDZFoLAr5YMwzBLtk= +cloud.google.com/go/kms v1.21.2/go.mod h1:8wkMtHV/9Z8mLXEXr1GK7xPSBdi6knuLXIhqjuWcI6w= cloud.google.com/go/language v1.10.1 h1:3MXeGEv8AlX+O2LyV4pO4NGpodanc26AmXwOuipEym0= cloud.google.com/go/language v1.11.0 h1:KnYolG0T5Oex722ZW/sP5QErhVAVNcqpJ16tVJd9RTw= cloud.google.com/go/language v1.11.1 h1:BjU7Ljhh0ZYnZC8jZwiezf1FH75yijJ4raAScseqCns= @@ -1144,6 +1204,7 @@ cloud.google.com/go/language v1.14.2 h1:rwrIOwcAgPTYbigOaiMSjKCvBy0xHZJbRc7HB/xM cloud.google.com/go/language v1.14.2/go.mod h1:dviAbkxT9art+2ioL9AM05t+3Ql6UPfMpwq1cDsF+rg= cloud.google.com/go/language v1.14.3 h1:8hmFMiS3wjjj3TX/U1zZYTgzwZoUjDbo9PaqcYEmuB4= cloud.google.com/go/language v1.14.3/go.mod h1:hjamj+KH//QzF561ZuU2J+82DdMlFUjmiGVWpovGGSA= +cloud.google.com/go/language v1.14.5/go.mod h1:nl2cyAVjcBct1Hk73tzxuKebk0t2eULFCaruhetdZIA= cloud.google.com/go/lifesciences v0.9.1 h1:axkANGx1wiBXHiPcJZAE+TDjjYoJRIDzbHC/WYllCBU= cloud.google.com/go/lifesciences v0.9.2 h1:0naTq5qUWoRt/b5P+SZ/0mun7ZTlhpJZJsUxhCmLv1c= cloud.google.com/go/lifesciences v0.9.4 h1:rZEI/UxcxVKEzyoRS/kdJ1VoolNItRWjNN0Uk9tfexg= @@ -1162,6 +1223,7 @@ cloud.google.com/go/lifesciences v0.10.2 h1:eZSaRgBwbnb/oXwCj1SGE0Kp534DuXpg55iY cloud.google.com/go/lifesciences v0.10.2/go.mod h1:vXDa34nz0T/ibUNoeHnhqI+Pn0OazUTdxemd0OLkyoY= cloud.google.com/go/lifesciences v0.10.3 h1:Z05C+Ui953f0EQx9hJ1la6+QQl8ADrIs3iNwP5Elkpg= cloud.google.com/go/lifesciences v0.10.3/go.mod h1:hnUUFht+KcZcliixAg+iOh88FUwAzDQQt5tWd7iIpNg= +cloud.google.com/go/lifesciences v0.10.6/go.mod h1:1nnZwaZcBThDujs9wXzECnd1S5d+UiDkPuJWAmhRi7Q= cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= cloud.google.com/go/logging v1.8.1 h1:26skQWPeYhvIasWKm48+Eq7oUqdcdbwsCVwz5Ys0FvU= cloud.google.com/go/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw= @@ -1191,6 +1253,7 @@ cloud.google.com/go/managedidentities v1.7.2 h1:oWxuIhIwQC1Vfs1SZi1x389W2TV9uyPs cloud.google.com/go/managedidentities v1.7.2/go.mod h1:t0WKYzagOoD3FNtJWSWcU8zpWZz2i9cw2sKa9RiPx5I= cloud.google.com/go/managedidentities v1.7.3 h1:b9xGs24BIjfyvLgCtJoClOZpPi8d8owPgWe5JEINgaY= cloud.google.com/go/managedidentities v1.7.3/go.mod h1:H9hO2aMkjlpY+CNnKWRh+WoQiUIDO8457wWzUGsdtLA= +cloud.google.com/go/managedidentities v1.7.6/go.mod h1:pYCWPaI1AvR8Q027Vtp+SFSM/VOVgbjBF4rxp1/z5p4= cloud.google.com/go/maps v1.3.0 h1:m4BlGu0qnPwuq5aToT3atcVckS+hf40jsRXveJhusJI= cloud.google.com/go/maps v1.4.0 h1:PdfgpBLhAoSzZrQXP+/zBc78fIPLZSJp5y8+qSMn2UU= cloud.google.com/go/maps v1.4.1 h1:/wp8wImC3tHIHOoaQGRA+KyH3as/Dvp+3J/NqJQBiPQ= @@ -1213,6 +1276,7 @@ cloud.google.com/go/maps v1.14.1/go.mod h1:ZFqZS04ucwFiHSNU8TBYDUr3wYhj5iBFJk24I cloud.google.com/go/maps v1.17.1 h1:u7U/DieTxYYMDyvHQ00la5ayXLjDImTfnhdAsyPZXyY= cloud.google.com/go/maps v1.17.1/go.mod h1:lGZCm2ILmN06GQyrRQwA1rScqQZuApQsCTX+0v+bdm8= cloud.google.com/go/maps v1.19.0/go.mod h1:goHUXrmzoZvQjUVd0KGhH8t3AYRm17P8b+fsyR1UAmQ= +cloud.google.com/go/maps v1.20.4/go.mod h1:Act0Ws4HffrECH+pL8YYy1scdSLegov7+0c6gvKqRzI= cloud.google.com/go/mediatranslation v0.8.1 h1:50cF7c1l3BanfKrpnTCaTvhf+Fo6kdF21DG0byG7gYU= cloud.google.com/go/mediatranslation v0.8.2 h1:nyBZbNX1j34H00n+irnQraCogrkRWntQsDoA6s8OfKo= cloud.google.com/go/mediatranslation v0.8.4 h1:VRCQfZB4s6jN0CSy7+cO3m4ewNwgVnaePanVCQh/9Z4= @@ -1231,6 +1295,7 @@ cloud.google.com/go/mediatranslation v0.9.2 h1:p37R/k9+L33bUMO87gFyv93MwJ+9nuzVh cloud.google.com/go/mediatranslation v0.9.2/go.mod h1:1xyRoDYN32THzy+QaU62vIMciX0CFexplju9t30XwUc= cloud.google.com/go/mediatranslation v0.9.3 h1:nRBjeaMLipw05Br+qDAlSCcCQAAlat4mvpafztbEVgc= cloud.google.com/go/mediatranslation v0.9.3/go.mod h1:KTrFV0dh7duYKDjmuzjM++2Wn6yw/I5sjZQVV5k3BAA= +cloud.google.com/go/mediatranslation v0.9.6/go.mod h1:WS3QmObhRtr2Xu5laJBQSsjnWFPPthsyetlOyT9fJvE= cloud.google.com/go/memcache v1.10.1 h1:7lkLsF0QF+Mre0O/NvkD9Q5utUNwtzvIYjrOLOs0HO0= cloud.google.com/go/memcache v1.10.2 h1:WLJALO3FxuStMiYdSQwiQBDBcs4G8DDwZQmXK+YzAWk= cloud.google.com/go/memcache v1.10.4 h1:cdex/ayDd294XBj2cGeMe6Y+H1JvhN8y78B9UW7pxuQ= @@ -1249,6 +1314,7 @@ cloud.google.com/go/memcache v1.11.2 h1:GGgC2A9AClJN8VLbMUAPUxj/dNMFwz6Lj01gDxPw cloud.google.com/go/memcache v1.11.2/go.mod h1:jIzHn79b0m5wbkax2SdlW5vNSbpaEk0yWHbeLpMIYZE= cloud.google.com/go/memcache v1.11.3 h1:XH/qT3GbbSH//R0JTqR77lRpBxaa0N9sHgAzfwbTrv0= cloud.google.com/go/memcache v1.11.3/go.mod h1:UeWI9cmY7hvjU1EU6dwJcQb6EFG4GaM3KNXOO2OFsbI= +cloud.google.com/go/memcache v1.11.6/go.mod h1:ZM6xr1mw3F8TWO+In7eq9rKlJc3jlX2MDt4+4H+/+cc= cloud.google.com/go/metastore v1.11.1 h1:sF2yYgo2P4b3hJP2LlIZoafZixtabF/fnORDDMkFeqQ= cloud.google.com/go/metastore v1.12.0 h1:+9DsxUOHvsqvC0ylrRc/JwzbXJaaBpfIK3tX0Lx8Tcc= cloud.google.com/go/metastore v1.13.0 h1:iMMU4DY4yojvKatMfv1q9WqBHi3ZrcwAIYQ+ZrlXM2o= @@ -1269,6 +1335,7 @@ cloud.google.com/go/metastore v1.14.2 h1:Euc9kLTKS8T6M1JVqQavwDFHu9UtT1//lGXSKjp cloud.google.com/go/metastore v1.14.2/go.mod h1:dk4zOBhZIy3TFOQlI8sbOa+ef0FjAcCHEnd8dO2J+LE= cloud.google.com/go/metastore v1.14.3 h1:jDqeCw6NGDRAPT9+2Y/EjnWAB0BfCcUfmPLOyhB0eHs= cloud.google.com/go/metastore v1.14.3/go.mod h1:HlbGVOvg0ubBLVFRk3Otj3gtuzInuzO/TImOBwsKlG4= +cloud.google.com/go/metastore v1.14.6/go.mod h1:iDbuGwlDr552EkWA5E1Y/4hHme3cLv3ZxArKHXjS2OU= cloud.google.com/go/monitoring v1.15.1 h1:65JhLMd+JiYnXr6j5Z63dUYCuOg770p8a/VC+gil/58= cloud.google.com/go/monitoring v1.16.0 h1:rlndy4K8yknMY9JuGe2aK4SbCh21FXoCdX7SAGHmRgI= cloud.google.com/go/monitoring v1.16.1 h1:CTklIuUkS5nCricGojPwdkSgPsCTX2HmYTxFDg+UvpU= @@ -1303,6 +1370,7 @@ cloud.google.com/go/networkconnectivity v1.15.2 h1:CuBLrRKhPbzXkFGADopQUpMcdY+SS cloud.google.com/go/networkconnectivity v1.15.2/go.mod h1:N1O01bEk5z9bkkWwXLKcN2T53QN49m/pSpjfUvlHDQY= cloud.google.com/go/networkconnectivity v1.16.1 h1:YsVhG71ZC4FkqCP2oCI55x/JeGFyd7738Lt8iNTrzJw= cloud.google.com/go/networkconnectivity v1.16.1/go.mod h1:GBC1iOLkblcnhcnfRV92j4KzqGBrEI6tT7LP52nZCTk= +cloud.google.com/go/networkconnectivity v1.17.1/go.mod h1:DTZCq8POTkHgAlOAAEDQF3cMEr/B9k1ZbpklqvHEBtg= cloud.google.com/go/networkmanagement v1.8.0 h1:/3xP37eMxnyvkfLrsm1nv1b2FbMMSAEAOlECTvoeCq4= cloud.google.com/go/networkmanagement v1.9.0 h1:aA6L8aioyM4S6nlPYzp2SvB88lBcByZmqMJM6ReafzU= cloud.google.com/go/networkmanagement v1.9.1 h1:ZK6i6FVQNc1t3fecM3hf9Nu6Kr9C95xr+zMVORYd8ak= @@ -1322,6 +1390,7 @@ cloud.google.com/go/networkmanagement v1.15.0 h1:nWWsKVyK9gr2qX/z3+6C8wZ3PIX97Hd cloud.google.com/go/networkmanagement v1.15.0/go.mod h1:Yc905R9U5jik5YMt76QWdG5WqzPU4ZsdI/mLnVa62/Q= cloud.google.com/go/networkmanagement v1.18.0 h1:oEoFGPYxTBsY47h0zdoE2ojV5aU/541D83UmxfjHWaE= cloud.google.com/go/networkmanagement v1.18.0/go.mod h1:yTxpAFuvQOOKgL3W7+k2Rp1bSKTxyRcZ5xNHGdHUM6w= +cloud.google.com/go/networkmanagement v1.19.1/go.mod h1:icgk265dNnilxQzpr6rO9WuAuuCmUOqq9H6WBeM2Af4= cloud.google.com/go/networksecurity v0.9.1 h1:TBLEkMp3AE+6IV/wbIGRNTxnqLXHCTEQWoxRVC18TzY= cloud.google.com/go/networksecurity v0.9.2 h1:fA73AX//KWaqNKOvuQ00WUD3Z/XMhiMhHSFTEl2Wxec= cloud.google.com/go/networksecurity v0.9.4 h1:947tNIPnj1bMGTIEBo3fc4QrrFKS5hh0bFVsHmFm4Vo= @@ -1340,6 +1409,7 @@ cloud.google.com/go/networksecurity v0.10.2 h1://zFZM8XZZs+3Y6QKuLqwD5tZ+B/17KUo cloud.google.com/go/networksecurity v0.10.2/go.mod h1:puU3Gwchd6Y/VTyMkL50GI2RSRMS3KXhcDBY1HSOcck= cloud.google.com/go/networksecurity v0.10.3 h1:JLJBFbxc8D7/OS81MyRoKhc2OvnVJxy5VMoQqqAhA7k= cloud.google.com/go/networksecurity v0.10.3/go.mod h1:G85ABVcPscEgpw+gcu+HUxNZJWjn3yhTqEU7+SsltFM= +cloud.google.com/go/networksecurity v0.10.6/go.mod h1:FTZvabFPvK2kR/MRIH3l/OoQ/i53eSix2KA1vhBMJec= cloud.google.com/go/notebooks v1.9.1 h1:CUqMNEtv4EHFnbogV+yGHQH5iAQLmijOx191innpOcs= cloud.google.com/go/notebooks v1.10.0 h1:6x2K1JAWv6RW2yQO6oa+xtKUGOpGQseCmT94vpOt1vc= cloud.google.com/go/notebooks v1.10.1 h1:j/G3r6SPoWzD6CZZrDffZGwgGALvxWwtKJHJ4GF17WA= @@ -1359,6 +1429,7 @@ cloud.google.com/go/notebooks v1.12.2 h1:BHIH9kf/02wSCcLAVttEXHSFAgSotgRg2y1YjR7 cloud.google.com/go/notebooks v1.12.2/go.mod h1:EkLwv8zwr8DUXnvzl944+sRBG+b73HEKzV632YYAGNI= cloud.google.com/go/notebooks v1.12.3 h1:+9DrGJcZhCu6B2t0JJorekjIUBvg/KvBmXJYGmfvVvA= cloud.google.com/go/notebooks v1.12.3/go.mod h1:I0pMxZct+8Rega2LYrXL8jGAGZgLchSmh8Ksc+0xNyA= +cloud.google.com/go/notebooks v1.12.6/go.mod h1:3Z4TMEqAKP3pu6DI/U+aEXrNJw9hGZIVbp+l3zw8EuA= cloud.google.com/go/optimization v1.4.1 h1:pEwOAmO00mxdbesCRSsfj8Sd4rKY9kBrYW7Vd3Pq7cA= cloud.google.com/go/optimization v1.5.0 h1:sGvPVtBJUKNYAwldhJvFmnM+EEdOXjDzjcly3g0n0Xg= cloud.google.com/go/optimization v1.5.1 h1:71wTxJz8gRrVEHF4fw18sGynAyNQwatxCJBI3m3Rd4c= @@ -1378,6 +1449,7 @@ cloud.google.com/go/optimization v1.7.2 h1:yM4teRB60qyIm8cV4VRW4wepmHbXCoqv3QKGf cloud.google.com/go/optimization v1.7.2/go.mod h1:msYgDIh1SGSfq6/KiWJQ/uxMkWq8LekPyn1LAZ7ifNE= cloud.google.com/go/optimization v1.7.3 h1:JwQjjoBZJpsoMQe/3mhVBMVZuSdagHg2pGOnwh2Jk+E= cloud.google.com/go/optimization v1.7.3/go.mod h1:GlYFp4Mju0ybK5FlOUtV6zvWC00TIScdbsPyF6Iv144= +cloud.google.com/go/optimization v1.7.6/go.mod h1:4MeQslrSJGv+FY4rg0hnZBR/tBX2awJ1gXYp6jZpsYY= cloud.google.com/go/orchestration v1.8.1 h1:KmN18kE/xa1n91cM5jhCh7s1/UfIguSCisw7nTMUzgE= cloud.google.com/go/orchestration v1.8.2 h1:lb+Vphr+x2V9ukHwLjyaXJpbPuPhaKdobQx3UAOeSsQ= cloud.google.com/go/orchestration v1.8.4 h1:kgwZ2f6qMMYIVBtUGGoU8yjYWwMTHDanLwM/CQCFaoQ= @@ -1396,6 +1468,7 @@ cloud.google.com/go/orchestration v1.11.1 h1:uZOwdQoAamx8+X0UdMqY/lro3/h/Zhb7Snf cloud.google.com/go/orchestration v1.11.1/go.mod h1:RFHf4g88Lbx6oKhwFstYiId2avwb6oswGeAQ7Tjjtfw= cloud.google.com/go/orchestration v1.11.4 h1:SFAsKyqvtS8VFcsq+JgXAeRkrksB9UH+AH7iFamkmlc= cloud.google.com/go/orchestration v1.11.4/go.mod h1:UKR2JwogaZmDGnAcBgAQgCPn89QMqhXFUCYVhHd31vs= +cloud.google.com/go/orchestration v1.11.9/go.mod h1:KKXK67ROQaPt7AxUS1V/iK0Gs8yabn3bzJ1cLHw4XBg= cloud.google.com/go/orgpolicy v1.11.1 h1:I/7dHICQkNwym9erHqmlb50LRU588NPCvkfIY0Bx9jI= cloud.google.com/go/orgpolicy v1.11.2 h1:Dnfh5sj3aIAuJzH4Q4rBp6lCJ/IdXRBbwQ0/nQsUySE= cloud.google.com/go/orgpolicy v1.11.4 h1:RWuXQDr9GDYhjmrredQJC7aY7cbyqP9ZuLbq5GJGves= @@ -1415,6 +1488,7 @@ cloud.google.com/go/orgpolicy v1.14.1 h1:c1QLoM5v8/aDKgYVCUaC039lD3GPvqAhTVOwsGh cloud.google.com/go/orgpolicy v1.14.1/go.mod h1:1z08Hsu1mkoH839X7C8JmnrqOkp2IZRSxiDw7W/Xpg4= cloud.google.com/go/orgpolicy v1.14.2 h1:WFvgmjq/FO5GiXlhebltA9N14KdbLMcgG88ME+SWeBo= cloud.google.com/go/orgpolicy v1.14.2/go.mod h1:2fTDMT3X048iFKxc6DEgkG+a/gN+68qEgtPrHItKMzo= +cloud.google.com/go/orgpolicy v1.15.0/go.mod h1:NTQLwgS8N5cJtdfK55tAnMGtvPSsy95JJhESwYHaJVs= cloud.google.com/go/osconfig v1.12.1 h1:dgyEHdfqML6cUW6/MkihNdTVc0INQst0qSE8Ou1ub9c= cloud.google.com/go/osconfig v1.12.2 h1:AjHbw8MgKKaTFAEJWGdOYtMED3wUXKLtvdfP8Uzbuy0= cloud.google.com/go/osconfig v1.12.4 h1:OrRCIYEAbrbXdhm13/JINn9pQchvTTIzgmOCA7uJw8I= @@ -1433,6 +1507,7 @@ cloud.google.com/go/osconfig v1.14.2 h1:iBN87PQc+EGh5QqijM3CuxcibvDWmF+9k0eOJT27 cloud.google.com/go/osconfig v1.14.2/go.mod h1:kHtsm0/j8ubyuzGciBsRxFlbWVjc4c7KdrwJw0+g+pQ= cloud.google.com/go/osconfig v1.14.3 h1:cyf1PMK5c2/WOIr5r2lxjH/XBJMA9P4zC8Tm10i0z3M= cloud.google.com/go/osconfig v1.14.3/go.mod h1:9D2MS1Etne18r/mAeW5jtto3toc9H1qu9wLNDG3NvQg= +cloud.google.com/go/osconfig v1.14.5/go.mod h1:XH+NjBVat41I/+xgQzKOJEhuC4xI7lX2INE5SWnVr9U= cloud.google.com/go/oslogin v1.10.1 h1:LdSuG3xBYu2Sgr3jTUULL1XCl5QBx6xwzGqzoDUw1j0= cloud.google.com/go/oslogin v1.11.0 h1:7OA/BHWna8s+8k1sjTLHs0zRttoktR8a36qjWIvzTco= cloud.google.com/go/oslogin v1.11.1 h1:r3JYeLf004krfXhRMDfYKlBdMgDDc2q2PM1bomb5Luw= @@ -1453,6 +1528,7 @@ cloud.google.com/go/oslogin v1.14.2 h1:6ehIKkALrLe9zUHwEmfXRVuSPm3HiUmEnnDRr7yLI cloud.google.com/go/oslogin v1.14.2/go.mod h1:M7tAefCr6e9LFTrdWRQRrmMeKHbkvc4D9g6tHIjHySA= cloud.google.com/go/oslogin v1.14.3 h1:yomxnFPk+ye0zd0mJ15nn9fH4Ns7ex4xA3ll+u2q59A= cloud.google.com/go/oslogin v1.14.3/go.mod h1:fDEGODTG/W9ZGUTHTlMh8euXWC1fTcgjJ9Kcxxy14a8= +cloud.google.com/go/oslogin v1.14.6/go.mod h1:xEvcRZTkMXHfNSKdZ8adxD6wvRzeyAq3cQX3F3kbMRw= cloud.google.com/go/phishingprotection v0.8.1 h1:aK/lNmSd1vtbft/vLe2g7edXK72sIQbqr2QyrZN/iME= cloud.google.com/go/phishingprotection v0.8.2 h1:BIv/42ooQXh/jW8BW2cgO0E6yRPbEdvqH3JzKV7BlmI= cloud.google.com/go/phishingprotection v0.8.4 h1:sPLUQkHq6b4AL0czSJZ0jd6vL55GSTHz2B3Md+TCZI0= @@ -1471,6 +1547,7 @@ cloud.google.com/go/phishingprotection v0.9.2 h1:SaW0IPf/1fflnzomjy7+9EMtReXuxkY cloud.google.com/go/phishingprotection v0.9.2/go.mod h1:mSCiq3tD8fTJAuXq5QBHFKZqMUy8SfWsbUM9NpzJIRQ= cloud.google.com/go/phishingprotection v0.9.3 h1:T5mGFV0ggBKg3qt9myFRiGJu+nIUucuHLAtVpAuQ08I= cloud.google.com/go/phishingprotection v0.9.3/go.mod h1:ylzN9HruB/X7dD50I4sk+FfYzuPx9fm5JWsYI0t7ncc= +cloud.google.com/go/phishingprotection v0.9.6/go.mod h1:VmuGg03DCI0wRp/FLSvNyjFj+J8V7+uITgHjCD/x4RQ= cloud.google.com/go/policytroubleshooter v1.7.1 h1:AZ2n6dw6OnYpDZAUk6WK1drupzTWNMRk/uatXEIDAsU= cloud.google.com/go/policytroubleshooter v1.8.0 h1:XTMHy31yFmXgQg57CB3w9YQX8US7irxDX0Fl0VwlZyY= cloud.google.com/go/policytroubleshooter v1.9.0 h1:pT4qSiL5o0hBSWHDiOcmes/s301PeLLWEhAr/eMQB/g= @@ -1491,6 +1568,7 @@ cloud.google.com/go/policytroubleshooter v1.11.2 h1:sTIH5AQ8tcgmnqrqlZfYWymjMhPh cloud.google.com/go/policytroubleshooter v1.11.2/go.mod h1:1TdeCRv8Qsjcz2qC3wFltg/Mjga4HSpv8Tyr5rzvPsw= cloud.google.com/go/policytroubleshooter v1.11.3 h1:ekIWI8JbKkpOfrgH/THGamQE/D16tcVBYJyrkseVcYI= cloud.google.com/go/policytroubleshooter v1.11.3/go.mod h1:AFHlORqh4AnMC0twc2yPKfzlozp3DO0yo9OfOd9aNOs= +cloud.google.com/go/policytroubleshooter v1.11.6/go.mod h1:jdjYGIveoYolk38Dm2JjS5mPkn8IjVqPsDHccTMu3mY= cloud.google.com/go/privatecatalog v0.9.1 h1:B/18xGo+E0EMS9LOEQ0zXz7F2asMgmVgTYGSI89MHOA= cloud.google.com/go/privatecatalog v0.9.2 h1:gxL4Kn9IXt3tdIOpDPEDPI/kBBLVzaAX5wq6IbOYi8A= cloud.google.com/go/privatecatalog v0.9.4 h1:Vo10IpWKbNvc/z/QZPVXgCiwfjpWoZ/wbgful4Uh/4E= @@ -1509,6 +1587,7 @@ cloud.google.com/go/privatecatalog v0.10.2 h1:01RPfn8IL2//8UHAmImRraTFYM/3gAEiIx cloud.google.com/go/privatecatalog v0.10.2/go.mod h1:o124dHoxdbO50ImR3T4+x3GRwBSTf4XTn6AatP8MgsQ= cloud.google.com/go/privatecatalog v0.10.4 h1:fu2LABMi7CgZORQ2oNGbc0hoZ0FTqLkjGqIgAV/Kc7U= cloud.google.com/go/privatecatalog v0.10.4/go.mod h1:n/vXBT+Wq8B4nSRUJNDsmqla5BYjbVxOlHzS6PjiF+w= +cloud.google.com/go/privatecatalog v0.10.7/go.mod h1:Fo/PF/B6m4A9vUYt0nEF1xd0U6Kk19/Je3eZGrQ6l60= cloud.google.com/go/pubsub v1.32.0 h1:JOEkgEYBuUTHSyHS4TcqOFuWr+vD6qO/imsFqShUCp4= cloud.google.com/go/pubsub v1.33.0 h1:6SPCPvWav64tj0sVX/+npCBKhUi/UjJehy9op/V3p2g= cloud.google.com/go/pubsub v1.34.0 h1:ZtPbfwfi5rLaPeSvDC29fFoE20/tQvGrUS6kVJZJvkU= @@ -1528,6 +1607,7 @@ cloud.google.com/go/pubsub v1.45.1/go.mod h1:3bn7fTmzZFwaUjllitv1WlsNMkqBgGUb3Ud cloud.google.com/go/pubsub v1.45.3 h1:prYj8EEAAAwkp6WNoGTE4ahe0DgHoyJd5Pbop931zow= cloud.google.com/go/pubsub v1.45.3/go.mod h1:cGyloK/hXC4at7smAtxFnXprKEFTqmMXNNd9w+bd94Q= cloud.google.com/go/pubsub v1.47.0/go.mod h1:LaENesmga+2u0nDtLkIOILskxsfvn/BXX9Ak1NFxOs8= +cloud.google.com/go/pubsub v1.49.0/go.mod h1:K1FswTWP+C1tI/nfi3HQecoVeFvL4HUOB1tdaNXKhUY= cloud.google.com/go/pubsublite v1.8.1 h1:pX+idpWMIH30/K7c0epN6V703xpIcMXWRjKJsz0tYGY= cloud.google.com/go/pubsublite v1.8.2 h1:jLQozsEVr+c6tOU13vDugtnaBSUy/PD5zK6mhm+uF1Y= cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= @@ -1552,6 +1632,7 @@ cloud.google.com/go/recaptchaenterprise/v2 v2.18.0 h1:Y7gRe16QA6ZmaelveFq4+/Tv35 cloud.google.com/go/recaptchaenterprise/v2 v2.18.0/go.mod h1:vnbA2SpVPPwKeoFrCQxR+5a0JFRRytwBBG69Zj9pGfk= cloud.google.com/go/recaptchaenterprise/v2 v2.19.4 h1:T5YGzaXwTesHaPDNTAuU3neDwZEnfjce70zufPFUwno= cloud.google.com/go/recaptchaenterprise/v2 v2.19.4/go.mod h1:WaglfocMJGkqZVdXY/FVB7OhoVRONPS4uXqtNn6HfX0= +cloud.google.com/go/recaptchaenterprise/v2 v2.20.4/go.mod h1:3H8nb8j8N7Ss2eJ+zr+/H7gyorfzcxiDEtVBDvDjwDQ= cloud.google.com/go/recommendationengine v0.8.1 h1:nMr1OEVHuDambRn+/y4RmNAmnR/pXCuHtH0Y4tCgGRQ= cloud.google.com/go/recommendationengine v0.8.2 h1:odf0TZXtwoZ5kJaWBlaE9D0AV+WJLLs+/SRSuE4T/ds= cloud.google.com/go/recommendationengine v0.8.4 h1:JRiwe4hvu3auuh2hujiTc2qNgPPfVp+Q8KOpsXlEzKQ= @@ -1570,6 +1651,7 @@ cloud.google.com/go/recommendationengine v0.9.2 h1:RHVdmoNBdzgRJXI/3SV+GB5TTv/um cloud.google.com/go/recommendationengine v0.9.2/go.mod h1:DjGfWZJ68ZF5ZuNgoTVXgajFAG0yLt4CJOpC0aMK3yw= cloud.google.com/go/recommendationengine v0.9.3 h1:kBpcYPx4ys4lrDGKp4OhP2uy8h7UjlmLW/qoO5Xb2bY= cloud.google.com/go/recommendationengine v0.9.3/go.mod h1:QRnX5aM7DCvtqtSs7I0zay5Zfq3fzxqnsPbZF7pa1G8= +cloud.google.com/go/recommendationengine v0.9.6/go.mod h1:nZnjKJu1vvoxbmuRvLB5NwGuh6cDMMQdOLXTnkukUOE= cloud.google.com/go/recommender v1.10.1 h1:UKp94UH5/Lv2WXSQe9+FttqV07x/2p1hFTMMYVFtilg= cloud.google.com/go/recommender v1.11.0 h1:SuzbMJhDAiPro7tR9QP7EX97+TI31urjsIgNh9XQHl8= cloud.google.com/go/recommender v1.11.1 h1:GI4EBCMTLfC8I8R+e13ZaTAa8ZZ0KRPdS99hGtJYyaU= @@ -1590,6 +1672,7 @@ cloud.google.com/go/recommender v1.13.2 h1:xDFzlFk5Xp5MXnac468eicKM3MUo6UNdxoYuB cloud.google.com/go/recommender v1.13.2/go.mod h1:XJau4M5Re8F4BM+fzF3fqSjxNJuM66fwF68VCy/ngGE= cloud.google.com/go/recommender v1.13.3 h1:dVlOjxsbjuhlwu4MIcyPWe09qVcDqc419iOjdPl5RHk= cloud.google.com/go/recommender v1.13.3/go.mod h1:6yAmcfqJRKglZrVuTHsieTFEm4ai9JtY3nQzmX4TC0Q= +cloud.google.com/go/recommender v1.13.5/go.mod h1:v7x/fzk38oC62TsN5Qkdpn0eoMBh610UgArJtDIgH/E= cloud.google.com/go/redis v1.13.1 h1:YrjQnCC7ydk+k30op7DSjSHw1yAYhqYXFcOq1bSXRYA= cloud.google.com/go/redis v1.13.2 h1:2ZtIGspMT65wern2rjX35XPCCJxVKF4J0P1S99bac3k= cloud.google.com/go/redis v1.14.1 h1:J9cEHxG9YLmA9o4jTSvWt/RuVEn6MTrPlYSCRHujxDQ= @@ -1609,6 +1692,7 @@ cloud.google.com/go/redis v1.17.2/go.mod h1:h071xkcTMnJgQnU/zRMOVKNj5J6AttG16RDo cloud.google.com/go/redis v1.17.3 h1:ROQXi5dCDSJCVezt/2nD1g+Ym0T6sio3DIzZ56NgMZI= cloud.google.com/go/redis v1.17.3/go.mod h1:23OoThXAU5bvhg4/oKsEcdVfq3wmyTEPNA9FP/t9xGo= cloud.google.com/go/redis v1.18.0/go.mod h1:fJ8dEQJQ7DY+mJRMkSafxQCuc8nOyPUwo9tXJqjvNEY= +cloud.google.com/go/redis v1.18.2/go.mod h1:q6mPRhLiR2uLf584Lcl4tsiRn0xiFlu6fnJLwCORMtY= cloud.google.com/go/resourcemanager v1.9.1 h1:QIAMfndPOHR6yTmMUB0ZN+HSeRmPjR/21Smq5/xwghI= cloud.google.com/go/resourcemanager v1.9.2 h1:lC3PjJMHLPlZKqLfan6FkEb3X1F8oCRc1ylY7vRHvDQ= cloud.google.com/go/resourcemanager v1.9.4 h1:JwZ7Ggle54XQ/FVYSBrMLOQIKoIT/uer8mmNvNLK51k= @@ -1627,6 +1711,7 @@ cloud.google.com/go/resourcemanager v1.10.2 h1:LpqZZGM0uJiu1YWM878AA8zZ/qOQ/Ngno cloud.google.com/go/resourcemanager v1.10.2/go.mod h1:5f+4zTM/ZOTDm6MmPOp6BQAhR0fi8qFPnvVGSoWszcc= cloud.google.com/go/resourcemanager v1.10.3 h1:SHOMw0kX0xWratC5Vb5VULBeWiGlPYAs82kiZqNtWpM= cloud.google.com/go/resourcemanager v1.10.3/go.mod h1:JSQDy1JA3K7wtaFH23FBGld4dMtzqCoOpwY55XYR8gs= +cloud.google.com/go/resourcemanager v1.10.6/go.mod h1:VqMoDQ03W4yZmxzLPrB+RuAoVkHDS5tFUUQUhOtnRTg= cloud.google.com/go/resourcesettings v1.6.1 h1:Fdyq418U69LhvNPFdlEO29w+DRRjwDA4/pFamm4ksAg= cloud.google.com/go/resourcesettings v1.6.2 h1:feqx2EcLRgtmwNHzeLw5Og4Wcy4vcZxw62b0x/QNu60= cloud.google.com/go/resourcesettings v1.6.4 h1:yTIL2CsZswmMfFyx2Ic77oLVzfBFoWBYgpkgiSPnC4Y= @@ -1663,6 +1748,7 @@ cloud.google.com/go/retail v1.19.1 h1:FVzvA+VuEdNoMz2WzWZ5KwfG+CX+jSv+SOspyQPLuR cloud.google.com/go/retail v1.19.1/go.mod h1:W48zg0zmt2JMqmJKCuzx0/0XDLtovwzGAeJjmv6VPaE= cloud.google.com/go/retail v1.19.2 h1:PT6CUlazIFIOLLJnV+bPBtiSH8iusKZ+FZRzZYFt2vk= cloud.google.com/go/retail v1.19.2/go.mod h1:71tRFYAcR4MhrZ1YZzaJxr030LvaZiIcupH7bXfFBcY= +cloud.google.com/go/retail v1.20.0/go.mod h1:1CXWDZDJTOsK6lPjkv67gValP9+h1TMadTC9NpFFr9s= cloud.google.com/go/run v1.2.0 h1:kHeIG8q+N6Zv0nDkBjSOYfK2eWqa5FnaiDPH/7/HirE= cloud.google.com/go/run v1.3.0 h1:NR3ibstYygrvNZQ+7+rSWmD+oKvbjB/B9Ve9mqhkj6s= cloud.google.com/go/run v1.3.1 h1:xc46W9kxJI2De9hmpqHEBSSLJhP3bSZl86LdlJa5zm8= @@ -1683,6 +1769,7 @@ cloud.google.com/go/run v1.6.1/go.mod h1:IvJOg2TBb/5a0Qkc6crn5yTy5nkjcgSWQLhgO8Q cloud.google.com/go/run v1.8.1 h1:aeVLygw0BGLH+Zbj8v3K3nEHvKlgoq+j8fcRJaYZtxY= cloud.google.com/go/run v1.8.1/go.mod h1:wR5IG8Nujk9pyyNai187K4p8jzSLeqCKCAFBrZ2Sd4c= cloud.google.com/go/run v1.9.0/go.mod h1:Dh0+mizUbtBOpPEzeXMM22t8qYQpyWpfmUiWQ0+94DU= +cloud.google.com/go/run v1.9.3/go.mod h1:Si9yDIkUGr5vsXE2QVSWFmAjJkv/O8s3tJ1eTxw3p1o= cloud.google.com/go/scheduler v1.10.1 h1:yoZbZR8880KgPGLmACOMCiY2tPk+iX4V/dkxqTirlz8= cloud.google.com/go/scheduler v1.10.2 h1:lgUd1D84JEgNzzHRlcZEIoQ6Ny10YWe8RNH1knhouNk= cloud.google.com/go/scheduler v1.10.4 h1:LXm6L6IYW3Fy8lxU7kvT7r6JiW/noxn2gItJmsvwzV4= @@ -1703,6 +1790,7 @@ cloud.google.com/go/scheduler v1.11.2/go.mod h1:GZSv76T+KTssX2I9WukIYQuQRf7jk1WI cloud.google.com/go/scheduler v1.11.3 h1:p6+h8BoYJC+TvUijGBfORN6nuhOvJ3EwZ2H84CZ1ZEU= cloud.google.com/go/scheduler v1.11.3/go.mod h1:Io2+gcvUjLX1GdymwaSPJ6ZYxHN9/NNGL5kIV3Ax5+Q= cloud.google.com/go/scheduler v1.11.4/go.mod h1:0ylvH3syJnRi8EDVo9ETHW/vzpITR/b+XNnoF+GPSz4= +cloud.google.com/go/scheduler v1.11.7/go.mod h1:gqYs8ndLx2M5D0oMJh48aGS630YYvC432tHCnVWN13s= cloud.google.com/go/secretmanager v1.11.1 h1:cLTCwAjFh9fKvU6F13Y4L9vPcx9yiWPyWXE4+zkuEQs= cloud.google.com/go/secretmanager v1.11.2 h1:52Z78hH8NBWIqbvIG0wi0EoTaAmSx99KIOAmDXIlX0M= cloud.google.com/go/secretmanager v1.11.4 h1:krnX9qpG2kR2fJ+u+uNyNo+ACVhplIAS4Pu7u+4gd+k= @@ -1722,6 +1810,7 @@ cloud.google.com/go/secretmanager v1.14.2/go.mod h1:Q18wAPMM6RXLC/zVpWTlqq2IBSbb cloud.google.com/go/secretmanager v1.14.3 h1:XVGHbcXEsbrgi4XHzgK5np81l1eO7O72WOXHhXUemrM= cloud.google.com/go/secretmanager v1.14.3/go.mod h1:Pwzcfn69Ni9Lrk1/XBzo1H9+MCJwJ6CDCoeoQUsMN+c= cloud.google.com/go/secretmanager v1.14.5/go.mod h1:GXznZF3qqPZDGZQqETZwZqHw4R6KCaYVvcGiRBA+aqY= +cloud.google.com/go/secretmanager v1.14.7/go.mod h1:uRuB4F6NTFbg0vLQ6HsT7PSsfbY7FqHbtJP1J94qxGc= cloud.google.com/go/security v1.15.1 h1:jR3itwycg/TgGA0uIgTItcVhA55hKWiNJxaNNpQJaZE= cloud.google.com/go/security v1.15.2 h1:VNpdJNfMeHSJZ+647QtzPrvZ6rWChBklLm/NY64RVW8= cloud.google.com/go/security v1.15.4 h1:sdnh4Islb1ljaNhpIXlIPgb3eYj70QWgPVDKOUYvzJc= @@ -1740,6 +1829,7 @@ cloud.google.com/go/security v1.18.2 h1:9Nzp9LGjiDvHqy7X7Q9GrS5lIHN0bI8RvDjkrl4I cloud.google.com/go/security v1.18.2/go.mod h1:3EwTcYw8554iEtgK8VxAjZaq2unFehcsgFIF9nOvQmU= cloud.google.com/go/security v1.18.3 h1:ya9gfY1ign6Yy25VMMMgZ9xy7D/TczDB0ElXcyWmEVE= cloud.google.com/go/security v1.18.3/go.mod h1:NmlSnEe7vzenMRoTLehUwa/ZTZHDQE59IPRevHcpCe4= +cloud.google.com/go/security v1.18.5/go.mod h1:D1wuUkDwGqTKD0Nv7d4Fn2Dc53POJSmO4tlg1K1iS7s= cloud.google.com/go/securitycenter v1.23.0 h1:XOGJ9OpnDtqg8izd7gYk/XUhj8ytjIalyjjsR6oyG0M= cloud.google.com/go/securitycenter v1.23.1 h1:Epx7Gm9ZRPRiFfwDFplka2zKCS0J3cpm0Et1KwI2tvY= cloud.google.com/go/securitycenter v1.24.2 h1:qCEyXoJoxNKKA1bDywBjjqCB7ODXazzHnVWnG5Uqd1M= @@ -1760,6 +1850,7 @@ cloud.google.com/go/securitycenter v1.35.2/go.mod h1:AVM2V9CJvaWGZRHf3eG+LeSTSis cloud.google.com/go/securitycenter v1.35.3 h1:H8UvBpcvs1OjI4jZuXX8xsN1IZo88a9PezHXkU2sGps= cloud.google.com/go/securitycenter v1.35.3/go.mod h1:kjsA8Eg4jlMHW1JwxbMC8148I+gcjgkWPdbDycatoRQ= cloud.google.com/go/securitycenter v1.36.0/go.mod h1:AErAQqIvrSrk8cpiItJG1+ATl7SD7vQ6lgTFy/Tcs4Q= +cloud.google.com/go/securitycenter v1.36.2/go.mod h1:80ocoXS4SNWxmpqeEPhttYrmlQzCPVGaPzL3wVcoJvE= cloud.google.com/go/servicecontrol v1.5.0 h1:ImIzbOu6y4jL6ob65I++QzvqgFaoAKgHOG+RU9/c4y8= cloud.google.com/go/servicecontrol v1.11.1 h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE= cloud.google.com/go/servicedirectory v1.10.1 h1:J/0csas97yAQ+dcc7i8HqbaOA4KOfPu7BPhJdxYRhCk= @@ -1781,6 +1872,7 @@ cloud.google.com/go/servicedirectory v1.12.2 h1:W/oZmTUzlWbeSTujRbmG9v7HZyHcorj6 cloud.google.com/go/servicedirectory v1.12.2/go.mod h1:F0TJdFjqqotiZRlMXgIOzszaplk4ZAmUV8ovHo08M2U= cloud.google.com/go/servicedirectory v1.12.3 h1:oFkCp6ti7fc7hzeROmOPQuPBHFqwyhcsv3Yrma28+uc= cloud.google.com/go/servicedirectory v1.12.3/go.mod h1:dwTKSCYRD6IZMrqoBCIvZek+aOYK/6+jBzOGw8ks5aY= +cloud.google.com/go/servicedirectory v1.12.6/go.mod h1:OojC1KhOMDYC45oyTn3Mup08FY/S0Kj7I58dxUMMTpg= cloud.google.com/go/servicemanagement v1.5.0 h1:TpkCO5M7dhKSy1bKUD9o/sSEW/U1Gtx7opA1fsiMx0c= cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY= cloud.google.com/go/serviceusage v1.4.0 h1:b0EwJxPJLpavSljMQh0RcdHsUrr5DQ+Nelt/3BAs5ro= @@ -1803,6 +1895,7 @@ cloud.google.com/go/shell v1.8.2 h1:lSfdEng3n7zZHzC40BJ4trEMyme3CGnLLnA09MlLQdQ= cloud.google.com/go/shell v1.8.2/go.mod h1:QQR12T6j/eKvqAQLv6R3ozeoqwJ0euaFSz2qLqG93Bs= cloud.google.com/go/shell v1.8.3 h1:mjYgUsOtV3jl9xvDmcvlRRmA64deEPf52zOfuc68b/g= cloud.google.com/go/shell v1.8.3/go.mod h1:OYcrgWF6JSp/uk76sNTtYFlMD0ho2+Cdzc7U3P/bF54= +cloud.google.com/go/shell v1.8.6/go.mod h1:GNbTWf1QA/eEtYa+kWSr+ef/XTCDkUzRpV3JPw0LqSk= cloud.google.com/go/speech v1.17.1 h1:KIV99afoYTJqA2qi8Cjbl5DpjSRzvqFgKcptGXg6kxw= cloud.google.com/go/speech v1.19.0 h1:MCagaq8ObV2tr1kZJcJYgXYbIn8Ai5rp42tyGYw9rls= cloud.google.com/go/speech v1.19.1 h1:z035FMLs98jpnqcP5xZZ6Es+g6utbeVoUH64BaTzTSU= @@ -1823,6 +1916,7 @@ cloud.google.com/go/speech v1.25.2 h1:rKOXU9LAZTOYHhRNB4gZDekNjJx21TktQpetBa5IzO cloud.google.com/go/speech v1.25.2/go.mod h1:KPFirZlLL8SqPaTtG6l+HHIFHPipjbemv4iFg7rTlYs= cloud.google.com/go/speech v1.26.0 h1:qvURtJs7BQzQhbxWxwai0pT79S8KLVKJ/4W8igVkt1Y= cloud.google.com/go/speech v1.26.0/go.mod h1:78bqDV2SgwFlP/M4n3i3PwLthFq6ta7qmyG6lUV7UCA= +cloud.google.com/go/speech v1.27.1/go.mod h1:efCfklHFL4Flxcdt9gpEMEJh9MupaBzw3QiSOVeJ6ck= cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= @@ -1836,6 +1930,7 @@ cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyX cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs= cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY= +cloud.google.com/go/storage v1.53.0/go.mod h1:7/eO2a/srr9ImZW9k5uufcNahT2+fPb8w5it1i5boaA= cloud.google.com/go/storagetransfer v1.10.0 h1:+ZLkeXx0K0Pk5XdDmG0MnUVqIR18lllsihU/yq39I8Q= cloud.google.com/go/storagetransfer v1.10.1 h1:CU03oYLauu7xRV25fFmozHZHA/SokLQlC20Ip/UvFro= cloud.google.com/go/storagetransfer v1.10.3 h1:YM1dnj5gLjfL6aDldO2s4GeU8JoAvH1xyIwXre63KmI= @@ -1854,6 +1949,7 @@ cloud.google.com/go/storagetransfer v1.11.2 h1:hMcP8ECmxedXjPxr2j3Ca45ro/TKEF+1Y cloud.google.com/go/storagetransfer v1.11.2/go.mod h1:FcM29aY4EyZ3yVPmW5SxhqUdhjgPBUOFyy4rqiQbias= cloud.google.com/go/storagetransfer v1.12.1 h1:W3v9A7MGBN7H9sAFstyciwP/1XEQhUhZfrjclmDnpMs= cloud.google.com/go/storagetransfer v1.12.1/go.mod h1:hQqbfs8/LTmObJyCC0KrlBw8yBJ2bSFlaGila0qBMk4= +cloud.google.com/go/storagetransfer v1.12.4/go.mod h1:p1xLKvpt78aQFRJ8lZGYArgFuL4wljFzitPZoYjl/8A= cloud.google.com/go/talent v1.6.2 h1:j46ZgD6N2YdpFPux9mc7OAf4YK3tiBCsbLKc8rQx+bU= cloud.google.com/go/talent v1.6.3 h1:TyJqwhmncdW5CL4rzYSYKJrR9YAe0iNqHtJTnnOaEyM= cloud.google.com/go/talent v1.6.5 h1:LnRJhhYkODDBoTwf6BeYkiJHFw9k+1mAFNyArwZUZAs= @@ -1872,6 +1968,7 @@ cloud.google.com/go/talent v1.7.2 h1:KONR7KX/EXI3pO2cbSIDOBqhBzvgDS71vaMz8k4qRCg cloud.google.com/go/talent v1.7.2/go.mod h1:k1sqlDgS9gbc0gMTRuRQpX6C6VB7bGUxSPcoTRWJod8= cloud.google.com/go/talent v1.8.0 h1:olv+s2g+LGXeJi+MYF1wI44/TwHaVnO0N7PiucVf5ZQ= cloud.google.com/go/talent v1.8.0/go.mod h1:/gvOzSrtMcfTL/9xWhdYaZATaxUNhQ+L+3ZaGOGs7bA= +cloud.google.com/go/talent v1.8.3/go.mod h1:oD3/BilJpJX8/ad8ZUAxlXHCslTg2YBbafFH3ciZSLQ= cloud.google.com/go/texttospeech v1.7.1 h1:S/pR/GZT9p15R7Y2dk2OXD/3AufTct/NSxT4a7nxByw= cloud.google.com/go/texttospeech v1.7.2 h1:Ac53sRkUo8UMSuhyyWRFJvWEaX8vm0EFwwiTAxeVYuU= cloud.google.com/go/texttospeech v1.7.4 h1:ahrzTgr7uAbvebuhkBAAVU6kRwVD0HWsmDsvMhtad5Q= @@ -1890,6 +1987,7 @@ cloud.google.com/go/texttospeech v1.10.0 h1:icRAxYDtq3zO1T0YBT/fe8C/7pXoIqfkY4iY cloud.google.com/go/texttospeech v1.10.0/go.mod h1:215FpCOyRxxrS7DSb2t7f4ylMz8dXsQg8+Vdup5IhP4= cloud.google.com/go/texttospeech v1.11.0 h1:YF/RdNb+jUEp22cIZCvqiFjfA5OxGE+Dxss3mhXU7oQ= cloud.google.com/go/texttospeech v1.11.0/go.mod h1:7M2ro3I2QfIEvArFk1TJ+pqXJqhszDtxUpnIv/150As= +cloud.google.com/go/texttospeech v1.12.1/go.mod h1:f8vrD3OXAKTRr4eL0TPjZgYQhiN6ti/tKM3i1Uub5X0= cloud.google.com/go/tpu v1.6.1 h1:kQf1jgPY04UJBYYjNUO+3GrZtIb57MfGAW2bwgLbR3A= cloud.google.com/go/tpu v1.6.2 h1:SAFzyGp6mU37lfLTV0cNQwu7tqH4X8b4RCpQZ1s+mYM= cloud.google.com/go/tpu v1.6.4 h1:XIEH5c0WeYGaVy9H+UueiTaf3NI6XNdB4/v6TFQJxtE= @@ -1908,6 +2006,7 @@ cloud.google.com/go/tpu v1.7.2 h1:xPBJd7xZgtl3CgrZoaUf7zFPVVj68jmzzGTSzkcsOtQ= cloud.google.com/go/tpu v1.7.2/go.mod h1:0Y7dUo2LIbDUx0yQ/vnLC6e18FK6NrDfAhYS9wZ/2vs= cloud.google.com/go/tpu v1.8.0 h1:BvMNijOb6Vd46Rr/SR5jWv1MPosOhVsi0UaeAGNjeds= cloud.google.com/go/tpu v1.8.0/go.mod h1:XyNzyK1xc55WvL5rZEML0Z9/TUHDfnq0uICkQw6rWMo= +cloud.google.com/go/tpu v1.8.3/go.mod h1:Do6Gq+/Jx6Xs3LcY2WhHyGwKDKVw++9jIJp+X+0rxRE= cloud.google.com/go/trace v1.10.1 h1:EwGdOLCNfYOOPtgqo+D2sDLZmRCEO1AagRTJCU6ztdg= cloud.google.com/go/trace v1.10.2 h1:80Rh4JSqJLfe/xGNrpyO4MQxiFDXcHG1XrsevfmrIRQ= cloud.google.com/go/trace v1.10.4 h1:2qOAuAzNezwW3QN+t41BtkDJOG42HywL73q8x/f6fnM= @@ -1926,6 +2025,7 @@ cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= +cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= cloud.google.com/go/translate v1.8.1 h1:7P75urEfnR/gU+7oYn5GuMsV9tJAiBGLJv06G10mM/E= cloud.google.com/go/translate v1.8.2 h1:PQHamiOzlehqLBJMnM72lXk/OsMQewZB12BKJ8zXrU0= cloud.google.com/go/translate v1.9.0 h1:0na4gC54Lu05ir00dmUSuMkLAojDe1ALq4hBTUkhwjE= @@ -1947,6 +2047,7 @@ cloud.google.com/go/translate v1.12.2 h1:qECivi8O+jFI/vnvN9elK6CME+WAWy56GIBszF+ cloud.google.com/go/translate v1.12.2/go.mod h1:jjLVf2SVH2uD+BNM40DYvRRKSsuyKxVvs3YjTW/XSWY= cloud.google.com/go/translate v1.12.3 h1:XJ7LipYJi80BCgVk2lx1fwc7DIYM6oV2qx1G4IAGQ5w= cloud.google.com/go/translate v1.12.3/go.mod h1:qINOVpgmgBnY4YTFHdfVO4nLrSBlpvlIyosqpGEgyEg= +cloud.google.com/go/translate v1.12.5/go.mod h1:o/v+QG/bdtBV1d1edmtau0PwTfActvxPk/gtqdSDBi4= cloud.google.com/go/video v1.17.1 h1:gWi0caJILQb9VwZPq28R1Wrg5YMsoLIvtvKDSglcQL8= cloud.google.com/go/video v1.19.0 h1:BRyyS+wU+Do6VOXnb8WfPr42ZXti9hzmLKLUCkggeK4= cloud.google.com/go/video v1.20.0 h1:AkjXyJfQ7DtPyDOAbTMeiGcuKsO8/iKSb3fAmTUHYSg= @@ -1967,6 +2068,7 @@ cloud.google.com/go/video v1.23.2 h1:CGAPOXTJMoZm9PeHkohBlMTy8lqN6VWCNDjp5VODfy8 cloud.google.com/go/video v1.23.2/go.mod h1:rNOr2pPHWeCbW0QsOwJRIe0ZiuwHpHtumK0xbiYB1Ew= cloud.google.com/go/video v1.23.3 h1:C2FH+6yr6LCZC4fP0gm9FwJB/SRh5Ul88O5Sc/bL83I= cloud.google.com/go/video v1.23.3/go.mod h1:Kvh/BheubZxGZDXSb0iO6YX7ZNcaYHbLjnnaC8Qyy3g= +cloud.google.com/go/video v1.23.5/go.mod h1:ZSpGFCpfTOTmb1IkmHNGC/9yI3TjIa/vkkOKBDo0Vpo= cloud.google.com/go/videointelligence v1.11.1 h1:MBMWnkQ78GQnRz5lfdTAbBq/8QMCF3wahgtHh3s/J+k= cloud.google.com/go/videointelligence v1.11.2 h1:vAKuM4YHwZy1W5P7hGJdfXriovqHHUZKhDBq8o4nqfg= cloud.google.com/go/videointelligence v1.11.4 h1:YS4j7lY0zxYyneTFXjBJUj2r4CFe/UoIi/PJG0Zt/Rg= @@ -1985,6 +2087,7 @@ cloud.google.com/go/videointelligence v1.12.2 h1:ZLElysepw9vfQGAKWfnxdnSnHSKbEn/ cloud.google.com/go/videointelligence v1.12.2/go.mod h1:8xKGlq0lNVyT8JgTkkCUCpyNJnYYEJVWGdqzv+UcwR8= cloud.google.com/go/videointelligence v1.12.3 h1:zNTOUQyatGQtnCJ2dR3faRtpWQOlC8wszJqwG5CtwVM= cloud.google.com/go/videointelligence v1.12.3/go.mod h1:dUA6V+NH7CVgX6TePq0IelVeBMGzvehxKPR4FGf1dtw= +cloud.google.com/go/videointelligence v1.12.6/go.mod h1:/l34WMndN5/bt04lHodxiYchLVuWPQjCU6SaiTswrIw= cloud.google.com/go/vision v1.2.0 h1:/CsSTkbmO9HC8iQpxbK8ATms3OQaX3YQUeTMGCxlaK4= cloud.google.com/go/vision/v2 v2.7.2 h1:ccK6/YgPfGHR/CyESz1mvIbsht5Y2xRsWCPqmTNydEw= cloud.google.com/go/vision/v2 v2.7.3 h1:o8iiH4UsI6O8wO2Ax2r88fLG1RzYQIFevUQY7hXPZeM= @@ -2004,6 +2107,7 @@ cloud.google.com/go/vision/v2 v2.9.2 h1:u4pu3gKps88oUe76WwVPeX9dgWVyyYopZ1s05Fws cloud.google.com/go/vision/v2 v2.9.2/go.mod h1:WuxjVQdAy4j4WZqY5Rr655EdAgi8B707Vdb5T8c90uo= cloud.google.com/go/vision/v2 v2.9.3 h1:dPvfDuPqPH+Yscf0f2f1RprvKkoo+N/j0a+IbLYX7Cs= cloud.google.com/go/vision/v2 v2.9.3/go.mod h1:weAcT8aNYSgrWWVTC2PuJTc7fcXKvUeAyDq8B6HkLSg= +cloud.google.com/go/vision/v2 v2.9.5/go.mod h1:1SiNZPpypqZDbOzU052ZYRiyKjwOcyqgGgqQCI/nlx8= cloud.google.com/go/vmmigration v1.7.1 h1:gnjIclgqbEMc+cF5IJuPxp53wjBIlqZ8h9hE8Rkwp7A= cloud.google.com/go/vmmigration v1.7.2 h1:ObE8VWzL+xkU22IsPEMvPCWArnSQ85dEwR5fzgaOvA4= cloud.google.com/go/vmmigration v1.7.4 h1:qPNdab4aGgtaRX+51jCOtJxlJp6P26qua4o1xxUDjpc= @@ -2022,6 +2126,7 @@ cloud.google.com/go/vmmigration v1.8.2 h1:Hpqv3fZ3Ri1OMhTNVJgxxsTou2ZlRzKbnc1dSy cloud.google.com/go/vmmigration v1.8.2/go.mod h1:FBejrsr8ZHmJb949BSOyr3D+/yCp9z9Hk0WtsTiHc1Q= cloud.google.com/go/vmmigration v1.8.3 h1:dpCQq3pj2HnKdbvGTftdWymm3r4ovF7JW5z8xBcO2x4= cloud.google.com/go/vmmigration v1.8.3/go.mod h1:8CzUpK9eBzohgpL4RvBVtW4sY/sDliVyQonTFQfWcJ4= +cloud.google.com/go/vmmigration v1.8.6/go.mod h1:uZ6/KXmekwK3JmC8PzBM/cKQmq404TTfWtThF6bbf0U= cloud.google.com/go/vmwareengine v0.4.1 h1:roQrCAkaysVvXxFMuK26lORi+gablOY54htDtDDow0w= cloud.google.com/go/vmwareengine v1.0.0 h1:qsJ0CPlOQu/3MFBGklu752v3AkD+Pdu091UmXJ+EjTA= cloud.google.com/go/vmwareengine v1.0.1 h1:Bj9WECvQk1fkx8IG7gqII3+g1CzhqkPOV84WXvifpFg= @@ -2041,6 +2146,7 @@ cloud.google.com/go/vmwareengine v1.3.2 h1:LmkojgSLvsRwU1+c0iiY2XoBkXYKzpArElHC9 cloud.google.com/go/vmwareengine v1.3.2/go.mod h1:JsheEadzT0nfXOGkdnwtS1FhFAnj4g8qhi4rKeLi/AU= cloud.google.com/go/vmwareengine v1.3.3 h1:TfuQr5j7qriINulUMotaC/+27SQaW2thIkF3Gb6VJ38= cloud.google.com/go/vmwareengine v1.3.3/go.mod h1:G7vz05KGijha0c0dj1INRKyDAaQW8TRMZt/FrfOZVXc= +cloud.google.com/go/vmwareengine v1.3.5/go.mod h1:QuVu2/b/eo8zcIkxBYY5QSwiyEcAy6dInI7N+keI+Jg= cloud.google.com/go/vpcaccess v1.7.1 h1:ram0GzjNWElmbxXMIzeOZUkQ9J8ZAahD6V8ilPGqX0Y= cloud.google.com/go/vpcaccess v1.7.2 h1:3qKiWvzK07eIa943mCvkcZB4gimxaQKKGdNoX01ps7A= cloud.google.com/go/vpcaccess v1.7.4 h1:zbs3V+9ux45KYq8lxxn/wgXole6SlBHHKKyZhNJoS+8= @@ -2059,6 +2165,7 @@ cloud.google.com/go/vpcaccess v1.8.2 h1:nvrkqAjS2sorOu4YGCIXWz+Kk+5aAAdnaMD2tnsq cloud.google.com/go/vpcaccess v1.8.2/go.mod h1:4yvYKNjlNjvk/ffgZ0PuEhpzNJb8HybSM1otG2aDxnY= cloud.google.com/go/vpcaccess v1.8.3 h1:vxVaoFM64M/ht619c4wZNF0iq0QPaMWElOh7Ns4r41A= cloud.google.com/go/vpcaccess v1.8.3/go.mod h1:bqOhyeSh/nEmLIsIUoCiQCBHeNPNjaK9M3bIvKxFdsY= +cloud.google.com/go/vpcaccess v1.8.6/go.mod h1:61yymNplV1hAbo8+kBOFO7Vs+4ZHYI244rSFgmsHC6E= cloud.google.com/go/webrisk v1.9.1 h1:Ssy3MkOMOnyRV5H2bkMQ13Umv7CwB/kugo3qkAX83Fk= cloud.google.com/go/webrisk v1.9.2 h1:1NZppagzdGO0hVMJsUhZQ5a3Iu2cNyNObu85VFcvIVA= cloud.google.com/go/webrisk v1.9.4 h1:iceR3k0BCRZgf2D/NiKviVMFfuNC9LmeNLtxUFRB/wI= @@ -2077,6 +2184,7 @@ cloud.google.com/go/webrisk v1.10.2 h1:X7zSwS1mX2bxoZ30Ozh6lqiSLezl7RMBWwp5a3Mkx cloud.google.com/go/webrisk v1.10.2/go.mod h1:c0ODT2+CuKCYjaeHO7b0ni4CUrJ95ScP5UFl9061Qq8= cloud.google.com/go/webrisk v1.10.3 h1:yh0v/5n49VO4/i9pYfDm1gLJUj1Ph3Xzegn8WvK9YRA= cloud.google.com/go/webrisk v1.10.3/go.mod h1:rRAqCA5/EQOX8ZEEF4HMIrLHGTK/Y1hEQgWMnih+jAw= +cloud.google.com/go/webrisk v1.11.1/go.mod h1:+9SaepGg2lcp1p0pXuHyz3R2Yi2fHKKb4c1Q9y0qbtA= cloud.google.com/go/websecurityscanner v1.6.1 h1:CfEF/vZ+xXyAR3zC9iaC/QRdf1MEgS20r5UR17Q4gOg= cloud.google.com/go/websecurityscanner v1.6.2 h1:V7PhbJ2OvpGHINL67RBhpwU3+g4MOoqOeL/sFYrogeE= cloud.google.com/go/websecurityscanner v1.6.4 h1:5Gp7h5j7jywxLUp6NTpjNPkgZb3ngl0tUSw6ICWvtJQ= @@ -2095,6 +2203,7 @@ cloud.google.com/go/websecurityscanner v1.7.2 h1:8/4rfJXcyxozbfzI0lDFPcPShRE6bJ4 cloud.google.com/go/websecurityscanner v1.7.2/go.mod h1:728wF9yz2VCErfBaACA5px2XSYHQgkK812NmHcUsDXA= cloud.google.com/go/websecurityscanner v1.7.3 h1:/uxhVCWKXzPw5pVfnBOVjaSiQ6Bm0tDExDOCLV40thw= cloud.google.com/go/websecurityscanner v1.7.3/go.mod h1:gy0Kmct4GNLoCePWs9xkQym1D7D59ld5AjhXrjipxSs= +cloud.google.com/go/websecurityscanner v1.7.6/go.mod h1:ucaaTO5JESFn5f2pjdX01wGbQ8D6h79KHrmO2uGZeiY= cloud.google.com/go/workflows v1.11.1 h1:2akeQ/PgtRhrNuD/n1WvJd5zb7YyuDZrlOanBj2ihPg= cloud.google.com/go/workflows v1.12.0 h1:cSUlx4PVV9O0vYCl+pHAUmu0996A7eN602d4wjjVHRs= cloud.google.com/go/workflows v1.12.1 h1:jvhSfcfAoOt0nILm7aZPJAHdpoe571qrJyc2ZlngaJk= @@ -2114,17 +2223,21 @@ cloud.google.com/go/workflows v1.13.2 h1:jYIxrDOVCGvTBHIAVhqQ+P8fhE0trm+Hf2hgL1Y cloud.google.com/go/workflows v1.13.2/go.mod h1:l5Wj2Eibqba4BsADIRzPLaevLmIuYF2W+wfFBkRG3vU= cloud.google.com/go/workflows v1.13.3 h1:lNFDMranJymDEB7cTI7DI9czbc1WU0RWY9KCEv9zuDY= cloud.google.com/go/workflows v1.13.3/go.mod h1:Xi7wggEt/ljoEcyk+CB/Oa1AHBCk0T1f5UH/exBB5CE= +cloud.google.com/go/workflows v1.14.2/go.mod h1:5nqKjMD+MsJs41sJhdVrETgvD5cOK3hUcAs8ygqYvXQ= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= gioui.org v0.0.0-20210308172011-57750fc8a0a6 h1:K72hopUosKG3ntOPNG4OzzbuhxGuVf06fa2la1/H/Ho= git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= +github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0/go.mod h1:6fTWu4m3jocfUZLYF5KsZC1TUfRvEjs7lM4crme/irw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0/go.mod h1:ZV4VOm0/eHR06JLrXWe09068dHpr3TRpY9Uo7T+anuA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -2166,6 +2279,7 @@ github.com/authzed/cel-go v0.17.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjul github.com/authzed/cel-go v0.17.3/go.mod h1:XL/zEq5hKGVF8aOdMbG7w+BQPihLjY2W8N+UIygDA2I= github.com/authzed/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ= github.com/authzed/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/bazelbuild/rules_go v0.49.0 h1:5vCbuvy8Q11g41lseGJDc5vxhDjJtfxr6nM/IC4VmqM= github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -2183,6 +2297,8 @@ github.com/bufbuild/protovalidate-go v0.9.1/go.mod h1:5jptBxfvlY51RhX32zR6875JfP github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= @@ -2289,6 +2405,7 @@ github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5 github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= +github.com/golangci/golangci-lint v1.64.8/go.mod h1:5cEsUQBSr6zi8XI8OjmcY2Xmliqc4iYL7YoPrL+zLJ4= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -2303,6 +2420,7 @@ github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/cel-go v0.23.0 h1:knsnzeUOcREUFo0ZFJqZI8Rk6uEVyobAlir7GEbf5v0= github.com/google/cel-go v0.23.0/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo= +github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI= github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= github.com/google/generative-ai-go v0.17.0 h1:kUmCXUIwJouD7I7ev3OmxzzQVICyhIWAxaXk2yblCMY= @@ -2311,12 +2429,14 @@ github.com/google/generative-ai-go v0.18.0 h1:6ybg9vOCLcI/UpBBYXOTVgvKmcUKFRNj+2 github.com/google/generative-ai-go v0.18.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg= github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= +github.com/google/generative-ai-go v0.20.1/go.mod h1:TjOnZJmZKzarWbjUJgy+r3Ee7HGBRVLhOIgupnwR4Bg= github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= github.com/google/go-pkcs11 v0.2.0 h1:5meDPB26aJ98f+K9G21f0AqZwo/S5BJMJh8nuhMbdsI= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9 h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk= github.com/google/go-pkcs11 v0.3.0 h1:PVRnTgtArZ3QQqTGtbtjtnIkzl2iY2kt24yqbrf7td8= github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= @@ -2389,6 +2509,7 @@ github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwg github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0= github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/dots v1.0.0/go.mod h1:rykuMydC9t3wfkM+ccYH3U3ss03vZGg6h3hmOznXLH0= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= @@ -2427,6 +2548,7 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -2502,6 +2624,7 @@ github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0Zqm github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/shirou/gopsutil/v4 v4.25.2 h1:NMscG3l2CqtWFS86kj3vP7soOczqrQYIEhO/pMvvQkk= github.com/shirou/gopsutil/v4 v4.25.2/go.mod h1:34gBYJzyqCDT11b6bMHP0XCvWeU3J61XRT7a2EmCRTA= +github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= @@ -2510,6 +2633,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -2588,6 +2712,7 @@ golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= @@ -2599,6 +2724,7 @@ golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6 h1:4WsZyVtkthqrHTbDCJfiTs8IWNYE4uvsSDgaV6xpp+o= @@ -2639,13 +2765,16 @@ google.golang.org/genproto/googleapis/bytestream v0.0.0-20250212204824-5a70512c5 google.golang.org/genproto/googleapis/bytestream v0.0.0-20250219182151-9fdb1cabc7b2 h1:UZtupsOaDeUm4KiG4HQTSyENUuCayW8K5d5cs7zK79c= google.golang.org/genproto/googleapis/bytestream v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:35wIojE/F1ptq1nfNDNjtowabHoMSA2qQs7+smpCO5s= google.golang.org/genproto/googleapis/bytestream v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:WkJpQl6Ujj3ElX4qZaNm5t6cT95ffI4K+HKQ0+1NyMw= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20250528174236-200df99c418a/go.mod h1:h6yxum/C2qRb4txaZRLDHK8RyS0H/o2oEDeKY4onY/Y= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= +google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= k8s.io/apiserver v0.28.1 h1:dw2/NKauDZCnOUAzIo2hFhtBRUo6gQK832NV8kuDbGM= k8s.io/apiserver v0.28.1/go.mod h1:d8aizlSRB6yRgJ6PKfDkdwCy2DXt/d1FDR6iJN9kY1w= @@ -2659,6 +2788,7 @@ k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= k8s.io/apiserver v0.32.1 h1:oo0OozRos66WFq87Zc5tclUX2r0mymoVHRq8JmR7Aak= k8s.io/apiserver v0.32.1/go.mod h1:UcB9tWjBY7aryeI5zAgzVJB/6k7E97bkr1RgqDz0jPw= +k8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8= k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= k8s.io/component-base v0.30.1 h1:bvAtlPh1UrdaZL20D9+sWxsJljMi0QZ3Lmw+kmZAaxQ= @@ -2667,6 +2797,7 @@ k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk= k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w= +k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= @@ -2718,3 +2849,4 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsA sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= From ba8d8d4e171eb612dda888d59030b747f1d556de Mon Sep 17 00:00:00 2001 From: Kartikay Date: Fri, 11 Jul 2025 00:17:08 +0530 Subject: [PATCH 3/6] fix merge conflict Signed-off-by: Kartikay Please enter the commit message for your changes. Lines starting --- go.mod | 2 +- pkg/cmd/datastore.go | 2 +- pkg/cmd/migrate.go | 2 +- pkg/cmd/root.go | 2 +- pkg/cmd/serve.go | 29 ++++++++++--------- pkg/cmd/server/cacheconfig.go | 2 +- pkg/cmd/server/defaults.go | 12 ++++---- pkg/cmd/server/server_test.go | 5 ++-- pkg/cmd/termination/termination.go | 2 +- pkg/releases/releases.go | 3 ++ pkg/releases/releases_test.go | 6 ++++ pkg/runtime/profiling.go | 4 +-- pkg/schemadsl/parser/parser.go | 4 ++- .../parser/tests/invaliduse.zed.expected | 2 +- 14 files changed, 45 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index 169ce29c19..a54c5bd072 100644 --- a/go.mod +++ b/go.mod @@ -440,4 +440,4 @@ require ( sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/yaml v1.5.0 // indirect -) +) \ No newline at end of file diff --git a/pkg/cmd/datastore.go b/pkg/cmd/datastore.go index b31e795a44..74970add3c 100644 --- a/pkg/cmd/datastore.go +++ b/pkg/cmd/datastore.go @@ -57,7 +57,7 @@ func NewGCDatastoreCommand(programName string, cfg *datastore.Config) *cobra.Com return &cobra.Command{ Use: "gc", Short: "executes garbage collection", - Long: "Executes garbage collection against the datastore", + Long: "Executes garbage collection against the datastore. Deletes stale relationships, expired relationships, and stale transactions.", PreRunE: server.DefaultPreRunE(programName), RunE: termination.PublishError(func(cmd *cobra.Command, args []string) error { ctx := context.Background() diff --git a/pkg/cmd/migrate.go b/pkg/cmd/migrate.go index d3b0d43d70..48689938fc 100644 --- a/pkg/cmd/migrate.go +++ b/pkg/cmd/migrate.go @@ -159,7 +159,7 @@ func RegisterHeadFlags(cmd *cobra.Command) { func NewHeadCommand(programName string) *cobra.Command { return &cobra.Command{ Use: "head", - Short: "compute the head database migration revision", + Short: "compute the head (latest) database migration revision available", PreRunE: server.DefaultPreRunE(programName), RunE: func(cmd *cobra.Command, args []string) error { headRevision, err := HeadRevision(cobrautil.MustGetStringExpanded(cmd, "datastore-engine")) diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index e5d241d4c2..118562a612 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -36,7 +36,7 @@ func NewRootCommand(programName string) *cobra.Command { return &cobra.Command{ Use: programName, Short: "A modern permissions database", - Long: "A database that stores, computes, and validates application permissions", + Long: "A database that stores and computes permissions", Example: server.ServeExample(programName), SilenceErrors: true, SilenceUsage: true, diff --git a/pkg/cmd/serve.go b/pkg/cmd/serve.go index 5f59f3d194..7d7a68a602 100644 --- a/pkg/cmd/serve.go +++ b/pkg/cmd/serve.go @@ -62,13 +62,10 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error { nfs := cobrautil.NewNamedFlagSets(cmd) grpcFlagSet := nfs.FlagSet(BoldBlue("gRPC")) - // Flags for logging - grpcFlagSet.BoolVar(&config.EnableRequestLogs, "grpc-log-requests-enabled", false, "logs API request payloads") - grpcFlagSet.BoolVar(&config.EnableResponseLogs, "grpc-log-responses-enabled", false, "logs API response payloads") // Flags for the gRPC API server util.RegisterGRPCServerFlags(grpcFlagSet, &config.GRPCServer, "grpc", "gRPC", ":50051", true) - grpcFlagSet.StringSliceVar(&config.PresharedSecureKey, PresharedKeyFlag, []string{}, "preshared key(s) to require for authenticated requests") + grpcFlagSet.StringSliceVar(&config.PresharedSecureKey, PresharedKeyFlag, []string{}, "(required) preshared key(s) that must be provided by clients to authenticate requests") grpcFlagSet.DurationVar(&config.ShutdownGracePeriod, "grpc-shutdown-grace-period", 0*time.Second, "amount of time after receiving sigint to continue serving") if err := cobra.MarkFlagRequired(grpcFlagSet, PresharedKeyFlag); err != nil { return fmt.Errorf("failed to mark flag as required: %w", err) @@ -76,7 +73,7 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error { // Flags for HTTP gateway httpFlags := nfs.FlagSet(BoldBlue("HTTP")) - util.RegisterHTTPServerFlags(httpFlags, &config.HTTPGateway, "http", "gateway", ":8443", false) + util.RegisterHTTPServerFlags(httpFlags, &config.HTTPGateway, "http", "proxy", ":8443", false) httpFlags.StringVar(&config.HTTPGatewayUpstreamAddr, "http-upstream-override-addr", "", "Override the upstream to point to a different gRPC server") if err := httpFlags.MarkHidden("http-upstream-override-addr"); err != nil { return fmt.Errorf("failed to mark flag as hidden: %w", err) @@ -106,7 +103,7 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error { apiFlags.Uint16Var(&config.MaximumUpdatesPerWrite, "write-relationships-max-updates-per-call", 1000, "maximum number of updates allowed for WriteRelationships calls") apiFlags.IntVar(&config.MaxCaveatContextSize, "max-caveat-context-size", 4096, "maximum allowed size of request caveat context in bytes. A value of zero or less means no limit") apiFlags.IntVar(&config.MaxRelationshipContextSize, "max-relationship-context-size", 25000, "maximum allowed size of the context to be stored in a relationship") - apiFlags.DurationVar(&config.StreamingAPITimeout, "streaming-api-response-delay-timeout", 30*time.Second, "max duration time elapsed between messages sent by the server-side to the client (responses) before the stream times out") + apiFlags.DurationVar(&config.StreamingAPITimeout, "streaming-api-response-delay-timeout", 30*time.Second, "maximum duration time elapsed between messages sent by the server-side to the client (responses) before the stream times out") apiFlags.DurationVar(&config.WatchHeartbeat, "watch-api-heartbeat", 1*time.Second, "heartbeat time on the watch in the API. 0 means to default to the datastore's minimum.") apiFlags.Uint32Var(&config.MaxReadRelationshipsLimit, "max-read-relationships-limit", 1000, "maximum number of relationships that can be read in a single request") apiFlags.Uint32Var(&config.MaxDeleteRelationshipsLimit, "max-delete-relationships-limit", 1000, "maximum number of relationships that can be deleted in a single request") @@ -171,24 +168,28 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error { Msg("The old implementation of LookupResources is no longer available, and a `false` value is no longer valid. Please remove this flag.") } - experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipExpiration, "enable-experimental-relationship-expiration", false, "enables experimental support for first-class relationship expiration") + experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipExpiration, "enable-experimental-relationship-expiration", false, "enables experimental support for relationship expiration") experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipDeprecation, "enable-experimental-relationship-deprecation", false, "enables experimental support for deprecating relations") - experimentalFlags.BoolVar(&config.EnableExperimentalWatchableSchemaCache, "enable-experimental-watchable-schema-cache", false, "enables the experimental schema cache which makes use of the Watch API for automatic updates") + experimentalFlags.BoolVar(&config.EnableExperimentalWatchableSchemaCache, "enable-experimental-watchable-schema-cache", false, "enables the experimental schema cache, which uses the Watch API to keep the schema up to date") // TODO: these two could reasonably be put in either the Dispatch group or the Experimental group. Is there a preference? experimentalFlags.StringToStringVar(&config.DispatchSecondaryUpstreamAddrs, "experimental-dispatch-secondary-upstream-addrs", nil, "secondary upstream addresses for dispatches, each with a name") experimentalFlags.StringToStringVar(&config.DispatchSecondaryUpstreamExprs, "experimental-dispatch-secondary-upstream-exprs", nil, "map from request type to its associated CEL expression, which returns the secondary upstream(s) to be used for the request") experimentalFlags.StringToStringVar(&config.DispatchSecondaryMaximumPrimaryHedgingDelays, "experimental-dispatch-secondary-maximum-primary-hedging-delays", nil, "maximum number of hedging delays to use for each request type to delay the primary request. default is 5ms") - observabilityFlags := nfs.FlagSet(BoldBlue("Observability")) - // Flags for observability and profiling + tracingFlags := nfs.FlagSet(BoldBlue("Tracing")) + // Flags for tracing // NOTE: cobraotel.New takes service name as an arg rather than command name. otel := cobraotel.New("spicedb") - otel.RegisterFlags(observabilityFlags) - runtime.RegisterFlags(observabilityFlags) + otel.RegisterFlags(tracingFlags) - metricsFlags := nfs.FlagSet(BoldBlue("Metrics Server")) + loggingFlagSet := nfs.FlagSet(BoldBlue("Logging")) + loggingFlagSet.BoolVar(&config.EnableRequestLogs, "grpc-log-requests-enabled", false, "enable logging of API request payloads") + loggingFlagSet.BoolVar(&config.EnableResponseLogs, "grpc-log-responses-enabled", false, "enable logging of API response payloads") + + metricsFlags := nfs.FlagSet(BoldBlue("Metrics & Profiling")) // Flags for metrics util.RegisterHTTPServerFlags(metricsFlags, &config.MetricsAPI, "metrics", "metrics", ":9090", true) + runtime.RegisterFlags(metricsFlags) telemetryFlags := nfs.FlagSet(BoldBlue("Telemetry")) // Flags for telemetry @@ -218,7 +219,7 @@ func NewServeCommand(programName string, config *server.Config) *cobra.Command { return &cobra.Command{ Use: "serve", Short: "serve the permissions database", - Long: "A database that stores, computes, and validates application permissions", + Long: "start a SpiceDB server", PreRunE: server.DefaultPreRunE(programName), RunE: termination.PublishError(func(cmd *cobra.Command, args []string) error { server, err := config.Complete(cmd.Context()) diff --git a/pkg/cmd/server/cacheconfig.go b/pkg/cmd/server/cacheconfig.go index 9b79d7ed36..991510dd65 100644 --- a/pkg/cmd/server/cacheconfig.go +++ b/pkg/cmd/server/cacheconfig.go @@ -135,7 +135,7 @@ func MustRegisterCacheFlags(flags *pflag.FlagSet, flagPrefix string, config, def config.Name = defaults.Name flagPrefix = cmp.Or(flagPrefix, "cache") flags.StringVar(&config.MaxCost, flagPrefix+"-max-cost", defaults.MaxCost, "upper bound cache size in bytes or percent of available memory") - flags.Int64Var(&config.NumCounters, flagPrefix+"-num-counters", defaults.NumCounters, "number of TinyLFU samples to track") + flags.Int64Var(&config.NumCounters, flagPrefix+"-num-counters", defaults.NumCounters, "number of TinyLFU samples to track. A higher number means more accurate eviction decisions but more memory usage") flags.BoolVar(&config.Metrics, flagPrefix+"-metrics", defaults.Metrics, "enable cache metrics") flags.BoolVar(&config.Enabled, flagPrefix+"-enabled", defaults.Enabled, "enable caching") diff --git a/pkg/cmd/server/defaults.go b/pkg/cmd/server/defaults.go index f849263246..4ac9fd7e96 100644 --- a/pkg/cmd/server/defaults.go +++ b/pkg/cmd/server/defaults.go @@ -54,12 +54,14 @@ func ServeExample(programName string) string { %[3]s serve --grpc-preshared-key "somerandomkeyhere" %[2]s: - %[3]s serve --grpc-preshared-key "realkeyhere" --grpc-tls-cert-path path/to/tls/cert --grpc-tls-key-path path/to/tls/key \ - --http-tls-cert-path path/to/tls/cert --http-tls-key-path path/to/tls/key \ - --datastore-engine postgres --datastore-conn-uri "postgres-connection-string-here" + %[3]s serve --grpc-preshared-key "realkeyhere" \ + --grpc-tls-cert-path path/to/tls/cert --grpc-tls-key-path path/to/tls/key \ + --http-enabled http-tls-cert-path path/to/tls/cert --http-tls-key-path path/to/tls/key \ + --datastore-engine postgres \ + --datastore-conn-uri "postgres-connection-string-here" `, - color.YellowString("No TLS and in-memory"), - color.GreenString("TLS and a real datastore"), + color.YellowString("No TLS and in-memory datastore"), + color.GreenString("TLS and HTTP enabled, and a real datastore"), programName, ) } diff --git a/pkg/cmd/server/server_test.go b/pkg/cmd/server/server_test.go index 86b4369143..9c12cc3ff7 100644 --- a/pkg/cmd/server/server_test.go +++ b/pkg/cmd/server/server_test.go @@ -62,6 +62,8 @@ func TestServerGracefulTermination(t *testing.T) { func TestOTelReporting(t *testing.T) { defer goleak.VerifyNone(t, append(testutil.GoLeakIgnores(), goleak.IgnoreCurrent())...) + spanrecorder, restoreOtel := setupSpanRecorder() + defer restoreOtel() ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() @@ -103,9 +105,6 @@ func TestOTelReporting(t *testing.T) { require.NoError(t, srv.Run(ctx)) }() - spanrecorder, restoreOtel := setupSpanRecorder() - defer restoreOtel() - // test unary OTel middleware _, err = schemaSrv.WriteSchema(ctx, &v1.WriteSchemaRequest{ Schema: `definition user {}`, diff --git a/pkg/cmd/termination/termination.go b/pkg/cmd/termination/termination.go index 3c38d5a4bd..878432b35e 100644 --- a/pkg/cmd/termination/termination.go +++ b/pkg/cmd/termination/termination.go @@ -70,6 +70,6 @@ func PublishError(runFunc cobrautil.CobraRunFunc) cobrautil.CobraRunFunc { func RegisterFlags(flagset *flag.FlagSet) { flagset.String(terminationLogFlagName, "", - "define the path to the termination log file, which contains a JSON payload to surface as reason for termination - disabled by default", + "local path to the termination log file, which contains a JSON payload to surface as reason for termination", ) } diff --git a/pkg/releases/releases.go b/pkg/releases/releases.go index 5a1f75f987..5b3a4bcee4 100644 --- a/pkg/releases/releases.go +++ b/pkg/releases/releases.go @@ -36,6 +36,9 @@ func GetLatestRelease(ctx context.Context) (*Release, error) { } func getLatestReleaseWithClient(ctx context.Context, httpClient *http.Client) (*Release, error) { + if httpClient == nil { + httpClient = http.DefaultClient + } url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", githubNamespace, githubRepository) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) diff --git a/pkg/releases/releases_test.go b/pkg/releases/releases_test.go index ec8726ad22..af22c389b3 100644 --- a/pkg/releases/releases_test.go +++ b/pkg/releases/releases_test.go @@ -17,6 +17,12 @@ func TestGetSourceRepository(t *testing.T) { } func TestGetLatestRelease(t *testing.T) { + t.Run("creates default http client", func(t *testing.T) { + release, err := getLatestReleaseWithClient(t.Context(), nil) + require.NoError(t, err) + require.NotNil(t, release) + }) + t.Run("successful release fetch", func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/repos/authzed/spicedb/releases/latest", r.URL.Path) diff --git a/pkg/runtime/profiling.go b/pkg/runtime/profiling.go index 28e995e1ff..8f2b310fb9 100644 --- a/pkg/runtime/profiling.go +++ b/pkg/runtime/profiling.go @@ -14,8 +14,8 @@ import ( // - "pprof-mutex-profile-rate" // - "pprof-block-profile-rate" func RegisterFlags(flags *pflag.FlagSet) { - flags.Int("pprof-mutex-profile-rate", 0, "sets the mutex profile sampling rate") - flags.Int("pprof-block-profile-rate", 0, "sets the block profile sampling rate") + flags.Int("pprof-mutex-profile-rate", 0, "sets the mutex profile sampling rate (between 0 and 1)") + flags.Int("pprof-block-profile-rate", 0, "sets the block profile sampling rate (between 0 and 1)") } // RunE returns a Cobra RunFunc that configures mutex and block profiles. diff --git a/pkg/schemadsl/parser/parser.go b/pkg/schemadsl/parser/parser.go index 6c028df83c..1a24028477 100644 --- a/pkg/schemadsl/parser/parser.go +++ b/pkg/schemadsl/parser/parser.go @@ -311,13 +311,15 @@ func (p *sourceParser) consumeDefinition() AstNode { case p.isToken(lexer.TokenTypeAt): defNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) + case p.isToken(lexer.TokenTypeAt): + defNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) + case p.isKeyword("relation"): defNode.Connect(dslshape.NodePredicateChild, p.consumeRelation()) case p.isKeyword("permission"): defNode.Connect(dslshape.NodePredicateChild, p.consumePermission()) } - ok := p.consumeStatementTerminator() if !ok { break diff --git a/pkg/schemadsl/parser/tests/invaliduse.zed.expected b/pkg/schemadsl/parser/tests/invaliduse.zed.expected index 50f1468985..f399586130 100644 --- a/pkg/schemadsl/parser/tests/invaliduse.zed.expected +++ b/pkg/schemadsl/parser/tests/invaliduse.zed.expected @@ -10,7 +10,7 @@ NodeTypeFile child-node => NodeTypeError end-rune = 12 - error-message = Unknown use flag: `something`. Options are: expiration, typechecking + error-message = Unknown use flag: `something`. Options are: deprecation, expiration, typechecking error-source = input-source = invalid use From 5c2c0760575d486d40a9cc6d3fbcfeef66e27b0f Mon Sep 17 00:00:00 2001 From: Kartikay Date: Sun, 20 Jul 2025 21:22:10 +0530 Subject: [PATCH 4/6] deprecation with opts Signed-off-by: Kartikay --- internal/services/shared/errors.go | 9 +- internal/services/v1/relationships.go | 69 +- internal/services/v1/schema_test.go | 35 +- pkg/diff/namespace/diff.go | 8 +- pkg/diff/namespace/diff_test.go | 12 +- pkg/namespace/builder.go | 12 +- pkg/proto/core/v1/core.pb.go | 1321 +++++++++-------- pkg/proto/core/v1/core.pb.validate.go | 241 ++- pkg/proto/core/v1/core_vtproto.pb.go | 496 ++++++- pkg/schemadsl/compiler/translator.go | 109 +- pkg/schemadsl/dslshape/dslshape.go | 28 +- .../dslshape/zz_generated.nodetype_string.go | 27 +- pkg/schemadsl/generator/generator.go | 4 +- pkg/schemadsl/generator/generator_test.go | 3 + pkg/schemadsl/parser/parser.go | 73 +- pkg/schemadsl/parser/parser_test.go | 3 + .../parser/tests/deprecated_options.zed | 14 + .../tests/deprecated_options.zed.expected | 71 + .../parser/tests/deprecation.zed.expected | 4 +- .../tests/deprecation_outside_definition.zed | 15 + ...eprecation_outside_definition.zed.expected | 71 + .../tests/invalid-deprecation.zed.expected | 4 +- .../parser/tests/multiple_deprecations.zed | 19 + .../tests/multiple_deprecations.zed.expected | 101 ++ proto/internal/core/v1/core.proto | 32 +- 25 files changed, 2070 insertions(+), 711 deletions(-) create mode 100644 pkg/schemadsl/parser/tests/deprecated_options.zed create mode 100644 pkg/schemadsl/parser/tests/deprecated_options.zed.expected create mode 100644 pkg/schemadsl/parser/tests/deprecation_outside_definition.zed create mode 100644 pkg/schemadsl/parser/tests/deprecation_outside_definition.zed.expected create mode 100644 pkg/schemadsl/parser/tests/multiple_deprecations.zed create mode 100644 pkg/schemadsl/parser/tests/multiple_deprecations.zed.expected diff --git a/internal/services/shared/errors.go b/internal/services/shared/errors.go index 26bbfa80c7..4e6d090088 100644 --- a/internal/services/shared/errors.go +++ b/internal/services/shared/errors.go @@ -56,9 +56,14 @@ type DeprecationError struct { error } -func NewDeprecationError(namespace string, relation string) DeprecationError { +func NewDeprecationError(namespace string, relation string, comments string) DeprecationError { + if relation == "" { + return DeprecationError{ + error: fmt.Errorf("object %s is deprecated, comments:%s", namespace, comments), + } + } return DeprecationError{ - error: fmt.Errorf("relation %s#%s is deprecated", namespace, relation), + error: fmt.Errorf("relation %s#%s is deprecated, comments:%s", namespace, relation, comments), } } diff --git a/internal/services/v1/relationships.go b/internal/services/v1/relationships.go index 83fde5fab2..11e64f12db 100644 --- a/internal/services/v1/relationships.go +++ b/internal/services/v1/relationships.go @@ -330,8 +330,10 @@ func (ps *permissionServer) WriteRelationships(ctx context.Context, req *v1.Writ updateRelationshipSet := mapz.NewSet[string]() for _, update := range req.Updates { // TODO(jschorr): Change to struct-based keys. - if err := checkForDeprecatedRelationships(ctx, update, ds, ps); err != nil { - return nil, ps.rewriteError(ctx, err) + if ps.config.DeprecatedRelationshipsEnabled { + if err := checkForDeprecatedRelationsAndObjects(ctx, update, ds); err != nil { + return nil, ps.rewriteError(ctx, err) + } } tupleStr := tuple.V1StringRelationshipWithoutCaveatOrExpiration(update.Relationship) @@ -631,7 +633,7 @@ func labelsForFilter(filter *v1.RelationshipFilter) perfinsights.APIShapeLabels } } -func checkForDeprecatedRelationships(ctx context.Context, update *v1.RelationshipUpdate, ds datastore.Datastore, ps *permissionServer) error { +func checkForDeprecatedRelationsAndObjects(ctx context.Context, update *v1.RelationshipUpdate, ds datastore.Datastore) error { resource := update.Relationship.Resource headRevision, err := ds.HeadRevision(ctx) if err != nil { @@ -643,22 +645,57 @@ func checkForDeprecatedRelationships(ctx context.Context, update *v1.Relationshi return err } - if !ps.config.DeprecatedRelationshipsEnabled && relDef.DeprecationType != corev1.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { - return ps.rewriteError( - ctx, - fmt.Errorf("support for deprecated relationships is not enabled"), - ) + if relDef.Deprecation != nil && relDef.Deprecation.DeprecationType != corev1.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + // Check if the relation is deprecated + switch relDef.Deprecation.DeprecationType { + case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: + log.Warn(). + Str("namespace", update.Relationship.Resource.ObjectType). + Str("relation", update.Relationship.Relation). + Str("comments", relDef.Deprecation.Comments). + Msg("write to deprecated relation") + + case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: + return shared.NewDeprecationError(update.Relationship.Resource.ObjectType, update.Relationship.Relation, relDef.Deprecation.Comments) + } + + } + nsdef, _, err := reader.ReadNamespaceByName(ctx, resource.ObjectType) + if err != nil { + return err + } + + // Check if the resource is deprecated + if nsdef.Deprecation != nil && nsdef.Deprecation.DeprecationType != corev1.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + // Check if the namespace is deprecated + switch nsdef.Deprecation.DeprecationType { + case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: + log.Warn(). + Str("namespace", nsdef.Name). + Str("comments", nsdef.Deprecation.Comments). + Msg("write to deprecated object") + case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: + return shared.NewDeprecationError(resource.ObjectType, "", nsdef.Deprecation.Comments) + } } - switch relDef.DeprecationType { - case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: - log.Warn(). - Str("namespace", update.Relationship.Resource.ObjectType). - Str("relation", update.Relationship.Relation). - Msg("write to deprecated relation") + objectRef := update.Relationship.Subject + nsdef, _, err = reader.ReadNamespaceByName(ctx, objectRef.Object.ObjectType) + if err != nil { + return err + } - case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: - return shared.NewDeprecationError(update.Relationship.Resource.ObjectType, update.Relationship.Relation) + if nsdef.Deprecation != nil && nsdef.Deprecation.DeprecationType != corev1.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + // Check if the subject is deprecated + switch nsdef.Deprecation.DeprecationType { + case corev1.DeprecationType_DEPRECATED_TYPE_WARNING: + log.Warn(). + Str("namespace", nsdef.Name). + Str("comments", nsdef.Deprecation.Comments). + Msg("write to deprecated object") + case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: + return shared.NewDeprecationError(resource.ObjectType, "", nsdef.Deprecation.Comments) + } } return nil diff --git a/internal/services/v1/schema_test.go b/internal/services/v1/schema_test.go index 093d152433..72b98a06f3 100644 --- a/internal/services/v1/schema_test.go +++ b/internal/services/v1/schema_test.go @@ -1649,15 +1649,20 @@ func TestSchemaChangeRelationDeprecation(t *testing.T) { client := v1.NewSchemaServiceClient(conn) v1client := v1.NewPermissionsServiceClient(conn) - // Write a basic schema with deprecation type warning. + // Write a basic schema with deprecations. originalSchema := ` use deprecation definition user {} + definition testuser {} definition document { - @deprecated(warn) relation somerelation: user - }` + relation otherelation: testuser + } + + @deprecated(warn, document#somerelation, "This relation is deprecated, please use otherelation instead.") + @deprecated(error, testuser, "super deprecated") + ` _, err := client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ Schema: originalSchema, }) @@ -1672,36 +1677,24 @@ func TestSchemaChangeRelationDeprecation(t *testing.T) { }) require.Nil(t, err) - deprecatedErrSchema := ` - use deprecation - definition user {} - - definition document { - @deprecated(error) - relation somerelation: user - }` - - // Enforce deprecation over the relation in the new schema. - _, err = client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ - Schema: deprecatedErrSchema, - }) - require.NoError(t, err) - - // Attempt to write to a deprecated relation which should fail. - toWrite = tuple.MustParse("document:somedoc#somerelation@user:jerry") + // Attempt to write to a deprecated object which should fail. + toWrite = tuple.MustParse("document:somedoc#otherelation@testuser:jerry") _, err = v1client.WriteRelationships(t.Context(), &v1.WriteRelationshipsRequest{ Updates: []*v1.RelationshipUpdate{tuple.MustUpdateToV1RelationshipUpdate(tuple.Create( toWrite, ))}, }) - require.Equal(t, "rpc error: code = Aborted desc = relation document#somerelation is deprecated", err.Error()) + require.Equal(t, "rpc error: code = Aborted desc = object document is deprecated, comments:super deprecated", err.Error()) // Change the schema to remove the deprecation type. newSchema := ` + use deprecation definition user {} + definition testuser {} definition document { relation somerelation: user + relation otherelation: testuser }` _, err = client.WriteSchema(t.Context(), &v1.WriteSchemaRequest{ Schema: newSchema, diff --git a/pkg/diff/namespace/diff.go b/pkg/diff/namespace/diff.go index 41b38c5206..889c2ac7fc 100644 --- a/pkg/diff/namespace/diff.go +++ b/pkg/diff/namespace/diff.go @@ -132,6 +132,12 @@ func DiffNamespaces(existing *core.NamespaceDefinition, updated *core.NamespaceD }) } + if existing.Deprecation != updated.Deprecation { + deltas = append(deltas, Delta{ + Type: ChangedDeprecation, + }) + } + // Collect up relations and check. existingRels := map[string]*core.Relation{} existingRelNames := mapz.NewSet[string]() @@ -244,7 +250,7 @@ func DiffNamespaces(existing *core.NamespaceDefinition, updated *core.NamespaceD } // Compare deprecation status - if existingRel.DeprecationType != updatedRel.DeprecationType { + if existingRel.Deprecation != updatedRel.Deprecation { deltas = append(deltas, Delta{ Type: ChangedDeprecation, RelationName: shared, diff --git a/pkg/diff/namespace/diff_test.go b/pkg/diff/namespace/diff_test.go index 429d65780c..ac6b71d955 100644 --- a/pkg/diff/namespace/diff_test.go +++ b/pkg/diff/namespace/diff_test.go @@ -575,11 +575,15 @@ func TestNamespaceDiff(t *testing.T) { "deprecate relation with an error type", ns.Namespace( "document", - ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED)), + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", &core.Deprecation{ + DeprecationType: core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED, + })), ), ns.Namespace( "document", - ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_ERROR)), + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", &core.Deprecation{ + DeprecationType: core.DeprecationType_DEPRECATED_TYPE_ERROR, + })), ), []Delta{ {Type: ChangedDeprecation, RelationName: "somerel"}, @@ -589,7 +593,9 @@ func TestNamespaceDiff(t *testing.T) { "remove deprecation", ns.Namespace( "document", - ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", core.DeprecationType_DEPRECATED_TYPE_ERROR)), + ns.MustRelation("somerel", nil, ns.AllowedDeprecatedRelation("foo", "bar", &core.Deprecation{ + DeprecationType: core.DeprecationType_DEPRECATED_TYPE_ERROR, + })), ), ns.Namespace( "document", diff --git a/pkg/namespace/builder.go b/pkg/namespace/builder.go index 2d551c40aa..982447d582 100644 --- a/pkg/namespace/builder.go +++ b/pkg/namespace/builder.go @@ -46,7 +46,7 @@ func Relation(name string, rewrite *core.UsersetRewrite, allowedDirectRelations TypeInformation: typeInfo, } - if err := setRelationDeprecationType(rel, allowedDirectRelations...); err != nil { + if err := setRelationDeprecation(rel, allowedDirectRelations...); err != nil { return nil, spiceerrors.MustBugf("failed to set deprecation type: %s", err.Error()) } @@ -99,13 +99,13 @@ func AllowedRelationWithCaveat(namespaceName string, relationName string, withCa } // AllowedDeprecatedRelation creates a relation reference to an allowed relation that is deprecated. -func AllowedDeprecatedRelation(namespaceName string, relationName string, deprecationType core.DeprecationType) *core.AllowedRelation { +func AllowedDeprecatedRelation(namespaceName string, relationName string, deprecation *core.Deprecation) *core.AllowedRelation { return &core.AllowedRelation{ Namespace: namespaceName, RelationOrWildcard: &core.AllowedRelation_Relation{ Relation: relationName, }, - DeprecationType: deprecationType, + Deprecation: deprecation, } } @@ -259,11 +259,11 @@ func setOperation(firstChild *core.SetOperation_Child, rest []*core.SetOperation } // setRelationDeprecationType sets the deprecation type of a relation based on all of the deprecations of allowed direct relations. -func setRelationDeprecationType(relation *core.Relation, allowedDirectRelations ...*core.AllowedRelation) error { +func setRelationDeprecation(relation *core.Relation, allowedDirectRelations ...*core.AllowedRelation) error { if len(allowedDirectRelations) > 0 { for _, allowedRelation := range allowedDirectRelations { - if allowedRelation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { - relation.DeprecationType = allowedRelation.DeprecationType + if allowedRelation.Deprecation != nil && allowedRelation.Deprecation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + relation.Deprecation = allowedRelation.Deprecation } } } diff --git a/pkg/proto/core/v1/core.pb.go b/pkg/proto/core/v1/core.pb.go index f1aaf57a27..1a428da2e1 100644 --- a/pkg/proto/core/v1/core.pb.go +++ b/pkg/proto/core/v1/core.pb.go @@ -234,7 +234,7 @@ func (x ReachabilityEntrypoint_ReachabilityEntrypointKind) Number() protoreflect // Deprecated: Use ReachabilityEntrypoint_ReachabilityEntrypointKind.Descriptor instead. func (ReachabilityEntrypoint_ReachabilityEntrypointKind) EnumDescriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{18, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{19, 0} } type ReachabilityEntrypoint_EntrypointResultStatus int32 @@ -287,7 +287,7 @@ func (x ReachabilityEntrypoint_EntrypointResultStatus) Number() protoreflect.Enu // Deprecated: Use ReachabilityEntrypoint_EntrypointResultStatus.Descriptor instead. func (ReachabilityEntrypoint_EntrypointResultStatus) EnumDescriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{18, 1} + return file_core_v1_core_proto_rawDescGZIP(), []int{19, 1} } type FunctionedTupleToUserset_Function int32 @@ -336,7 +336,7 @@ func (x FunctionedTupleToUserset_Function) Number() protoreflect.EnumNumber { // Deprecated: Use FunctionedTupleToUserset_Function.Descriptor instead. func (FunctionedTupleToUserset_Function) EnumDescriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{26, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{27, 0} } type ComputedUserset_Object int32 @@ -382,7 +382,7 @@ func (x ComputedUserset_Object) Number() protoreflect.EnumNumber { // Deprecated: Use ComputedUserset_Object.Descriptor instead. func (ComputedUserset_Object) EnumDescriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{27, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{28, 0} } type CaveatOperation_Operation int32 @@ -434,7 +434,7 @@ func (x CaveatOperation_Operation) Number() protoreflect.EnumNumber { // Deprecated: Use CaveatOperation_Operation.Descriptor instead. func (CaveatOperation_Operation) EnumDescriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{30, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{31, 0} } type RelationTuple struct { @@ -1330,6 +1330,8 @@ type NamespaceDefinition struct { Metadata *Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` // * source_position contains the position of the namespace in the source schema, if any SourcePosition *SourcePosition `protobuf:"bytes,4,opt,name=source_position,json=sourcePosition,proto3" json:"source_position,omitempty"` + // * deprecation contains the deprecation information for the namespace, if any + Deprecation *Deprecation `protobuf:"bytes,5,opt,name=deprecation,proto3" json:"deprecation,omitempty"` } func (x *NamespaceDefinition) Reset() { @@ -1392,6 +1394,96 @@ func (x *NamespaceDefinition) GetSourcePosition() *SourcePosition { return nil } +func (x *NamespaceDefinition) GetDeprecation() *Deprecation { + if x != nil { + return x.Deprecation + } + return nil +} + +type Deprecation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeprecationType DeprecationType `protobuf:"varint,1,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` + // * object is the object that is deprecated + Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` + // * relation is the relation that is deprecated + Relation string `protobuf:"bytes,3,opt,name=relation,proto3" json:"relation,omitempty"` + // * comments are the comments to show when the relation is used + Comments string `protobuf:"bytes,4,opt,name=comments,proto3" json:"comments,omitempty"` + // * source_position contains the position of the deprecation in the source schema, if any + SourcePosition *SourcePosition `protobuf:"bytes,5,opt,name=source_position,json=sourcePosition,proto3" json:"source_position,omitempty"` +} + +func (x *Deprecation) Reset() { + *x = Deprecation{} + if protoimpl.UnsafeEnabled { + mi := &file_core_v1_core_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Deprecation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Deprecation) ProtoMessage() {} + +func (x *Deprecation) ProtoReflect() protoreflect.Message { + mi := &file_core_v1_core_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Deprecation.ProtoReflect.Descriptor instead. +func (*Deprecation) Descriptor() ([]byte, []int) { + return file_core_v1_core_proto_rawDescGZIP(), []int{15} +} + +func (x *Deprecation) GetDeprecationType() DeprecationType { + if x != nil { + return x.DeprecationType + } + return DeprecationType_DEPRECATED_TYPE_UNSPECIFIED +} + +func (x *Deprecation) GetObject() string { + if x != nil { + return x.Object + } + return "" +} + +func (x *Deprecation) GetRelation() string { + if x != nil { + return x.Relation + } + return "" +} + +func (x *Deprecation) GetComments() string { + if x != nil { + return x.Comments + } + return "" +} + +func (x *Deprecation) GetSourcePosition() *SourcePosition { + if x != nil { + return x.SourcePosition + } + return nil +} + // * // Relation represents the definition of a relation or permission under a namespace. type Relation struct { @@ -1414,13 +1506,13 @@ type Relation struct { AliasingRelation string `protobuf:"bytes,6,opt,name=aliasing_relation,json=aliasingRelation,proto3" json:"aliasing_relation,omitempty"` CanonicalCacheKey string `protobuf:"bytes,7,opt,name=canonical_cache_key,json=canonicalCacheKey,proto3" json:"canonical_cache_key,omitempty"` // * deprecation_type is the type of deprecation for the relation - DeprecationType DeprecationType `protobuf:"varint,8,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` + Deprecation *Deprecation `protobuf:"bytes,8,opt,name=deprecation,proto3" json:"deprecation,omitempty"` } func (x *Relation) Reset() { *x = Relation{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[15] + mi := &file_core_v1_core_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1433,7 +1525,7 @@ func (x *Relation) String() string { func (*Relation) ProtoMessage() {} func (x *Relation) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[15] + mi := &file_core_v1_core_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1446,7 +1538,7 @@ func (x *Relation) ProtoReflect() protoreflect.Message { // Deprecated: Use Relation.ProtoReflect.Descriptor instead. func (*Relation) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{15} + return file_core_v1_core_proto_rawDescGZIP(), []int{16} } func (x *Relation) GetName() string { @@ -1498,11 +1590,11 @@ func (x *Relation) GetCanonicalCacheKey() string { return "" } -func (x *Relation) GetDeprecationType() DeprecationType { +func (x *Relation) GetDeprecation() *Deprecation { if x != nil { - return x.DeprecationType + return x.Deprecation } - return DeprecationType_DEPRECATED_TYPE_UNSPECIFIED + return nil } // * @@ -1555,7 +1647,7 @@ type ReachabilityGraph struct { func (x *ReachabilityGraph) Reset() { *x = ReachabilityGraph{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[16] + mi := &file_core_v1_core_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1568,7 +1660,7 @@ func (x *ReachabilityGraph) String() string { func (*ReachabilityGraph) ProtoMessage() {} func (x *ReachabilityGraph) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[16] + mi := &file_core_v1_core_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1581,7 +1673,7 @@ func (x *ReachabilityGraph) ProtoReflect() protoreflect.Message { // Deprecated: Use ReachabilityGraph.ProtoReflect.Descriptor instead. func (*ReachabilityGraph) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{16} + return file_core_v1_core_proto_rawDescGZIP(), []int{17} } func (x *ReachabilityGraph) GetEntrypointsBySubjectType() map[string]*ReachabilityEntrypoints { @@ -1622,7 +1714,7 @@ type ReachabilityEntrypoints struct { func (x *ReachabilityEntrypoints) Reset() { *x = ReachabilityEntrypoints{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[17] + mi := &file_core_v1_core_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1635,7 +1727,7 @@ func (x *ReachabilityEntrypoints) String() string { func (*ReachabilityEntrypoints) ProtoMessage() {} func (x *ReachabilityEntrypoints) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[17] + mi := &file_core_v1_core_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1648,7 +1740,7 @@ func (x *ReachabilityEntrypoints) ProtoReflect() protoreflect.Message { // Deprecated: Use ReachabilityEntrypoints.ProtoReflect.Descriptor instead. func (*ReachabilityEntrypoints) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{17} + return file_core_v1_core_proto_rawDescGZIP(), []int{18} } func (x *ReachabilityEntrypoints) GetEntrypoints() []*ReachabilityEntrypoint { @@ -1703,7 +1795,7 @@ type ReachabilityEntrypoint struct { func (x *ReachabilityEntrypoint) Reset() { *x = ReachabilityEntrypoint{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[18] + mi := &file_core_v1_core_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1716,7 +1808,7 @@ func (x *ReachabilityEntrypoint) String() string { func (*ReachabilityEntrypoint) ProtoMessage() {} func (x *ReachabilityEntrypoint) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[18] + mi := &file_core_v1_core_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1729,7 +1821,7 @@ func (x *ReachabilityEntrypoint) ProtoReflect() protoreflect.Message { // Deprecated: Use ReachabilityEntrypoint.ProtoReflect.Descriptor instead. func (*ReachabilityEntrypoint) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{18} + return file_core_v1_core_proto_rawDescGZIP(), []int{19} } func (x *ReachabilityEntrypoint) GetKind() ReachabilityEntrypoint_ReachabilityEntrypointKind { @@ -1783,7 +1875,7 @@ type TypeInformation struct { func (x *TypeInformation) Reset() { *x = TypeInformation{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[19] + mi := &file_core_v1_core_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1796,7 +1888,7 @@ func (x *TypeInformation) String() string { func (*TypeInformation) ProtoMessage() {} func (x *TypeInformation) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[19] + mi := &file_core_v1_core_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1809,7 +1901,7 @@ func (x *TypeInformation) ProtoReflect() protoreflect.Message { // Deprecated: Use TypeInformation.ProtoReflect.Descriptor instead. func (*TypeInformation) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{19} + return file_core_v1_core_proto_rawDescGZIP(), []int{20} } func (x *TypeInformation) GetAllowedDirectRelations() []*AllowedRelation { @@ -1846,13 +1938,13 @@ type AllowedRelation struct { RequiredExpiration *ExpirationTrait `protobuf:"bytes,7,opt,name=required_expiration,json=requiredExpiration,proto3" json:"required_expiration,omitempty"` // * // deprecation_type defines the type of deprecation for this relation. - DeprecationType DeprecationType `protobuf:"varint,8,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` + Deprecation *Deprecation `protobuf:"bytes,8,opt,name=deprecation,proto3" json:"deprecation,omitempty"` } func (x *AllowedRelation) Reset() { *x = AllowedRelation{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[20] + mi := &file_core_v1_core_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1865,7 +1957,7 @@ func (x *AllowedRelation) String() string { func (*AllowedRelation) ProtoMessage() {} func (x *AllowedRelation) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[20] + mi := &file_core_v1_core_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1878,7 +1970,7 @@ func (x *AllowedRelation) ProtoReflect() protoreflect.Message { // Deprecated: Use AllowedRelation.ProtoReflect.Descriptor instead. func (*AllowedRelation) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{20} + return file_core_v1_core_proto_rawDescGZIP(), []int{21} } func (x *AllowedRelation) GetNamespace() string { @@ -1930,11 +2022,11 @@ func (x *AllowedRelation) GetRequiredExpiration() *ExpirationTrait { return nil } -func (x *AllowedRelation) GetDeprecationType() DeprecationType { +func (x *AllowedRelation) GetDeprecation() *Deprecation { if x != nil { - return x.DeprecationType + return x.Deprecation } - return DeprecationType_DEPRECATED_TYPE_UNSPECIFIED + return nil } type isAllowedRelation_RelationOrWildcard interface { @@ -1964,7 +2056,7 @@ type ExpirationTrait struct { func (x *ExpirationTrait) Reset() { *x = ExpirationTrait{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[21] + mi := &file_core_v1_core_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1977,7 +2069,7 @@ func (x *ExpirationTrait) String() string { func (*ExpirationTrait) ProtoMessage() {} func (x *ExpirationTrait) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[21] + mi := &file_core_v1_core_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1990,7 +2082,7 @@ func (x *ExpirationTrait) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpirationTrait.ProtoReflect.Descriptor instead. func (*ExpirationTrait) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{21} + return file_core_v1_core_proto_rawDescGZIP(), []int{22} } // * @@ -2008,7 +2100,7 @@ type AllowedCaveat struct { func (x *AllowedCaveat) Reset() { *x = AllowedCaveat{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[22] + mi := &file_core_v1_core_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2021,7 +2113,7 @@ func (x *AllowedCaveat) String() string { func (*AllowedCaveat) ProtoMessage() {} func (x *AllowedCaveat) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[22] + mi := &file_core_v1_core_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2034,7 +2126,7 @@ func (x *AllowedCaveat) ProtoReflect() protoreflect.Message { // Deprecated: Use AllowedCaveat.ProtoReflect.Descriptor instead. func (*AllowedCaveat) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{22} + return file_core_v1_core_proto_rawDescGZIP(), []int{23} } func (x *AllowedCaveat) GetCaveatName() string { @@ -2061,7 +2153,7 @@ type UsersetRewrite struct { func (x *UsersetRewrite) Reset() { *x = UsersetRewrite{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[23] + mi := &file_core_v1_core_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2074,7 +2166,7 @@ func (x *UsersetRewrite) String() string { func (*UsersetRewrite) ProtoMessage() {} func (x *UsersetRewrite) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[23] + mi := &file_core_v1_core_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2087,7 +2179,7 @@ func (x *UsersetRewrite) ProtoReflect() protoreflect.Message { // Deprecated: Use UsersetRewrite.ProtoReflect.Descriptor instead. func (*UsersetRewrite) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{23} + return file_core_v1_core_proto_rawDescGZIP(), []int{24} } func (m *UsersetRewrite) GetRewriteOperation() isUsersetRewrite_RewriteOperation { @@ -2158,7 +2250,7 @@ type SetOperation struct { func (x *SetOperation) Reset() { *x = SetOperation{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[24] + mi := &file_core_v1_core_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2171,7 +2263,7 @@ func (x *SetOperation) String() string { func (*SetOperation) ProtoMessage() {} func (x *SetOperation) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[24] + mi := &file_core_v1_core_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2184,7 +2276,7 @@ func (x *SetOperation) ProtoReflect() protoreflect.Message { // Deprecated: Use SetOperation.ProtoReflect.Descriptor instead. func (*SetOperation) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{24} + return file_core_v1_core_proto_rawDescGZIP(), []int{25} } func (x *SetOperation) GetChild() []*SetOperation_Child { @@ -2207,7 +2299,7 @@ type TupleToUserset struct { func (x *TupleToUserset) Reset() { *x = TupleToUserset{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[25] + mi := &file_core_v1_core_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2220,7 +2312,7 @@ func (x *TupleToUserset) String() string { func (*TupleToUserset) ProtoMessage() {} func (x *TupleToUserset) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[25] + mi := &file_core_v1_core_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2233,7 +2325,7 @@ func (x *TupleToUserset) ProtoReflect() protoreflect.Message { // Deprecated: Use TupleToUserset.ProtoReflect.Descriptor instead. func (*TupleToUserset) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{25} + return file_core_v1_core_proto_rawDescGZIP(), []int{26} } func (x *TupleToUserset) GetTupleset() *TupleToUserset_Tupleset { @@ -2271,7 +2363,7 @@ type FunctionedTupleToUserset struct { func (x *FunctionedTupleToUserset) Reset() { *x = FunctionedTupleToUserset{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[26] + mi := &file_core_v1_core_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2284,7 +2376,7 @@ func (x *FunctionedTupleToUserset) String() string { func (*FunctionedTupleToUserset) ProtoMessage() {} func (x *FunctionedTupleToUserset) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[26] + mi := &file_core_v1_core_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2297,7 +2389,7 @@ func (x *FunctionedTupleToUserset) ProtoReflect() protoreflect.Message { // Deprecated: Use FunctionedTupleToUserset.ProtoReflect.Descriptor instead. func (*FunctionedTupleToUserset) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{26} + return file_core_v1_core_proto_rawDescGZIP(), []int{27} } func (x *FunctionedTupleToUserset) GetFunction() FunctionedTupleToUserset_Function { @@ -2341,7 +2433,7 @@ type ComputedUserset struct { func (x *ComputedUserset) Reset() { *x = ComputedUserset{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[27] + mi := &file_core_v1_core_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2354,7 +2446,7 @@ func (x *ComputedUserset) String() string { func (*ComputedUserset) ProtoMessage() {} func (x *ComputedUserset) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[27] + mi := &file_core_v1_core_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2367,7 +2459,7 @@ func (x *ComputedUserset) ProtoReflect() protoreflect.Message { // Deprecated: Use ComputedUserset.ProtoReflect.Descriptor instead. func (*ComputedUserset) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{27} + return file_core_v1_core_proto_rawDescGZIP(), []int{28} } func (x *ComputedUserset) GetObject() ComputedUserset_Object { @@ -2403,7 +2495,7 @@ type SourcePosition struct { func (x *SourcePosition) Reset() { *x = SourcePosition{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[28] + mi := &file_core_v1_core_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2416,7 +2508,7 @@ func (x *SourcePosition) String() string { func (*SourcePosition) ProtoMessage() {} func (x *SourcePosition) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[28] + mi := &file_core_v1_core_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2429,7 +2521,7 @@ func (x *SourcePosition) ProtoReflect() protoreflect.Message { // Deprecated: Use SourcePosition.ProtoReflect.Descriptor instead. func (*SourcePosition) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{28} + return file_core_v1_core_proto_rawDescGZIP(), []int{29} } func (x *SourcePosition) GetZeroIndexedLineNumber() uint64 { @@ -2461,7 +2553,7 @@ type CaveatExpression struct { func (x *CaveatExpression) Reset() { *x = CaveatExpression{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[29] + mi := &file_core_v1_core_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2474,7 +2566,7 @@ func (x *CaveatExpression) String() string { func (*CaveatExpression) ProtoMessage() {} func (x *CaveatExpression) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[29] + mi := &file_core_v1_core_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2487,7 +2579,7 @@ func (x *CaveatExpression) ProtoReflect() protoreflect.Message { // Deprecated: Use CaveatExpression.ProtoReflect.Descriptor instead. func (*CaveatExpression) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{29} + return file_core_v1_core_proto_rawDescGZIP(), []int{30} } func (m *CaveatExpression) GetOperationOrCaveat() isCaveatExpression_OperationOrCaveat { @@ -2539,7 +2631,7 @@ type CaveatOperation struct { func (x *CaveatOperation) Reset() { *x = CaveatOperation{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[30] + mi := &file_core_v1_core_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2552,7 +2644,7 @@ func (x *CaveatOperation) String() string { func (*CaveatOperation) ProtoMessage() {} func (x *CaveatOperation) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[30] + mi := &file_core_v1_core_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2565,7 +2657,7 @@ func (x *CaveatOperation) ProtoReflect() protoreflect.Message { // Deprecated: Use CaveatOperation.ProtoReflect.Descriptor instead. func (*CaveatOperation) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{30} + return file_core_v1_core_proto_rawDescGZIP(), []int{31} } func (x *CaveatOperation) GetOp() CaveatOperation_Operation { @@ -2605,7 +2697,7 @@ type RelationshipFilter struct { func (x *RelationshipFilter) Reset() { *x = RelationshipFilter{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[31] + mi := &file_core_v1_core_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2618,7 +2710,7 @@ func (x *RelationshipFilter) String() string { func (*RelationshipFilter) ProtoMessage() {} func (x *RelationshipFilter) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[31] + mi := &file_core_v1_core_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2631,7 +2723,7 @@ func (x *RelationshipFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use RelationshipFilter.ProtoReflect.Descriptor instead. func (*RelationshipFilter) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{31} + return file_core_v1_core_proto_rawDescGZIP(), []int{32} } func (x *RelationshipFilter) GetResourceType() string { @@ -2686,7 +2778,7 @@ type SubjectFilter struct { func (x *SubjectFilter) Reset() { *x = SubjectFilter{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[32] + mi := &file_core_v1_core_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2699,7 +2791,7 @@ func (x *SubjectFilter) String() string { func (*SubjectFilter) ProtoMessage() {} func (x *SubjectFilter) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[32] + mi := &file_core_v1_core_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2712,7 +2804,7 @@ func (x *SubjectFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use SubjectFilter.ProtoReflect.Descriptor instead. func (*SubjectFilter) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{32} + return file_core_v1_core_proto_rawDescGZIP(), []int{33} } func (x *SubjectFilter) GetSubjectType() string { @@ -2745,7 +2837,7 @@ type AllowedRelation_PublicWildcard struct { func (x *AllowedRelation_PublicWildcard) Reset() { *x = AllowedRelation_PublicWildcard{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[36] + mi := &file_core_v1_core_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2758,7 +2850,7 @@ func (x *AllowedRelation_PublicWildcard) String() string { func (*AllowedRelation_PublicWildcard) ProtoMessage() {} func (x *AllowedRelation_PublicWildcard) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[36] + mi := &file_core_v1_core_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2771,7 +2863,7 @@ func (x *AllowedRelation_PublicWildcard) ProtoReflect() protoreflect.Message { // Deprecated: Use AllowedRelation_PublicWildcard.ProtoReflect.Descriptor instead. func (*AllowedRelation_PublicWildcard) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{20, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{21, 0} } type SetOperation_Child struct { @@ -2800,7 +2892,7 @@ type SetOperation_Child struct { func (x *SetOperation_Child) Reset() { *x = SetOperation_Child{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[37] + mi := &file_core_v1_core_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2813,7 +2905,7 @@ func (x *SetOperation_Child) String() string { func (*SetOperation_Child) ProtoMessage() {} func (x *SetOperation_Child) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[37] + mi := &file_core_v1_core_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2826,7 +2918,7 @@ func (x *SetOperation_Child) ProtoReflect() protoreflect.Message { // Deprecated: Use SetOperation_Child.ProtoReflect.Descriptor instead. func (*SetOperation_Child) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{24, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{25, 0} } func (m *SetOperation_Child) GetChildType() isSetOperation_Child_ChildType { @@ -2941,7 +3033,7 @@ type SetOperation_Child_This struct { func (x *SetOperation_Child_This) Reset() { *x = SetOperation_Child_This{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[38] + mi := &file_core_v1_core_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2954,7 +3046,7 @@ func (x *SetOperation_Child_This) String() string { func (*SetOperation_Child_This) ProtoMessage() {} func (x *SetOperation_Child_This) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[38] + mi := &file_core_v1_core_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2967,7 +3059,7 @@ func (x *SetOperation_Child_This) ProtoReflect() protoreflect.Message { // Deprecated: Use SetOperation_Child_This.ProtoReflect.Descriptor instead. func (*SetOperation_Child_This) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{24, 0, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{25, 0, 0} } type SetOperation_Child_Nil struct { @@ -2979,7 +3071,7 @@ type SetOperation_Child_Nil struct { func (x *SetOperation_Child_Nil) Reset() { *x = SetOperation_Child_Nil{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[39] + mi := &file_core_v1_core_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2992,7 +3084,7 @@ func (x *SetOperation_Child_Nil) String() string { func (*SetOperation_Child_Nil) ProtoMessage() {} func (x *SetOperation_Child_Nil) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[39] + mi := &file_core_v1_core_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3005,7 +3097,7 @@ func (x *SetOperation_Child_Nil) ProtoReflect() protoreflect.Message { // Deprecated: Use SetOperation_Child_Nil.ProtoReflect.Descriptor instead. func (*SetOperation_Child_Nil) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{24, 0, 1} + return file_core_v1_core_proto_rawDescGZIP(), []int{25, 0, 1} } type TupleToUserset_Tupleset struct { @@ -3019,7 +3111,7 @@ type TupleToUserset_Tupleset struct { func (x *TupleToUserset_Tupleset) Reset() { *x = TupleToUserset_Tupleset{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[40] + mi := &file_core_v1_core_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3032,7 +3124,7 @@ func (x *TupleToUserset_Tupleset) String() string { func (*TupleToUserset_Tupleset) ProtoMessage() {} func (x *TupleToUserset_Tupleset) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[40] + mi := &file_core_v1_core_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3045,7 +3137,7 @@ func (x *TupleToUserset_Tupleset) ProtoReflect() protoreflect.Message { // Deprecated: Use TupleToUserset_Tupleset.ProtoReflect.Descriptor instead. func (*TupleToUserset_Tupleset) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{25, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{26, 0} } func (x *TupleToUserset_Tupleset) GetRelation() string { @@ -3066,7 +3158,7 @@ type FunctionedTupleToUserset_Tupleset struct { func (x *FunctionedTupleToUserset_Tupleset) Reset() { *x = FunctionedTupleToUserset_Tupleset{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[41] + mi := &file_core_v1_core_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3079,7 +3171,7 @@ func (x *FunctionedTupleToUserset_Tupleset) String() string { func (*FunctionedTupleToUserset_Tupleset) ProtoMessage() {} func (x *FunctionedTupleToUserset_Tupleset) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[41] + mi := &file_core_v1_core_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3092,7 +3184,7 @@ func (x *FunctionedTupleToUserset_Tupleset) ProtoReflect() protoreflect.Message // Deprecated: Use FunctionedTupleToUserset_Tupleset.ProtoReflect.Descriptor instead. func (*FunctionedTupleToUserset_Tupleset) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{26, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{27, 0} } func (x *FunctionedTupleToUserset_Tupleset) GetRelation() string { @@ -3113,7 +3205,7 @@ type SubjectFilter_RelationFilter struct { func (x *SubjectFilter_RelationFilter) Reset() { *x = SubjectFilter_RelationFilter{} if protoimpl.UnsafeEnabled { - mi := &file_core_v1_core_proto_msgTypes[42] + mi := &file_core_v1_core_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3126,7 +3218,7 @@ func (x *SubjectFilter_RelationFilter) String() string { func (*SubjectFilter_RelationFilter) ProtoMessage() {} func (x *SubjectFilter_RelationFilter) ProtoReflect() protoreflect.Message { - mi := &file_core_v1_core_proto_msgTypes[42] + mi := &file_core_v1_core_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3139,7 +3231,7 @@ func (x *SubjectFilter_RelationFilter) ProtoReflect() protoreflect.Message { // Deprecated: Use SubjectFilter_RelationFilter.ProtoReflect.Descriptor instead. func (*SubjectFilter_RelationFilter) Descriptor() ([]byte, []int) { - return file_core_v1_core_proto_rawDescGZIP(), []int{32, 0} + return file_core_v1_core_proto_rawDescGZIP(), []int{33, 0} } func (x *SubjectFilter_RelationFilter) GetRelation() string { @@ -3346,7 +3438,7 @@ var file_core_v1_core_proto_rawDesc = []byte{ 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x93, 0x02, 0x0a, 0x13, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x73, 0x61, 0x67, 0x65, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, @@ -3363,399 +3455,416 @@ var file_core_v1_core_proto_rawDesc = []byte{ 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe1, 0x03, 0x0a, 0x08, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, - 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, - 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, - 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, - 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, - 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, - 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, 0x79, 0x70, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x08, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x11, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x61, 0x6e, - 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, - 0x6c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x64, 0x65, 0x70, - 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x64, - 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xf4, - 0x03, 0x0a, 0x11, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x12, 0x77, 0x0a, 0x1b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x18, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x83, 0x01, - 0x0a, 0x1f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, - 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, - 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1c, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x1d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x71, 0x0a, 0x21, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xce, - 0x04, 0x0a, 0x16, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x4e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, - 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x0f, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, - 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x64, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0xf8, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, + 0x52, 0x0f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x28, 0x80, + 0x02, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x0f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd4, 0x03, + 0x0a, 0x08, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, + 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, + 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, + 0x24, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, + 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x74, + 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, + 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x2b, 0x0a, 0x11, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, + 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, + 0x69, 0x63, 0x61, 0x6c, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x0b, + 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, + 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xf4, 0x03, 0x0a, 0x11, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x77, 0x0a, 0x1b, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x38, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x1f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x47, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1c, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x1d, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x71, 0x0a, 0x21, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x63, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x1a, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, - 0x6e, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, - 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x43, - 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, - 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, - 0x54, 0x55, 0x50, 0x4c, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x54, 0x4f, 0x5f, 0x55, 0x53, 0x45, 0x52, - 0x53, 0x45, 0x54, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x02, - 0x22, 0x57, 0x0a, 0x16, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, - 0x41, 0x43, 0x48, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, - 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, - 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, - 0x65, 0x0a, 0x0f, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xda, 0x04, 0x0a, 0x0f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x09, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, - 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, - 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, - 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, - 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, - 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xfa, 0x42, 0x2d, 0x72, 0x2b, 0x28, 0x40, 0x32, 0x27, 0x5e, - 0x28, 0x5c, 0x2e, 0x5c, 0x2e, 0x5c, 0x2e, 0x7c, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x24, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x77, 0x69, 0x6c, - 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, - 0x63, 0x61, 0x72, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, - 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, 0x49, 0x0a, 0x13, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, - 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x1a, 0x10, 0x0a, 0x0e, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x42, 0x16, 0x0a, 0x14, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x72, 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, - 0x61, 0x72, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x22, 0x30, 0x0a, 0x0d, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x76, 0x65, 0x61, - 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xad, 0x02, 0x0a, 0x0e, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x75, - 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x05, 0x75, - 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0c, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x65, - 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, - 0x00, 0x52, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, + 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0b, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, + 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xce, 0x04, 0x0a, 0x16, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x4e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x52, + 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, + 0x43, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x75, + 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, + 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x1a, 0x52, 0x65, + 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4c, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, + 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x53, + 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, 0x4f, 0x49, 0x4e, 0x54, + 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x54, + 0x4f, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x50, + 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x22, 0x57, 0x0a, 0x16, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x41, 0x43, 0x48, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x43, 0x4f, + 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, + 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x4a, + 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x65, 0x0a, 0x0f, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x18, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x44, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xcd, 0x04, 0x0a, + 0x0f, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x66, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, + 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, + 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, + 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, + 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x09, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xfa, 0x42, 0x2d, 0x72, + 0x2b, 0x28, 0x40, 0x32, 0x27, 0x5e, 0x28, 0x5c, 0x2e, 0x5c, 0x2e, 0x5c, 0x2e, 0x7c, 0x5b, 0x61, + 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, + 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x24, 0x48, 0x00, 0x52, 0x08, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, - 0x0a, 0x11, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xb2, 0x05, 0x0a, 0x0c, 0x53, 0x65, 0x74, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x05, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x43, 0x68, 0x69, 0x6c, 0x64, 0x42, 0x0f, 0xfa, 0x42, 0x0c, 0x92, 0x01, 0x09, 0x08, 0x01, 0x22, - 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x1a, 0xdd, 0x04, - 0x0a, 0x05, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x37, 0x0a, 0x05, 0x5f, 0x74, 0x68, 0x69, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, - 0x69, 0x6c, 0x64, 0x2e, 0x54, 0x68, 0x69, 0x73, 0x48, 0x00, 0x52, 0x04, 0x54, 0x68, 0x69, 0x73, - 0x12, 0x4f, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, - 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, + 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x52, + 0x0e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x12, + 0x49, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x64, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x10, 0x0a, 0x0e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x57, 0x69, 0x6c, 0x64, + 0x63, 0x61, 0x72, 0x64, 0x42, 0x16, 0x0a, 0x14, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x6f, 0x72, 0x5f, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x11, 0x0a, 0x0f, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x22, + 0x30, 0x0a, 0x0d, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0xad, 0x02, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, + 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, + 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, + 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, + 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x09, 0x65, 0x78, 0x63, 0x6c, + 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x18, 0x0a, 0x11, 0x72, 0x65, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x03, 0xf8, 0x42, + 0x01, 0x22, 0xb2, 0x05, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x42, 0x0f, + 0xfa, 0x42, 0x0c, 0x92, 0x01, 0x09, 0x08, 0x01, 0x22, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, + 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x1a, 0xdd, 0x04, 0x0a, 0x05, 0x43, 0x68, 0x69, 0x6c, 0x64, + 0x12, 0x37, 0x0a, 0x05, 0x5f, 0x74, 0x68, 0x69, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x54, 0x68, 0x69, + 0x73, 0x48, 0x00, 0x52, 0x04, 0x54, 0x68, 0x69, 0x73, 0x12, 0x4f, 0x0a, 0x10, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, + 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x74, 0x75, + 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, + 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x74, 0x75, 0x70, 0x6c, 0x65, + 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, + 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x1b, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, + 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, + 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x18, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x5f, 0x6e, 0x69, 0x6c, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, + 0x2e, 0x4e, 0x69, 0x6c, 0x48, 0x00, 0x52, 0x03, 0x4e, 0x69, 0x6c, 0x12, 0x40, 0x0a, 0x0f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, + 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x61, 0x74, 0x68, 0x1a, 0x06, 0x0a, 0x04, 0x54, 0x68, 0x69, 0x73, 0x1a, 0x05, 0x0a, 0x03, + 0x4e, 0x69, 0x6c, 0x42, 0x11, 0x0a, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xba, 0x02, 0x0a, 0x0e, 0x54, 0x75, 0x70, 0x6c, 0x65, + 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x46, 0x0a, 0x08, 0x74, 0x75, 0x70, + 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, - 0x52, 0x0e, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, - 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x72, - 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x0e, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x52, 0x65, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x6c, - 0x0a, 0x1b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x75, 0x70, - 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, - 0x48, 0x00, 0x52, 0x18, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, - 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x34, 0x0a, 0x04, - 0x5f, 0x6e, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x2e, 0x4e, 0x69, 0x6c, 0x48, 0x00, 0x52, 0x03, 0x4e, - 0x69, 0x6c, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x06, 0x0a, 0x04, 0x54, - 0x68, 0x69, 0x73, 0x1a, 0x05, 0x0a, 0x03, 0x4e, 0x69, 0x6c, 0x42, 0x11, 0x0a, 0x0a, 0x63, 0x68, - 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, 0x03, 0xf8, 0x42, 0x01, 0x22, 0xba, 0x02, - 0x0a, 0x0e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, - 0x12, 0x46, 0x0a, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, - 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, - 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, - 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, - 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, - 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, - 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xec, 0x03, 0x0a, 0x18, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x52, 0x0a, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, - 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x46, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x82, 0x01, 0x04, 0x10, 0x01, 0x20, - 0x00, 0x52, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x74, - 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x72, 0x73, 0x65, 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, + 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, + 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, + 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, + 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, + 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0xec, 0x03, 0x0a, 0x18, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, - 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, - 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, - 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, - 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, - 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, - 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x48, 0x0a, 0x08, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x14, 0x46, - 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x02, 0x22, 0x91, 0x02, 0x0a, 0x0f, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x41, 0x0a, - 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, - 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x08, - 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, - 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, - 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x12, 0x52, 0x0a, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x54, 0x6f, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, + 0xfa, 0x42, 0x07, 0x82, 0x01, 0x04, 0x10, 0x01, 0x20, 0x00, 0x52, 0x08, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x54, 0x75, 0x70, 0x6c, 0x65, + 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, + 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x75, + 0x70, 0x6c, 0x65, 0x73, 0x65, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, + 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x8a, + 0x01, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, - 0x54, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x55, 0x50, 0x4c, 0x45, 0x5f, 0x55, 0x53, 0x45, - 0x52, 0x53, 0x45, 0x54, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x01, 0x22, 0x8a, 0x01, - 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x37, 0x0a, 0x18, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, - 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x15, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x4c, - 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x1c, 0x7a, 0x65, 0x72, - 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, - 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x19, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x01, 0x0a, 0x10, 0x43, - 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, - 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x09, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x76, - 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x76, 0x65, - 0x61, 0x74, 0x42, 0x15, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x6f, 0x72, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x22, 0xb0, 0x01, 0x0a, 0x0f, 0x43, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, - 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, - 0x70, 0x12, 0x35, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, - 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x32, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, - 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x4e, 0x4f, 0x54, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, - 0x12, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0xfa, 0x42, 0x48, 0x72, - 0x46, 0x28, 0x80, 0x01, 0x32, 0x41, 0x5e, 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, - 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, - 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, - 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, - 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, - 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, 0x52, 0x12, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x64, - 0x0a, 0x1b, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x4f, 0x0a, 0x08, 0x54, 0x75, 0x70, 0x6c, 0x65, + 0x73, 0x65, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, + 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, + 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x08, 0x46, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, + 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4e, 0x59, 0x10, 0x01, + 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c, 0x4c, + 0x10, 0x02, 0x22, 0x91, 0x02, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, 0x12, 0x41, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x65, 0x74, + 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, + 0x01, 0x52, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x27, 0xfa, 0x42, 0x24, + 0x72, 0x22, 0x28, 0x40, 0x32, 0x1e, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, + 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, + 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, + 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x34, 0x0a, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x55, + 0x50, 0x4c, 0x45, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, + 0x54, 0x55, 0x50, 0x4c, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x53, 0x45, 0x54, 0x5f, 0x4f, 0x42, + 0x4a, 0x45, 0x43, 0x54, 0x10, 0x01, 0x22, 0x8a, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x18, 0x7a, 0x65, 0x72, + 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x7a, 0x65, 0x72, + 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x1c, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x7a, 0x65, 0x72, 0x6f, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x9c, 0x01, 0x0a, 0x10, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, + 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x75, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x61, 0x76, 0x65, 0x61, + 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x42, 0x15, 0x0a, 0x13, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x72, 0x5f, 0x63, 0x61, 0x76, 0x65, + 0x61, 0x74, 0x22, 0xb0, 0x01, 0x0a, 0x0f, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, + 0x65, 0x61, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x35, 0x0a, 0x08, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x45, 0x78, 0x70, + 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, + 0x6e, 0x22, 0x32, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, + 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, + 0x52, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, + 0x4e, 0x4f, 0x54, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, 0x12, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0d, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x4b, 0xfa, 0x42, 0x48, 0x72, 0x46, 0x28, 0x80, 0x01, 0x32, 0x41, 0x5e, + 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, + 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, + 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, + 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, + 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x57, + 0x0a, 0x14, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, + 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, + 0x29, 0x3f, 0x24, 0x52, 0x12, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x64, 0x0a, 0x1b, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x25, 0xfa, 0x42, + 0x22, 0x72, 0x20, 0x28, 0x80, 0x08, 0x32, 0x1b, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, + 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, + 0x29, 0x3f, 0x24, 0x52, 0x18, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x57, 0x0a, + 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, + 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, + 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, + 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x86, 0x03, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x6b, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, + 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, + 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, + 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x13, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x80, 0x08, 0x32, 0x20, 0x5e, 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, - 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x3f, 0x24, 0x52, 0x18, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x57, 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, - 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, - 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x10, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, - 0x17, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x86, 0x03, - 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, - 0x6b, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x48, 0xfa, 0x42, 0x45, 0x72, 0x43, 0x28, 0x80, 0x01, 0x32, - 0x3e, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, - 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x31, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2f, - 0x29, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, - 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x24, 0x52, - 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x13, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, - 0x28, 0x80, 0x08, 0x32, 0x20, 0x5e, 0x28, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, - 0x2d, 0x39, 0x2f, 0x5f, 0x7c, 0x5c, 0x2d, 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x7c, - 0x5c, 0x2a, 0x29, 0x3f, 0x24, 0x52, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x58, 0x0a, 0x0e, - 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x46, - 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, 0x28, 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, - 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, - 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x08, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x6a, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x45, 0x50, - 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, - 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x41, - 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x50, 0x52, 0x45, - 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x02, 0x42, 0x8a, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x42, 0x09, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, - 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, - 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x43, 0x6f, 0x72, - 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, - 0x13, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x43, 0x6f, 0x72, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x3d, 0x2b, 0x5d, 0x7b, 0x31, 0x2c, 0x7d, 0x29, 0x7c, 0x5c, 0x2a, 0x29, 0x3f, 0x24, 0x52, 0x11, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x64, 0x12, 0x52, 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x58, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xfa, 0x42, 0x27, 0x72, 0x25, + 0x28, 0x40, 0x32, 0x21, 0x5e, 0x28, 0x5b, 0x61, 0x2d, 0x7a, 0x5d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, + 0x2d, 0x39, 0x5f, 0x5d, 0x7b, 0x31, 0x2c, 0x36, 0x32, 0x7d, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, + 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2a, + 0x6a, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, + 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, + 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x42, 0x8a, 0x01, 0x0a, 0x0b, + 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x43, 0x6f, 0x72, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, + 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, + 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, + 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x13, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, + 0x43, 0x6f, 0x72, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3771,7 +3880,7 @@ func file_core_v1_core_proto_rawDescGZIP() []byte { } var file_core_v1_core_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_core_v1_core_proto_msgTypes = make([]protoimpl.MessageInfo, 43) +var file_core_v1_core_proto_msgTypes = make([]protoimpl.MessageInfo, 44) var file_core_v1_core_proto_goTypes = []any{ (DeprecationType)(0), // 0: core.v1.DeprecationType (RelationTupleUpdate_Operation)(0), // 1: core.v1.RelationTupleUpdate.Operation @@ -3796,118 +3905,122 @@ var file_core_v1_core_proto_goTypes = []any{ (*DirectSubjects)(nil), // 20: core.v1.DirectSubjects (*Metadata)(nil), // 21: core.v1.Metadata (*NamespaceDefinition)(nil), // 22: core.v1.NamespaceDefinition - (*Relation)(nil), // 23: core.v1.Relation - (*ReachabilityGraph)(nil), // 24: core.v1.ReachabilityGraph - (*ReachabilityEntrypoints)(nil), // 25: core.v1.ReachabilityEntrypoints - (*ReachabilityEntrypoint)(nil), // 26: core.v1.ReachabilityEntrypoint - (*TypeInformation)(nil), // 27: core.v1.TypeInformation - (*AllowedRelation)(nil), // 28: core.v1.AllowedRelation - (*ExpirationTrait)(nil), // 29: core.v1.ExpirationTrait - (*AllowedCaveat)(nil), // 30: core.v1.AllowedCaveat - (*UsersetRewrite)(nil), // 31: core.v1.UsersetRewrite - (*SetOperation)(nil), // 32: core.v1.SetOperation - (*TupleToUserset)(nil), // 33: core.v1.TupleToUserset - (*FunctionedTupleToUserset)(nil), // 34: core.v1.FunctionedTupleToUserset - (*ComputedUserset)(nil), // 35: core.v1.ComputedUserset - (*SourcePosition)(nil), // 36: core.v1.SourcePosition - (*CaveatExpression)(nil), // 37: core.v1.CaveatExpression - (*CaveatOperation)(nil), // 38: core.v1.CaveatOperation - (*RelationshipFilter)(nil), // 39: core.v1.RelationshipFilter - (*SubjectFilter)(nil), // 40: core.v1.SubjectFilter - nil, // 41: core.v1.CaveatDefinition.ParameterTypesEntry - nil, // 42: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry - nil, // 43: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry - (*AllowedRelation_PublicWildcard)(nil), // 44: core.v1.AllowedRelation.PublicWildcard - (*SetOperation_Child)(nil), // 45: core.v1.SetOperation.Child - (*SetOperation_Child_This)(nil), // 46: core.v1.SetOperation.Child.This - (*SetOperation_Child_Nil)(nil), // 47: core.v1.SetOperation.Child.Nil - (*TupleToUserset_Tupleset)(nil), // 48: core.v1.TupleToUserset.Tupleset - (*FunctionedTupleToUserset_Tupleset)(nil), // 49: core.v1.FunctionedTupleToUserset.Tupleset - (*SubjectFilter_RelationFilter)(nil), // 50: core.v1.SubjectFilter.RelationFilter - (*timestamppb.Timestamp)(nil), // 51: google.protobuf.Timestamp - (*structpb.Struct)(nil), // 52: google.protobuf.Struct - (*anypb.Any)(nil), // 53: google.protobuf.Any + (*Deprecation)(nil), // 23: core.v1.Deprecation + (*Relation)(nil), // 24: core.v1.Relation + (*ReachabilityGraph)(nil), // 25: core.v1.ReachabilityGraph + (*ReachabilityEntrypoints)(nil), // 26: core.v1.ReachabilityEntrypoints + (*ReachabilityEntrypoint)(nil), // 27: core.v1.ReachabilityEntrypoint + (*TypeInformation)(nil), // 28: core.v1.TypeInformation + (*AllowedRelation)(nil), // 29: core.v1.AllowedRelation + (*ExpirationTrait)(nil), // 30: core.v1.ExpirationTrait + (*AllowedCaveat)(nil), // 31: core.v1.AllowedCaveat + (*UsersetRewrite)(nil), // 32: core.v1.UsersetRewrite + (*SetOperation)(nil), // 33: core.v1.SetOperation + (*TupleToUserset)(nil), // 34: core.v1.TupleToUserset + (*FunctionedTupleToUserset)(nil), // 35: core.v1.FunctionedTupleToUserset + (*ComputedUserset)(nil), // 36: core.v1.ComputedUserset + (*SourcePosition)(nil), // 37: core.v1.SourcePosition + (*CaveatExpression)(nil), // 38: core.v1.CaveatExpression + (*CaveatOperation)(nil), // 39: core.v1.CaveatOperation + (*RelationshipFilter)(nil), // 40: core.v1.RelationshipFilter + (*SubjectFilter)(nil), // 41: core.v1.SubjectFilter + nil, // 42: core.v1.CaveatDefinition.ParameterTypesEntry + nil, // 43: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry + nil, // 44: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry + (*AllowedRelation_PublicWildcard)(nil), // 45: core.v1.AllowedRelation.PublicWildcard + (*SetOperation_Child)(nil), // 46: core.v1.SetOperation.Child + (*SetOperation_Child_This)(nil), // 47: core.v1.SetOperation.Child.This + (*SetOperation_Child_Nil)(nil), // 48: core.v1.SetOperation.Child.Nil + (*TupleToUserset_Tupleset)(nil), // 49: core.v1.TupleToUserset.Tupleset + (*FunctionedTupleToUserset_Tupleset)(nil), // 50: core.v1.FunctionedTupleToUserset.Tupleset + (*SubjectFilter_RelationFilter)(nil), // 51: core.v1.SubjectFilter.RelationFilter + (*timestamppb.Timestamp)(nil), // 52: google.protobuf.Timestamp + (*structpb.Struct)(nil), // 53: google.protobuf.Struct + (*anypb.Any)(nil), // 54: google.protobuf.Any } var file_core_v1_core_proto_depIdxs = []int32{ 13, // 0: core.v1.RelationTuple.resource_and_relation:type_name -> core.v1.ObjectAndRelation 13, // 1: core.v1.RelationTuple.subject:type_name -> core.v1.ObjectAndRelation 10, // 2: core.v1.RelationTuple.caveat:type_name -> core.v1.ContextualizedCaveat 9, // 3: core.v1.RelationTuple.integrity:type_name -> core.v1.RelationshipIntegrity - 51, // 4: core.v1.RelationTuple.optional_expiration_time:type_name -> google.protobuf.Timestamp - 51, // 5: core.v1.RelationshipIntegrity.hashed_at:type_name -> google.protobuf.Timestamp - 52, // 6: core.v1.ContextualizedCaveat.context:type_name -> google.protobuf.Struct - 41, // 7: core.v1.CaveatDefinition.parameter_types:type_name -> core.v1.CaveatDefinition.ParameterTypesEntry + 52, // 4: core.v1.RelationTuple.optional_expiration_time:type_name -> google.protobuf.Timestamp + 52, // 5: core.v1.RelationshipIntegrity.hashed_at:type_name -> google.protobuf.Timestamp + 53, // 6: core.v1.ContextualizedCaveat.context:type_name -> google.protobuf.Struct + 42, // 7: core.v1.CaveatDefinition.parameter_types:type_name -> core.v1.CaveatDefinition.ParameterTypesEntry 21, // 8: core.v1.CaveatDefinition.metadata:type_name -> core.v1.Metadata - 36, // 9: core.v1.CaveatDefinition.source_position:type_name -> core.v1.SourcePosition + 37, // 9: core.v1.CaveatDefinition.source_position:type_name -> core.v1.SourcePosition 12, // 10: core.v1.CaveatTypeReference.child_types:type_name -> core.v1.CaveatTypeReference 1, // 11: core.v1.RelationTupleUpdate.operation:type_name -> core.v1.RelationTupleUpdate.Operation 8, // 12: core.v1.RelationTupleUpdate.tuple:type_name -> core.v1.RelationTuple 18, // 13: core.v1.RelationTupleTreeNode.intermediate_node:type_name -> core.v1.SetOperationUserset 20, // 14: core.v1.RelationTupleTreeNode.leaf_node:type_name -> core.v1.DirectSubjects 13, // 15: core.v1.RelationTupleTreeNode.expanded:type_name -> core.v1.ObjectAndRelation - 37, // 16: core.v1.RelationTupleTreeNode.caveat_expression:type_name -> core.v1.CaveatExpression + 38, // 16: core.v1.RelationTupleTreeNode.caveat_expression:type_name -> core.v1.CaveatExpression 2, // 17: core.v1.SetOperationUserset.operation:type_name -> core.v1.SetOperationUserset.Operation 17, // 18: core.v1.SetOperationUserset.child_nodes:type_name -> core.v1.RelationTupleTreeNode 13, // 19: core.v1.DirectSubject.subject:type_name -> core.v1.ObjectAndRelation - 37, // 20: core.v1.DirectSubject.caveat_expression:type_name -> core.v1.CaveatExpression + 38, // 20: core.v1.DirectSubject.caveat_expression:type_name -> core.v1.CaveatExpression 19, // 21: core.v1.DirectSubjects.subjects:type_name -> core.v1.DirectSubject - 53, // 22: core.v1.Metadata.metadata_message:type_name -> google.protobuf.Any - 23, // 23: core.v1.NamespaceDefinition.relation:type_name -> core.v1.Relation + 54, // 22: core.v1.Metadata.metadata_message:type_name -> google.protobuf.Any + 24, // 23: core.v1.NamespaceDefinition.relation:type_name -> core.v1.Relation 21, // 24: core.v1.NamespaceDefinition.metadata:type_name -> core.v1.Metadata - 36, // 25: core.v1.NamespaceDefinition.source_position:type_name -> core.v1.SourcePosition - 31, // 26: core.v1.Relation.userset_rewrite:type_name -> core.v1.UsersetRewrite - 27, // 27: core.v1.Relation.type_information:type_name -> core.v1.TypeInformation - 21, // 28: core.v1.Relation.metadata:type_name -> core.v1.Metadata - 36, // 29: core.v1.Relation.source_position:type_name -> core.v1.SourcePosition - 0, // 30: core.v1.Relation.deprecation_type:type_name -> core.v1.DeprecationType - 42, // 31: core.v1.ReachabilityGraph.entrypoints_by_subject_type:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry - 43, // 32: core.v1.ReachabilityGraph.entrypoints_by_subject_relation:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry - 26, // 33: core.v1.ReachabilityEntrypoints.entrypoints:type_name -> core.v1.ReachabilityEntrypoint - 14, // 34: core.v1.ReachabilityEntrypoints.subject_relation:type_name -> core.v1.RelationReference - 3, // 35: core.v1.ReachabilityEntrypoint.kind:type_name -> core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind - 14, // 36: core.v1.ReachabilityEntrypoint.target_relation:type_name -> core.v1.RelationReference - 4, // 37: core.v1.ReachabilityEntrypoint.result_status:type_name -> core.v1.ReachabilityEntrypoint.EntrypointResultStatus - 28, // 38: core.v1.TypeInformation.allowed_direct_relations:type_name -> core.v1.AllowedRelation - 44, // 39: core.v1.AllowedRelation.public_wildcard:type_name -> core.v1.AllowedRelation.PublicWildcard - 36, // 40: core.v1.AllowedRelation.source_position:type_name -> core.v1.SourcePosition - 30, // 41: core.v1.AllowedRelation.required_caveat:type_name -> core.v1.AllowedCaveat - 29, // 42: core.v1.AllowedRelation.required_expiration:type_name -> core.v1.ExpirationTrait - 0, // 43: core.v1.AllowedRelation.deprecation_type:type_name -> core.v1.DeprecationType - 32, // 44: core.v1.UsersetRewrite.union:type_name -> core.v1.SetOperation - 32, // 45: core.v1.UsersetRewrite.intersection:type_name -> core.v1.SetOperation - 32, // 46: core.v1.UsersetRewrite.exclusion:type_name -> core.v1.SetOperation - 36, // 47: core.v1.UsersetRewrite.source_position:type_name -> core.v1.SourcePosition - 45, // 48: core.v1.SetOperation.child:type_name -> core.v1.SetOperation.Child - 48, // 49: core.v1.TupleToUserset.tupleset:type_name -> core.v1.TupleToUserset.Tupleset - 35, // 50: core.v1.TupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset - 36, // 51: core.v1.TupleToUserset.source_position:type_name -> core.v1.SourcePosition - 5, // 52: core.v1.FunctionedTupleToUserset.function:type_name -> core.v1.FunctionedTupleToUserset.Function - 49, // 53: core.v1.FunctionedTupleToUserset.tupleset:type_name -> core.v1.FunctionedTupleToUserset.Tupleset - 35, // 54: core.v1.FunctionedTupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset - 36, // 55: core.v1.FunctionedTupleToUserset.source_position:type_name -> core.v1.SourcePosition - 6, // 56: core.v1.ComputedUserset.object:type_name -> core.v1.ComputedUserset.Object - 36, // 57: core.v1.ComputedUserset.source_position:type_name -> core.v1.SourcePosition - 38, // 58: core.v1.CaveatExpression.operation:type_name -> core.v1.CaveatOperation - 10, // 59: core.v1.CaveatExpression.caveat:type_name -> core.v1.ContextualizedCaveat - 7, // 60: core.v1.CaveatOperation.op:type_name -> core.v1.CaveatOperation.Operation - 37, // 61: core.v1.CaveatOperation.children:type_name -> core.v1.CaveatExpression - 40, // 62: core.v1.RelationshipFilter.optional_subject_filter:type_name -> core.v1.SubjectFilter - 50, // 63: core.v1.SubjectFilter.optional_relation:type_name -> core.v1.SubjectFilter.RelationFilter - 12, // 64: core.v1.CaveatDefinition.ParameterTypesEntry.value:type_name -> core.v1.CaveatTypeReference - 25, // 65: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry.value:type_name -> core.v1.ReachabilityEntrypoints - 25, // 66: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry.value:type_name -> core.v1.ReachabilityEntrypoints - 46, // 67: core.v1.SetOperation.Child._this:type_name -> core.v1.SetOperation.Child.This - 35, // 68: core.v1.SetOperation.Child.computed_userset:type_name -> core.v1.ComputedUserset - 33, // 69: core.v1.SetOperation.Child.tuple_to_userset:type_name -> core.v1.TupleToUserset - 31, // 70: core.v1.SetOperation.Child.userset_rewrite:type_name -> core.v1.UsersetRewrite - 34, // 71: core.v1.SetOperation.Child.functioned_tuple_to_userset:type_name -> core.v1.FunctionedTupleToUserset - 47, // 72: core.v1.SetOperation.Child._nil:type_name -> core.v1.SetOperation.Child.Nil - 36, // 73: core.v1.SetOperation.Child.source_position:type_name -> core.v1.SourcePosition - 74, // [74:74] is the sub-list for method output_type - 74, // [74:74] is the sub-list for method input_type - 74, // [74:74] is the sub-list for extension type_name - 74, // [74:74] is the sub-list for extension extendee - 0, // [0:74] is the sub-list for field type_name + 37, // 25: core.v1.NamespaceDefinition.source_position:type_name -> core.v1.SourcePosition + 23, // 26: core.v1.NamespaceDefinition.deprecation:type_name -> core.v1.Deprecation + 0, // 27: core.v1.Deprecation.deprecation_type:type_name -> core.v1.DeprecationType + 37, // 28: core.v1.Deprecation.source_position:type_name -> core.v1.SourcePosition + 32, // 29: core.v1.Relation.userset_rewrite:type_name -> core.v1.UsersetRewrite + 28, // 30: core.v1.Relation.type_information:type_name -> core.v1.TypeInformation + 21, // 31: core.v1.Relation.metadata:type_name -> core.v1.Metadata + 37, // 32: core.v1.Relation.source_position:type_name -> core.v1.SourcePosition + 23, // 33: core.v1.Relation.deprecation:type_name -> core.v1.Deprecation + 43, // 34: core.v1.ReachabilityGraph.entrypoints_by_subject_type:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry + 44, // 35: core.v1.ReachabilityGraph.entrypoints_by_subject_relation:type_name -> core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry + 27, // 36: core.v1.ReachabilityEntrypoints.entrypoints:type_name -> core.v1.ReachabilityEntrypoint + 14, // 37: core.v1.ReachabilityEntrypoints.subject_relation:type_name -> core.v1.RelationReference + 3, // 38: core.v1.ReachabilityEntrypoint.kind:type_name -> core.v1.ReachabilityEntrypoint.ReachabilityEntrypointKind + 14, // 39: core.v1.ReachabilityEntrypoint.target_relation:type_name -> core.v1.RelationReference + 4, // 40: core.v1.ReachabilityEntrypoint.result_status:type_name -> core.v1.ReachabilityEntrypoint.EntrypointResultStatus + 29, // 41: core.v1.TypeInformation.allowed_direct_relations:type_name -> core.v1.AllowedRelation + 45, // 42: core.v1.AllowedRelation.public_wildcard:type_name -> core.v1.AllowedRelation.PublicWildcard + 37, // 43: core.v1.AllowedRelation.source_position:type_name -> core.v1.SourcePosition + 31, // 44: core.v1.AllowedRelation.required_caveat:type_name -> core.v1.AllowedCaveat + 30, // 45: core.v1.AllowedRelation.required_expiration:type_name -> core.v1.ExpirationTrait + 23, // 46: core.v1.AllowedRelation.deprecation:type_name -> core.v1.Deprecation + 33, // 47: core.v1.UsersetRewrite.union:type_name -> core.v1.SetOperation + 33, // 48: core.v1.UsersetRewrite.intersection:type_name -> core.v1.SetOperation + 33, // 49: core.v1.UsersetRewrite.exclusion:type_name -> core.v1.SetOperation + 37, // 50: core.v1.UsersetRewrite.source_position:type_name -> core.v1.SourcePosition + 46, // 51: core.v1.SetOperation.child:type_name -> core.v1.SetOperation.Child + 49, // 52: core.v1.TupleToUserset.tupleset:type_name -> core.v1.TupleToUserset.Tupleset + 36, // 53: core.v1.TupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset + 37, // 54: core.v1.TupleToUserset.source_position:type_name -> core.v1.SourcePosition + 5, // 55: core.v1.FunctionedTupleToUserset.function:type_name -> core.v1.FunctionedTupleToUserset.Function + 50, // 56: core.v1.FunctionedTupleToUserset.tupleset:type_name -> core.v1.FunctionedTupleToUserset.Tupleset + 36, // 57: core.v1.FunctionedTupleToUserset.computed_userset:type_name -> core.v1.ComputedUserset + 37, // 58: core.v1.FunctionedTupleToUserset.source_position:type_name -> core.v1.SourcePosition + 6, // 59: core.v1.ComputedUserset.object:type_name -> core.v1.ComputedUserset.Object + 37, // 60: core.v1.ComputedUserset.source_position:type_name -> core.v1.SourcePosition + 39, // 61: core.v1.CaveatExpression.operation:type_name -> core.v1.CaveatOperation + 10, // 62: core.v1.CaveatExpression.caveat:type_name -> core.v1.ContextualizedCaveat + 7, // 63: core.v1.CaveatOperation.op:type_name -> core.v1.CaveatOperation.Operation + 38, // 64: core.v1.CaveatOperation.children:type_name -> core.v1.CaveatExpression + 41, // 65: core.v1.RelationshipFilter.optional_subject_filter:type_name -> core.v1.SubjectFilter + 51, // 66: core.v1.SubjectFilter.optional_relation:type_name -> core.v1.SubjectFilter.RelationFilter + 12, // 67: core.v1.CaveatDefinition.ParameterTypesEntry.value:type_name -> core.v1.CaveatTypeReference + 26, // 68: core.v1.ReachabilityGraph.EntrypointsBySubjectTypeEntry.value:type_name -> core.v1.ReachabilityEntrypoints + 26, // 69: core.v1.ReachabilityGraph.EntrypointsBySubjectRelationEntry.value:type_name -> core.v1.ReachabilityEntrypoints + 47, // 70: core.v1.SetOperation.Child._this:type_name -> core.v1.SetOperation.Child.This + 36, // 71: core.v1.SetOperation.Child.computed_userset:type_name -> core.v1.ComputedUserset + 34, // 72: core.v1.SetOperation.Child.tuple_to_userset:type_name -> core.v1.TupleToUserset + 32, // 73: core.v1.SetOperation.Child.userset_rewrite:type_name -> core.v1.UsersetRewrite + 35, // 74: core.v1.SetOperation.Child.functioned_tuple_to_userset:type_name -> core.v1.FunctionedTupleToUserset + 48, // 75: core.v1.SetOperation.Child._nil:type_name -> core.v1.SetOperation.Child.Nil + 37, // 76: core.v1.SetOperation.Child.source_position:type_name -> core.v1.SourcePosition + 77, // [77:77] is the sub-list for method output_type + 77, // [77:77] is the sub-list for method input_type + 77, // [77:77] is the sub-list for extension type_name + 77, // [77:77] is the sub-list for extension extendee + 0, // [0:77] is the sub-list for field type_name } func init() { file_core_v1_core_proto_init() } @@ -4097,7 +4210,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[15].Exporter = func(v any, i int) any { - switch v := v.(*Relation); i { + switch v := v.(*Deprecation); i { case 0: return &v.state case 1: @@ -4109,7 +4222,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[16].Exporter = func(v any, i int) any { - switch v := v.(*ReachabilityGraph); i { + switch v := v.(*Relation); i { case 0: return &v.state case 1: @@ -4121,7 +4234,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[17].Exporter = func(v any, i int) any { - switch v := v.(*ReachabilityEntrypoints); i { + switch v := v.(*ReachabilityGraph); i { case 0: return &v.state case 1: @@ -4133,7 +4246,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[18].Exporter = func(v any, i int) any { - switch v := v.(*ReachabilityEntrypoint); i { + switch v := v.(*ReachabilityEntrypoints); i { case 0: return &v.state case 1: @@ -4145,7 +4258,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[19].Exporter = func(v any, i int) any { - switch v := v.(*TypeInformation); i { + switch v := v.(*ReachabilityEntrypoint); i { case 0: return &v.state case 1: @@ -4157,7 +4270,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[20].Exporter = func(v any, i int) any { - switch v := v.(*AllowedRelation); i { + switch v := v.(*TypeInformation); i { case 0: return &v.state case 1: @@ -4169,7 +4282,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[21].Exporter = func(v any, i int) any { - switch v := v.(*ExpirationTrait); i { + switch v := v.(*AllowedRelation); i { case 0: return &v.state case 1: @@ -4181,7 +4294,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[22].Exporter = func(v any, i int) any { - switch v := v.(*AllowedCaveat); i { + switch v := v.(*ExpirationTrait); i { case 0: return &v.state case 1: @@ -4193,7 +4306,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[23].Exporter = func(v any, i int) any { - switch v := v.(*UsersetRewrite); i { + switch v := v.(*AllowedCaveat); i { case 0: return &v.state case 1: @@ -4205,7 +4318,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[24].Exporter = func(v any, i int) any { - switch v := v.(*SetOperation); i { + switch v := v.(*UsersetRewrite); i { case 0: return &v.state case 1: @@ -4217,7 +4330,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[25].Exporter = func(v any, i int) any { - switch v := v.(*TupleToUserset); i { + switch v := v.(*SetOperation); i { case 0: return &v.state case 1: @@ -4229,7 +4342,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[26].Exporter = func(v any, i int) any { - switch v := v.(*FunctionedTupleToUserset); i { + switch v := v.(*TupleToUserset); i { case 0: return &v.state case 1: @@ -4241,7 +4354,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[27].Exporter = func(v any, i int) any { - switch v := v.(*ComputedUserset); i { + switch v := v.(*FunctionedTupleToUserset); i { case 0: return &v.state case 1: @@ -4253,7 +4366,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[28].Exporter = func(v any, i int) any { - switch v := v.(*SourcePosition); i { + switch v := v.(*ComputedUserset); i { case 0: return &v.state case 1: @@ -4265,7 +4378,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[29].Exporter = func(v any, i int) any { - switch v := v.(*CaveatExpression); i { + switch v := v.(*SourcePosition); i { case 0: return &v.state case 1: @@ -4277,7 +4390,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[30].Exporter = func(v any, i int) any { - switch v := v.(*CaveatOperation); i { + switch v := v.(*CaveatExpression); i { case 0: return &v.state case 1: @@ -4289,7 +4402,7 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[31].Exporter = func(v any, i int) any { - switch v := v.(*RelationshipFilter); i { + switch v := v.(*CaveatOperation); i { case 0: return &v.state case 1: @@ -4301,6 +4414,18 @@ func file_core_v1_core_proto_init() { } } file_core_v1_core_proto_msgTypes[32].Exporter = func(v any, i int) any { + switch v := v.(*RelationshipFilter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_v1_core_proto_msgTypes[33].Exporter = func(v any, i int) any { switch v := v.(*SubjectFilter); i { case 0: return &v.state @@ -4312,7 +4437,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[36].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[37].Exporter = func(v any, i int) any { switch v := v.(*AllowedRelation_PublicWildcard); i { case 0: return &v.state @@ -4324,7 +4449,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[37].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[38].Exporter = func(v any, i int) any { switch v := v.(*SetOperation_Child); i { case 0: return &v.state @@ -4336,7 +4461,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[38].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[39].Exporter = func(v any, i int) any { switch v := v.(*SetOperation_Child_This); i { case 0: return &v.state @@ -4348,7 +4473,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[39].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[40].Exporter = func(v any, i int) any { switch v := v.(*SetOperation_Child_Nil); i { case 0: return &v.state @@ -4360,7 +4485,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[40].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[41].Exporter = func(v any, i int) any { switch v := v.(*TupleToUserset_Tupleset); i { case 0: return &v.state @@ -4372,7 +4497,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[41].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[42].Exporter = func(v any, i int) any { switch v := v.(*FunctionedTupleToUserset_Tupleset); i { case 0: return &v.state @@ -4384,7 +4509,7 @@ func file_core_v1_core_proto_init() { return nil } } - file_core_v1_core_proto_msgTypes[42].Exporter = func(v any, i int) any { + file_core_v1_core_proto_msgTypes[43].Exporter = func(v any, i int) any { switch v := v.(*SubjectFilter_RelationFilter); i { case 0: return &v.state @@ -4401,20 +4526,20 @@ func file_core_v1_core_proto_init() { (*RelationTupleTreeNode_IntermediateNode)(nil), (*RelationTupleTreeNode_LeafNode)(nil), } - file_core_v1_core_proto_msgTypes[20].OneofWrappers = []any{ + file_core_v1_core_proto_msgTypes[21].OneofWrappers = []any{ (*AllowedRelation_Relation)(nil), (*AllowedRelation_PublicWildcard_)(nil), } - file_core_v1_core_proto_msgTypes[23].OneofWrappers = []any{ + file_core_v1_core_proto_msgTypes[24].OneofWrappers = []any{ (*UsersetRewrite_Union)(nil), (*UsersetRewrite_Intersection)(nil), (*UsersetRewrite_Exclusion)(nil), } - file_core_v1_core_proto_msgTypes[29].OneofWrappers = []any{ + file_core_v1_core_proto_msgTypes[30].OneofWrappers = []any{ (*CaveatExpression_Operation)(nil), (*CaveatExpression_Caveat)(nil), } - file_core_v1_core_proto_msgTypes[37].OneofWrappers = []any{ + file_core_v1_core_proto_msgTypes[38].OneofWrappers = []any{ (*SetOperation_Child_XThis)(nil), (*SetOperation_Child_ComputedUserset)(nil), (*SetOperation_Child_TupleToUserset)(nil), @@ -4428,7 +4553,7 @@ func file_core_v1_core_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_core_v1_core_proto_rawDesc, NumEnums: 8, - NumMessages: 43, + NumMessages: 44, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/proto/core/v1/core.pb.validate.go b/pkg/proto/core/v1/core.pb.validate.go index 8cd4ed538b..bcc93ef290 100644 --- a/pkg/proto/core/v1/core.pb.validate.go +++ b/pkg/proto/core/v1/core.pb.validate.go @@ -2536,6 +2536,35 @@ func (m *NamespaceDefinition) validate(all bool) error { } } + if all { + switch v := interface{}(m.GetDeprecation()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, NamespaceDefinitionValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, NamespaceDefinitionValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDeprecation()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return NamespaceDefinitionValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return NamespaceDefinitionMultiError(errors) } @@ -2618,6 +2647,160 @@ var _ interface { var _NamespaceDefinition_Name_Pattern = regexp.MustCompile("^([a-z][a-z0-9_]{1,62}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$") +// Validate checks the field values on Deprecation with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *Deprecation) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on Deprecation with the rules defined in +// the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in DeprecationMultiError, or +// nil if none found. +func (m *Deprecation) ValidateAll() error { + return m.validate(true) +} + +func (m *Deprecation) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if _, ok := DeprecationType_name[int32(m.GetDeprecationType())]; !ok { + err := DeprecationValidationError{ + field: "DeprecationType", + reason: "value must be one of the defined enum values", + } + if !all { + return err + } + errors = append(errors, err) + } + + // no validation rules for Object + + // no validation rules for Relation + + if len(m.GetComments()) > 256 { + err := DeprecationValidationError{ + field: "Comments", + reason: "value length must be at most 256 bytes", + } + if !all { + return err + } + errors = append(errors, err) + } + + if all { + switch v := interface{}(m.GetSourcePosition()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, DeprecationValidationError{ + field: "SourcePosition", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, DeprecationValidationError{ + field: "SourcePosition", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetSourcePosition()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return DeprecationValidationError{ + field: "SourcePosition", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return DeprecationMultiError(errors) + } + + return nil +} + +// DeprecationMultiError is an error wrapping multiple validation errors +// returned by Deprecation.ValidateAll() if the designated constraints aren't met. +type DeprecationMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DeprecationMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DeprecationMultiError) AllErrors() []error { return m } + +// DeprecationValidationError is the validation error returned by +// Deprecation.Validate if the designated constraints aren't met. +type DeprecationValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DeprecationValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DeprecationValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DeprecationValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DeprecationValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DeprecationValidationError) ErrorName() string { return "DeprecationValidationError" } + +// Error satisfies the builtin error interface +func (e DeprecationValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDeprecation.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = DeprecationValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DeprecationValidationError{} + // Validate checks the field values on Relation with the rules defined in the // proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. @@ -2782,7 +2965,34 @@ func (m *Relation) validate(all bool) error { // no validation rules for CanonicalCacheKey - // no validation rules for DeprecationType + if all { + switch v := interface{}(m.GetDeprecation()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, RelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, RelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDeprecation()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return RelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + } + } + } if len(errors) > 0 { return RelationMultiError(errors) @@ -3628,7 +3838,34 @@ func (m *AllowedRelation) validate(all bool) error { } } - // no validation rules for DeprecationType + if all { + switch v := interface{}(m.GetDeprecation()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, AllowedRelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, AllowedRelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDeprecation()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return AllowedRelationValidationError{ + field: "Deprecation", + reason: "embedded message failed validation", + cause: err, + } + } + } switch v := m.RelationOrWildcard.(type) { case *AllowedRelation_Relation: diff --git a/pkg/proto/core/v1/core_vtproto.pb.go b/pkg/proto/core/v1/core_vtproto.pb.go index 9807016358..dbf9980ef1 100644 --- a/pkg/proto/core/v1/core_vtproto.pb.go +++ b/pkg/proto/core/v1/core_vtproto.pb.go @@ -351,6 +351,7 @@ func (m *NamespaceDefinition) CloneVT() *NamespaceDefinition { r.Name = m.Name r.Metadata = m.Metadata.CloneVT() r.SourcePosition = m.SourcePosition.CloneVT() + r.Deprecation = m.Deprecation.CloneVT() if rhs := m.Relation; rhs != nil { tmpContainer := make([]*Relation, len(rhs)) for k, v := range rhs { @@ -369,6 +370,27 @@ func (m *NamespaceDefinition) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *Deprecation) CloneVT() *Deprecation { + if m == nil { + return (*Deprecation)(nil) + } + r := new(Deprecation) + r.DeprecationType = m.DeprecationType + r.Object = m.Object + r.Relation = m.Relation + r.Comments = m.Comments + r.SourcePosition = m.SourcePosition.CloneVT() + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *Deprecation) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *Relation) CloneVT() *Relation { if m == nil { return (*Relation)(nil) @@ -381,7 +403,7 @@ func (m *Relation) CloneVT() *Relation { r.SourcePosition = m.SourcePosition.CloneVT() r.AliasingRelation = m.AliasingRelation r.CanonicalCacheKey = m.CanonicalCacheKey - r.DeprecationType = m.DeprecationType + r.Deprecation = m.Deprecation.CloneVT() if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -517,7 +539,7 @@ func (m *AllowedRelation) CloneVT() *AllowedRelation { r.SourcePosition = m.SourcePosition.CloneVT() r.RequiredCaveat = m.RequiredCaveat.CloneVT() r.RequiredExpiration = m.RequiredExpiration.CloneVT() - r.DeprecationType = m.DeprecationType + r.Deprecation = m.Deprecation.CloneVT() if m.RelationOrWildcard != nil { r.RelationOrWildcard = m.RelationOrWildcard.(interface { CloneVT() isAllowedRelation_RelationOrWildcard @@ -1490,6 +1512,9 @@ func (this *NamespaceDefinition) EqualVT(that *NamespaceDefinition) bool { if !this.SourcePosition.EqualVT(that.SourcePosition) { return false } + if !this.Deprecation.EqualVT(that.Deprecation) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1500,6 +1525,37 @@ func (this *NamespaceDefinition) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *Deprecation) EqualVT(that *Deprecation) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.DeprecationType != that.DeprecationType { + return false + } + if this.Object != that.Object { + return false + } + if this.Relation != that.Relation { + return false + } + if this.Comments != that.Comments { + return false + } + if !this.SourcePosition.EqualVT(that.SourcePosition) { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *Deprecation) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*Deprecation) + if !ok { + return false + } + return this.EqualVT(that) +} func (this *Relation) EqualVT(that *Relation) bool { if this == that { return true @@ -1527,7 +1583,7 @@ func (this *Relation) EqualVT(that *Relation) bool { if this.CanonicalCacheKey != that.CanonicalCacheKey { return false } - if this.DeprecationType != that.DeprecationType { + if !this.Deprecation.EqualVT(that.Deprecation) { return false } return string(this.unknownFields) == string(that.unknownFields) @@ -1745,7 +1801,7 @@ func (this *AllowedRelation) EqualVT(that *AllowedRelation) bool { if !this.RequiredExpiration.EqualVT(that.RequiredExpiration) { return false } - if this.DeprecationType != that.DeprecationType { + if !this.Deprecation.EqualVT(that.Deprecation) { return false } return string(this.unknownFields) == string(that.unknownFields) @@ -3374,6 +3430,16 @@ func (m *NamespaceDefinition) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Deprecation != nil { + size, err := m.Deprecation.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } if m.SourcePosition != nil { size, err := m.SourcePosition.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -3416,6 +3482,75 @@ func (m *NamespaceDefinition) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Deprecation) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Deprecation) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Deprecation) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.SourcePosition != nil { + size, err := m.SourcePosition.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if len(m.Comments) > 0 { + i -= len(m.Comments) + copy(dAtA[i:], m.Comments) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Comments))) + i-- + dAtA[i] = 0x22 + } + if len(m.Relation) > 0 { + i -= len(m.Relation) + copy(dAtA[i:], m.Relation) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Relation))) + i-- + dAtA[i] = 0x1a + } + if len(m.Object) > 0 { + i -= len(m.Object) + copy(dAtA[i:], m.Object) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Object))) + i-- + dAtA[i] = 0x12 + } + if m.DeprecationType != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DeprecationType)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *Relation) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -3446,10 +3581,15 @@ func (m *Relation) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if m.DeprecationType != 0 { - i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DeprecationType)) + if m.Deprecation != nil { + size, err := m.Deprecation.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) i-- - dAtA[i] = 0x40 + dAtA[i] = 0x42 } if len(m.CanonicalCacheKey) > 0 { i -= len(m.CanonicalCacheKey) @@ -3838,10 +3978,15 @@ func (m *AllowedRelation) MarshalToSizedBufferVT(dAtA []byte) (int, error) { } i -= size } - if m.DeprecationType != 0 { - i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DeprecationType)) + if m.Deprecation != nil { + size, err := m.Deprecation.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) i-- - dAtA[i] = 0x40 + dAtA[i] = 0x42 } if m.RequiredExpiration != nil { size, err := m.RequiredExpiration.MarshalToSizedBufferVT(dAtA[:i]) @@ -5392,6 +5537,39 @@ func (m *NamespaceDefinition) SizeVT() (n int) { l = m.SourcePosition.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + if m.Deprecation != nil { + l = m.Deprecation.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Deprecation) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DeprecationType != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DeprecationType)) + } + l = len(m.Object) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Relation) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Comments) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.SourcePosition != nil { + l = m.SourcePosition.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -5430,8 +5608,9 @@ func (m *Relation) SizeVT() (n int) { if l > 0 { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } - if m.DeprecationType != 0 { - n += 1 + protohelpers.SizeOfVarint(uint64(m.DeprecationType)) + if m.Deprecation != nil { + l = m.Deprecation.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } n += len(m.unknownFields) return n @@ -5576,8 +5755,9 @@ func (m *AllowedRelation) SizeVT() (n int) { l = m.RequiredExpiration.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } - if m.DeprecationType != 0 { - n += 1 + protohelpers.SizeOfVarint(uint64(m.DeprecationType)) + if m.Deprecation != nil { + l = m.Deprecation.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } n += len(m.unknownFields) return n @@ -8230,6 +8410,244 @@ func (m *NamespaceDefinition) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deprecation", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Deprecation == nil { + m.Deprecation = &Deprecation{} + } + if err := m.Deprecation.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Deprecation) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Deprecation: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Deprecation: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DeprecationType", wireType) + } + m.DeprecationType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DeprecationType |= DeprecationType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Object = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Relation", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Relation = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Comments", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Comments = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourcePosition", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SourcePosition == nil { + m.SourcePosition = &SourcePosition{} + } + if err := m.SourcePosition.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -8522,10 +8940,10 @@ func (m *Relation) UnmarshalVT(dAtA []byte) error { m.CanonicalCacheKey = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DeprecationType", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deprecation", wireType) } - m.DeprecationType = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return protohelpers.ErrIntOverflow @@ -8535,11 +8953,28 @@ func (m *Relation) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.DeprecationType |= DeprecationType(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Deprecation == nil { + m.Deprecation = &Deprecation{} + } + if err := m.Deprecation.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -9592,10 +10027,10 @@ func (m *AllowedRelation) UnmarshalVT(dAtA []byte) error { } iNdEx = postIndex case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DeprecationType", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Deprecation", wireType) } - m.DeprecationType = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return protohelpers.ErrIntOverflow @@ -9605,11 +10040,28 @@ func (m *AllowedRelation) UnmarshalVT(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.DeprecationType |= DeprecationType(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Deprecation == nil { + m.Deprecation = &Deprecation{} + } + if err := m.Deprecation.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/schemadsl/compiler/translator.go b/pkg/schemadsl/compiler/translator.go index 681a20c5cb..e418c9dacd 100644 --- a/pkg/schemadsl/compiler/translator.go +++ b/pkg/schemadsl/compiler/translator.go @@ -26,7 +26,7 @@ type translationContext struct { enabledFlags []string caveatTypeSet *caveattypes.TypeSet deprecatedRelation bool - deprecatedType string + deprecation *core.Deprecation } func (tctx *translationContext) prefixedPath(definitionName string) (string, error) { @@ -52,6 +52,7 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) orderedDefinitions := make([]SchemaDefinition, 0, len(root.GetChildren())) var objectDefinitions []*core.NamespaceDefinition var caveatDefinitions []*core.CaveatDefinition + var deprecationDefinition []*core.Deprecation nodes := make(map[string]*dslNode) @@ -83,15 +84,23 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) definition = def objectDefinitions = append(objectDefinitions, def) - } - if _, ok := nodes[definition.GetName()]; ok { - return nil, definitionNode.WithSourceErrorf(definition.GetName(), "found name reused between multiple definitions and/or caveats: %s", definition.GetName()) + case dslshape.NodeTypeDeprecation: + def, err := translateDeprecation(tctx, definitionNode) + if err != nil { + return nil, err + } + deprecationDefinition = append(deprecationDefinition, def) } - nodes[definition.GetName()] = definitionNode + if definition != nil { + if _, ok := nodes[definition.GetName()]; ok { + return nil, definitionNode.WithSourceErrorf(definition.GetName(), "found name reused between multiple definitions and/or caveats: %s", definition.GetName()) + } + nodes[definition.GetName()] = definitionNode - orderedDefinitions = append(orderedDefinitions, definition) + orderedDefinitions = append(orderedDefinitions, definition) + } } // Strip the type annotation metadata if typechecking isn't enabled. @@ -106,6 +115,13 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) } } + if slices.Contains(tctx.allowedFlags, "deprecation") && slices.Contains(tctx.enabledFlags, "deprecation") { + err := deprecateRelationsAndObjects(deprecationDefinition, objectDefinitions) + if err != nil { + return nil, err + } + } + return &CompiledSchema{ CaveatDefinitions: caveatDefinitions, ObjectDefinitions: objectDefinitions, @@ -235,12 +251,14 @@ func translateObjectDefinition(tctx *translationContext, defNode *dslNode) (*cor if relationOrPermissionNode.GetType() == dslshape.NodeTypeDeprecation { if !slices.Contains(tctx.allowedFlags, "deprecation") || !slices.Contains(tctx.enabledFlags, "deprecation") { - return nil, relationOrPermissionNode.WithSourceErrorf(tctx.deprecatedType, "deprecation not enabled: %w", err) + return nil, relationOrPermissionNode.Errorf("deprecation not enabled") } + // in case of a deprecation found in the definition, we mark the relation as deprecated with the help of a context bool + // which would help mark the immediately following relation as deprecated tctx.deprecatedRelation = true - tctx.deprecatedType, err = relationOrPermissionNode.GetString(dslshape.NodeDeprecatedPredicateName) + tctx.deprecation, err = translateDeprecation(tctx, relationOrPermissionNode) if err != nil { - return nil, relationOrPermissionNode.WithSourceErrorf(tctx.deprecatedType, "invalid deprecation type: %w", err) + return nil, relationOrPermissionNode.Errorf("invalid deprecation: %w", err) } continue @@ -286,6 +304,44 @@ func translateObjectDefinition(tctx *translationContext, defNode *dslNode) (*cor return ns, nil } +func deprecateRelationsAndObjects(deprecations []*core.Deprecation, namespaces []*core.NamespaceDefinition) error { + + objectMap := make(map[string]*core.NamespaceDefinition) + relationMap := make(map[string]*core.Relation) + + for _, ns := range namespaces { + ns.Deprecation = &core.Deprecation{DeprecationType: core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED} + objectMap[ns.GetName()] = ns + for _, rel := range ns.GetRelation() { + + // check if the relation already has a deprecation defined inside a definition + if rel.Deprecation == nil { + rel.Deprecation = &core.Deprecation{DeprecationType: core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED} + } + key := ns.GetName() + "#" + rel.GetName() + relationMap[key] = rel + } + } + + // Apply deprecations + for _, dep := range deprecations { + if dep.Object != "" && dep.Relation != "" { + rel, ok := relationMap[dep.Object+"#"+dep.Relation] + if !ok { + return fmt.Errorf("warning: Deprecation for relation %s not found in relation map", dep.Object) + } + rel.Deprecation = dep + } else { + obj, ok := objectMap[dep.Object] + if !ok { + return fmt.Errorf("warning: Deprecation for object %s not found in object map", dep.Object) + } + obj.Deprecation = dep + } + } + return nil +} + func getSourcePosition(dslNode *dslNode, mapper input.PositionMapper) *core.SourcePosition { if !dslNode.Has(dslshape.NodePredicateStartRune) { return nil @@ -353,8 +409,9 @@ func translateRelationOrPermission(tctx *translationContext, relOrPermNode *dslN } rel.Metadata = addComments(rel.Metadata, relOrPermNode) rel.SourcePosition = getSourcePosition(relOrPermNode, tctx.mapper) + if tctx.deprecatedRelation { - rel.DeprecationType = deprecationTypeFromString(tctx.deprecatedType) + rel.Deprecation = tctx.deprecation tctx.deprecatedRelation = false } return rel, err @@ -452,6 +509,38 @@ func translatePermission(tctx *translationContext, permissionNode *dslNode) (*co return permission, nil } +func translateDeprecation(tctx *translationContext, depNode *dslNode) (*core.Deprecation, error) { + if !slices.Contains(tctx.allowedFlags, "deprecation") || !slices.Contains(tctx.enabledFlags, "deprecation") { + return nil, depNode.Errorf("deprecation not enabled") + } + + deprecationType, err := depNode.GetString(dslshape.NodeDeprecatedType) + if err != nil { + return nil, depNode.Errorf("invalid deprecation type: %w", err) + } + + object, objErr := depNode.GetString(dslshape.NodeDeprecatedObject) + rel, relErr := depNode.GetString(dslshape.NodeTypeDeprecatedRelation) + comments, commentsErr := depNode.GetString(dslshape.NodeDeprecatedComments) + + deprecation := &core.Deprecation{ + DeprecationType: deprecationTypeFromString(deprecationType), + } + + // Conditionally add optional fields + if objErr == nil { + deprecation.Object = object + } + if relErr == nil { + deprecation.Relation = rel + } + if commentsErr == nil { + deprecation.Comments = comments + } + + return deprecation, nil +} + // extractTypeAnnotations is a helper function to return the literal identifiers under the type annotation node func extractTypeAnnotations(typeAnnotationNode *dslNode) ([]string, error) { children := typeAnnotationNode.List(dslshape.NodeTypeAnnotationPredicateTypes) diff --git a/pkg/schemadsl/dslshape/dslshape.go b/pkg/schemadsl/dslshape/dslshape.go index 54fd8baaaf..f59075d653 100644 --- a/pkg/schemadsl/dslshape/dslshape.go +++ b/pkg/schemadsl/dslshape/dslshape.go @@ -22,7 +22,9 @@ const ( NodeTypePermission // A permission NodeTypeTypeAnnotation // A type annotation for permissions - NodeTypeDeprecation // A deprecated relation. + NodeTypeDeprecation // A deprecated relation. + NodeTypeDeprecationOptions // Options for a deprecation. + NodeTypeTypeReference // A type reference NodeTypeSpecificTypeReference // A reference to a specific type. NodeTypeCaveatReference // A caveat reference under a type. @@ -220,8 +222,26 @@ const ( NodeExpressionPredicateRightExpr = "right-expr" // - // NodeTypeDeprecated + // NodeTypeDeprecatedOptions + // + // The type of deprecation + NodeDeprecatedType = "deprecation-type" + + // + // NodeTypeDeprecatedObject + // + // The value of an object for a deprecation + NodeDeprecatedObject = "deprecation-object" + + // + // NodeTypeDeprecatedRelation + // + // The value of a relation for depreaction + NodeTypeDeprecatedRelation = "deprecation-relation" + + // + // NodeTypeDeprecatedOptions // - // The value of a deprecated node - NodeDeprecatedPredicateName = "deprecated-relation-value" + // The value of an option for a deprecation + NodeDeprecatedComments = "deprecation-comments" ) diff --git a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go index 16e83c9ec6..d30b2c8460 100644 --- a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go +++ b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go @@ -20,22 +20,23 @@ func _() { _ = x[NodeTypePermission-9] _ = x[NodeTypeTypeAnnotation-10] _ = x[NodeTypeDeprecation-11] - _ = x[NodeTypeTypeReference-12] - _ = x[NodeTypeSpecificTypeReference-13] - _ = x[NodeTypeCaveatReference-14] - _ = x[NodeTypeTraitReference-15] - _ = x[NodeTypeUnionExpression-16] - _ = x[NodeTypeIntersectExpression-17] - _ = x[NodeTypeExclusionExpression-18] - _ = x[NodeTypeArrowExpression-19] - _ = x[NodeTypeIdentifier-20] - _ = x[NodeTypeNilExpression-21] - _ = x[NodeTypeCaveatTypeReference-22] + _ = x[NodeTypeDeprecationOptions-12] + _ = x[NodeTypeTypeReference-13] + _ = x[NodeTypeSpecificTypeReference-14] + _ = x[NodeTypeCaveatReference-15] + _ = x[NodeTypeTraitReference-16] + _ = x[NodeTypeUnionExpression-17] + _ = x[NodeTypeIntersectExpression-18] + _ = x[NodeTypeExclusionExpression-19] + _ = x[NodeTypeArrowExpression-20] + _ = x[NodeTypeIdentifier-21] + _ = x[NodeTypeNilExpression-22] + _ = x[NodeTypeCaveatTypeReference-23] } -const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeAnnotationNodeTypeDeprecationNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" +const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeAnnotationNodeTypeDeprecationNodeTypeDeprecationOptionsNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" -var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 200, 219, 240, 269, 292, 314, 337, 364, 391, 414, 432, 453, 480} +var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 200, 219, 245, 266, 295, 318, 340, 363, 390, 417, 440, 458, 479, 506} func (i NodeType) String() string { if i < 0 || i >= NodeType(len(_NodeType_index)-1) { diff --git a/pkg/schemadsl/generator/generator.go b/pkg/schemadsl/generator/generator.go index 79ae847d9d..8b1c311703 100644 --- a/pkg/schemadsl/generator/generator.go +++ b/pkg/schemadsl/generator/generator.go @@ -202,11 +202,11 @@ func (sg *sourceGenerator) emitNamespace(namespace *core.NamespaceDefinition) er sg.markNewScope() for _, relation := range namespace.Relation { - if relation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { + if relation.Deprecation != nil && relation.Deprecation.DeprecationType != core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED { sg.flags.Add("deprecation") sg.append("@deprecated(") - switch relation.DeprecationType { + switch relation.Deprecation.DeprecationType { case core.DeprecationType_DEPRECATED_TYPE_WARNING: sg.append("warn") case core.DeprecationType_DEPRECATED_TYPE_ERROR: diff --git a/pkg/schemadsl/generator/generator_test.go b/pkg/schemadsl/generator/generator_test.go index 8ab944ab55..67ded6b769 100644 --- a/pkg/schemadsl/generator/generator_test.go +++ b/pkg/schemadsl/generator/generator_test.go @@ -398,6 +398,7 @@ definition document { { "deprecation test", `use deprecation + definition user{} definition document { @@ -409,6 +410,8 @@ definition document { }`, `use deprecation +definition user {} + definition document { @deprecated(warn) relation viewer: user diff --git a/pkg/schemadsl/parser/parser.go b/pkg/schemadsl/parser/parser.go index 1a24028477..14e93618b3 100644 --- a/pkg/schemadsl/parser/parser.go +++ b/pkg/schemadsl/parser/parser.go @@ -69,6 +69,9 @@ Loop: hasSeenDefinition = true rootNode.Connect(dslshape.NodePredicateChild, p.consumeCaveat()) + case p.isToken(lexer.TokenTypeAt): + rootNode.Connect(dslshape.NodePredicateChild, p.consumeDeprecation()) + default: p.emitErrorf("Unexpected token at root level: %v", p.currentToken.Kind) break Loop @@ -298,7 +301,7 @@ func (p *sourceParser) consumeDefinition() AstNode { return defNode } - // Relations and permissions. + // Relations and permissions and associated deprecations for objects and relations. for { // } if _, ok := p.tryConsume(lexer.TokenTypeRightBrace); ok { @@ -355,6 +358,8 @@ func (p *sourceParser) consumeRelation() AstNode { return relNode } +// consumeDeprecation consumes a deprecation statement +// ```@deprecated(type, object, relation)``` func (p *sourceParser) consumeDeprecation() AstNode { depNode := p.startNode(dslshape.NodeTypeDeprecation) defer p.mustFinishNode() @@ -366,22 +371,80 @@ func (p *sourceParser) consumeDeprecation() AstNode { return depNode } - _, ok = p.consume(lexer.TokenTypeLeftParen) + _, ok = p.tryConsume(lexer.TokenTypeLeftParen) if !ok { + p.emitErrorf("Expected '(' after 'deprecated' keyword") return depNode } - deprecationType, ok := p.consumeIdentifier() + // Required: deprecation type + deprecationType, ok := p.tryConsume(lexer.TokenTypeIdentifier) if !ok { + p.emitErrorf("Expected identifier for deprecation type") return depNode } - depNode.MustDecorate(dslshape.NodeDeprecatedPredicateName, deprecationType) + depNode.MustDecorate(dslshape.NodeDeprecatedType, deprecationType.Value) - _, ok = p.consume(lexer.TokenTypeRightParen) + // Try consume after every opt. + if p.isToken(lexer.TokenTypeRightParen) { + p.consume(lexer.TokenTypeRightParen) + return depNode + } + + _, ok = p.tryConsume(lexer.TokenTypeComma) if !ok { + p.emitErrorf("Expected ',' after deprecation type") + return depNode + } + + // A comment + if p.isToken(lexer.TokenTypeString) { + commentTok, _ := p.tryConsume(lexer.TokenTypeString) + comment := strings.Trim(commentTok.Value, `"`) + depNode.MustDecorate(dslshape.NodeDeprecatedComments, comment) + + p.consume(lexer.TokenTypeRightParen) + return depNode + } + + if p.isToken(lexer.TokenTypeIdentifier) { + // Object + objectTok, _ := p.tryConsume(lexer.TokenTypeIdentifier) + depNode.MustDecorate(dslshape.NodeDeprecatedObject, objectTok.Value) + + // Check if relation follows: # + if p.isToken(lexer.TokenTypeHash) { + p.consume(lexer.TokenTypeHash) + if !p.isToken(lexer.TokenTypeIdentifier) { + p.emitErrorf("Expected identifier for deprecation relation after '#'") + } else { + relTok, _ := p.tryConsume(lexer.TokenTypeIdentifier) + depNode.MustDecorate(dslshape.NodeTypeDeprecatedRelation, relTok.Value) + } + } + + if p.isToken(lexer.TokenTypeRightParen) { + p.consume(lexer.TokenTypeRightParen) + return depNode + } + + _, ok = p.tryConsume(lexer.TokenTypeComma) + if !ok { + p.emitErrorf("Expected ',' after deprecation object or object#relation") + } else if p.isToken(lexer.TokenTypeString) { + commentTok, _ := p.tryConsume(lexer.TokenTypeString) + comment := strings.Trim(commentTok.Value, `"`) + depNode.MustDecorate(dslshape.NodeDeprecatedComments, comment) + } else { + p.emitErrorf("Expected string value for deprecation comment") + } + + p.consume(lexer.TokenTypeRightParen) return depNode } + // If it's neither string nor identifier, it's invalid + p.emitErrorf("Unexpected token after deprecation type: %s", p.currentToken.Value) return depNode } diff --git a/pkg/schemadsl/parser/parser_test.go b/pkg/schemadsl/parser/parser_test.go index 6b0f113765..a8fad175d4 100644 --- a/pkg/schemadsl/parser/parser_test.go +++ b/pkg/schemadsl/parser/parser_test.go @@ -156,6 +156,9 @@ func TestParser(t *testing.T) { {"permission type annotation just pipe test", "permission_type_annotation_just_pipe"}, {"deprecated relation test", "deprecation"}, {"invalid deprecated relation test", "invalid-deprecation"}, + {"deprecated options test", "deprecated_options"}, + {"deprecation which is outside of a definition", "deprecation_outside_definition"}, + {"multiple deprecations with comments", "multiple_deprecations"}, } for _, test := range parserTests { diff --git a/pkg/schemadsl/parser/tests/deprecated_options.zed b/pkg/schemadsl/parser/tests/deprecated_options.zed new file mode 100644 index 0000000000..8b8e617105 --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecated_options.zed @@ -0,0 +1,14 @@ +use deprecation + +definition deprecated_relation { + + @deprecated(warn, user, "comments") + relation writer: user + + + @deprecated(error, testuser) + relation reader: user +} + +definition user {} +definition testuser {} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/deprecated_options.zed.expected b/pkg/schemadsl/parser/tests/deprecated_options.zed.expected new file mode 100644 index 0000000000..d79574cecc --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecated_options.zed.expected @@ -0,0 +1,71 @@ +NodeTypeFile + end-rune = 221 + input-source = deprecated options test + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 14 + input-source = deprecated options test + start-rune = 0 + use-flag-name = deprecation + NodeTypeDefinition + definition-name = deprecated_relation + end-rune = 178 + input-source = deprecated options test + start-rune = 17 + child-node => + NodeTypeDeprecation + deprecation-comments = comments + deprecation-object = user + deprecation-type = warn + end-rune = 89 + input-source = deprecated options test + start-rune = 55 + NodeTypeRelation + end-rune = 115 + input-source = deprecated options test + relation-name = writer + start-rune = 95 + allowed-types => + NodeTypeTypeReference + end-rune = 115 + input-source = deprecated options test + start-rune = 112 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 115 + input-source = deprecated options test + start-rune = 112 + type-name = user + NodeTypeDeprecation + deprecation-object = testuser + deprecation-type = error + end-rune = 150 + input-source = deprecated options test + start-rune = 123 + NodeTypeRelation + end-rune = 176 + input-source = deprecated options test + relation-name = reader + start-rune = 156 + allowed-types => + NodeTypeTypeReference + end-rune = 176 + input-source = deprecated options test + start-rune = 173 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 176 + input-source = deprecated options test + start-rune = 173 + type-name = user + NodeTypeDefinition + definition-name = user + end-rune = 198 + input-source = deprecated options test + start-rune = 181 + NodeTypeDefinition + definition-name = testuser + end-rune = 221 + input-source = deprecated options test + start-rune = 200 diff --git a/pkg/schemadsl/parser/tests/deprecation.zed.expected b/pkg/schemadsl/parser/tests/deprecation.zed.expected index d64cde9d98..38332ddb83 100644 --- a/pkg/schemadsl/parser/tests/deprecation.zed.expected +++ b/pkg/schemadsl/parser/tests/deprecation.zed.expected @@ -15,7 +15,7 @@ NodeTypeFile start-rune = 17 child-node => NodeTypeDeprecation - deprecated-relation-value = warn + deprecation-type = warn end-rune = 71 input-source = deprecated relation test start-rune = 55 @@ -36,7 +36,7 @@ NodeTypeFile start-rune = 94 type-name = user NodeTypeDeprecation - deprecated-relation-value = error + deprecation-type = error end-rune = 121 input-source = deprecated relation test start-rune = 104 diff --git a/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed b/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed new file mode 100644 index 0000000000..60a7ac59c5 --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed @@ -0,0 +1,15 @@ +use deprecation + +definition user {} +definition testuser {} + +definition deprecated_relation { + + relation writer: user + + + @deprecated(error, testuser) + relation reader: user +} + +@deprecated(warn, user, "comments") \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed.expected b/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed.expected new file mode 100644 index 0000000000..4ef41d852c --- /dev/null +++ b/pkg/schemadsl/parser/tests/deprecation_outside_definition.zed.expected @@ -0,0 +1,71 @@ +NodeTypeFile + end-rune = 218 + input-source = deprecation which is outside of a definition + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 14 + input-source = deprecation which is outside of a definition + start-rune = 0 + use-flag-name = deprecation + NodeTypeDefinition + definition-name = user + end-rune = 34 + input-source = deprecation which is outside of a definition + start-rune = 17 + NodeTypeDefinition + definition-name = testuser + end-rune = 57 + input-source = deprecation which is outside of a definition + start-rune = 36 + NodeTypeDefinition + definition-name = deprecated_relation + end-rune = 181 + input-source = deprecation which is outside of a definition + start-rune = 60 + child-node => + NodeTypeRelation + end-rune = 118 + input-source = deprecation which is outside of a definition + relation-name = writer + start-rune = 98 + allowed-types => + NodeTypeTypeReference + end-rune = 118 + input-source = deprecation which is outside of a definition + start-rune = 115 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 118 + input-source = deprecation which is outside of a definition + start-rune = 115 + type-name = user + NodeTypeDeprecation + deprecation-object = testuser + deprecation-type = error + end-rune = 153 + input-source = deprecation which is outside of a definition + start-rune = 126 + NodeTypeRelation + end-rune = 179 + input-source = deprecation which is outside of a definition + relation-name = reader + start-rune = 159 + allowed-types => + NodeTypeTypeReference + end-rune = 179 + input-source = deprecation which is outside of a definition + start-rune = 176 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 179 + input-source = deprecation which is outside of a definition + start-rune = 176 + type-name = user + NodeTypeDeprecation + deprecation-comments = comments + deprecation-object = user + deprecation-type = warn + end-rune = 218 + input-source = deprecation which is outside of a definition + start-rune = 184 diff --git a/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected index 74ce356b8c..8300143dac 100644 --- a/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected +++ b/pkg/schemadsl/parser/tests/invalid-deprecation.zed.expected @@ -16,7 +16,7 @@ NodeTypeFile child-node => NodeTypeError end-rune = 48 - error-message = Expected identifier, found token TokenTypeRightParen + error-message = Expected identifier for deprecation type error-source = ) input-source = invalid deprecated relation test start-rune = 49 @@ -31,4 +31,4 @@ NodeTypeFile error-message = Unexpected token at root level: TokenTypeRightParen error-source = ) input-source = invalid deprecated relation test - start-rune = 49 + start-rune = 49 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/multiple_deprecations.zed b/pkg/schemadsl/parser/tests/multiple_deprecations.zed new file mode 100644 index 0000000000..2c246d6d8e --- /dev/null +++ b/pkg/schemadsl/parser/tests/multiple_deprecations.zed @@ -0,0 +1,19 @@ +use deprecation + +definition user {} +definition testuser {} +definition superuser{} + +definition deprecated_relation { + + relation writer: user + + + @deprecated(warn, testuser, "oops deprecated!") + relation reader: testuser + + relation editor: superuser +} + +@deprecated(error, user, "obj user is deprecated, use superuser instead") +@deprecated(warn, deprecated_relation#editor, "rel editor is deprecated") \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/multiple_deprecations.zed.expected b/pkg/schemadsl/parser/tests/multiple_deprecations.zed.expected new file mode 100644 index 0000000000..ab5a291314 --- /dev/null +++ b/pkg/schemadsl/parser/tests/multiple_deprecations.zed.expected @@ -0,0 +1,101 @@ +NodeTypeFile + end-rune = 408 + input-source = multiple deprecations with comments + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 14 + input-source = multiple deprecations with comments + start-rune = 0 + use-flag-name = deprecation + NodeTypeDefinition + definition-name = user + end-rune = 34 + input-source = multiple deprecations with comments + start-rune = 17 + NodeTypeDefinition + definition-name = testuser + end-rune = 57 + input-source = multiple deprecations with comments + start-rune = 36 + NodeTypeDefinition + definition-name = superuser + end-rune = 80 + input-source = multiple deprecations with comments + start-rune = 59 + NodeTypeDefinition + definition-name = deprecated_relation + end-rune = 259 + input-source = multiple deprecations with comments + start-rune = 83 + child-node => + NodeTypeRelation + end-rune = 141 + input-source = multiple deprecations with comments + relation-name = writer + start-rune = 121 + allowed-types => + NodeTypeTypeReference + end-rune = 141 + input-source = multiple deprecations with comments + start-rune = 138 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 141 + input-source = multiple deprecations with comments + start-rune = 138 + type-name = user + NodeTypeDeprecation + deprecation-comments = oops deprecated! + deprecation-object = testuser + deprecation-type = warn + end-rune = 195 + input-source = multiple deprecations with comments + start-rune = 149 + NodeTypeRelation + end-rune = 225 + input-source = multiple deprecations with comments + relation-name = reader + start-rune = 201 + allowed-types => + NodeTypeTypeReference + end-rune = 225 + input-source = multiple deprecations with comments + start-rune = 218 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 225 + input-source = multiple deprecations with comments + start-rune = 218 + type-name = testuser + NodeTypeRelation + end-rune = 257 + input-source = multiple deprecations with comments + relation-name = editor + start-rune = 232 + allowed-types => + NodeTypeTypeReference + end-rune = 257 + input-source = multiple deprecations with comments + start-rune = 249 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 257 + input-source = multiple deprecations with comments + start-rune = 249 + type-name = superuser + NodeTypeDeprecation + deprecation-comments = obj user is deprecated, use superuser instead + deprecation-object = user + deprecation-type = error + end-rune = 334 + input-source = multiple deprecations with comments + start-rune = 262 + NodeTypeDeprecation + deprecation-comments = rel editor is deprecated + deprecation-object = deprecated_relation + deprecation-relation = editor + deprecation-type = warn + end-rune = 408 + input-source = multiple deprecations with comments + start-rune = 336 \ No newline at end of file diff --git a/proto/internal/core/v1/core.proto b/proto/internal/core/v1/core.proto index 039b7331bb..41f7938358 100644 --- a/proto/internal/core/v1/core.proto +++ b/proto/internal/core/v1/core.proto @@ -204,6 +204,9 @@ message NamespaceDefinition { /** source_position contains the position of the namespace in the source schema, if any */ SourcePosition source_position = 4; + + /** deprecation contains the deprecation information for the namespace, if any */ + Deprecation deprecation = 5; } /** @@ -214,6 +217,31 @@ enum DeprecationType { DEPRECATED_TYPE_WARNING = 1; DEPRECATED_TYPE_ERROR = 2; } +/** + * Deprecation represents the deprecation information for a relation and object. + * It contains the type of deprecation, a comment to show when the relation is used, + * and the source position of the deprecation in the source schema, if any. + */ + +message Deprecation { + /** + * deprecation_type is the type of deprecation for the relation. + * It can be either a warning or an error, defaults to unspecified. + */ + DeprecationType deprecation_type = 1 [(validate.rules).enum.defined_only = true]; + + /** object is the object that is deprecated */ + string object = 2; + + /** relation is the relation that is deprecated */ + string relation = 3; + + /** comments are the comments to show when the relation is used */ + string comments = 4 [(validate.rules).string = {max_bytes: 256}]; + + /** source_position contains the position of the deprecation in the source schema, if any */ + SourcePosition source_position = 5; +} /** * Relation represents the definition of a relation or permission under a namespace. @@ -244,7 +272,7 @@ message Relation { string canonical_cache_key = 7; /** deprecation_type is the type of deprecation for the relation */ - DeprecationType deprecation_type = 8; + Deprecation deprecation = 8; } /** @@ -436,7 +464,7 @@ message AllowedRelation { /** * deprecation_type defines the type of deprecation for this relation. */ - DeprecationType deprecation_type = 8; + Deprecation deprecation = 8; } /** From bb9f5b7a6f74d7b0f5ae36fb924e8ca2d51b22b9 Mon Sep 17 00:00:00 2001 From: Kartikay Date: Sun, 20 Jul 2025 21:33:54 +0530 Subject: [PATCH 5/6] mage gen:proto Signed-off-by: Kartikay --- e2e/go.mod | 2 +- go.mod | 2 +- go.sum | 2 +- pkg/proto/core/v1/core.pb.go | 3 + pkg/schema/arrows.go | 53 +++++++++++++----- pkg/schema/arrows_test.go | 84 ++++++++++++++++++++++++++++ pkg/schema/full_reachability.go | 3 + pkg/schema/full_reachability_test.go | 62 ++++++++++++++++++++ pkg/schemadsl/compiler/translator.go | 14 ++--- 9 files changed, 200 insertions(+), 25 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index 4a0229521a..698fc09bd1 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -82,4 +82,4 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/controller-runtime v0.21.0 // indirect -) +) \ No newline at end of file diff --git a/go.mod b/go.mod index a54c5bd072..169ce29c19 100644 --- a/go.mod +++ b/go.mod @@ -440,4 +440,4 @@ require ( sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/yaml v1.5.0 // indirect -) \ No newline at end of file +) diff --git a/go.sum b/go.sum index 280a9ed567..451213c26d 100644 --- a/go.sum +++ b/go.sum @@ -3627,4 +3627,4 @@ sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= \ No newline at end of file diff --git a/pkg/proto/core/v1/core.pb.go b/pkg/proto/core/v1/core.pb.go index 1a428da2e1..fdc551b277 100644 --- a/pkg/proto/core/v1/core.pb.go +++ b/pkg/proto/core/v1/core.pb.go @@ -1406,6 +1406,9 @@ type Deprecation struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // * + // deprecation_type is the type of deprecation for the relation. + // It can be either a warning or an error, defaults to unspecified. DeprecationType DeprecationType `protobuf:"varint,1,opt,name=deprecation_type,json=deprecationType,proto3,enum=core.v1.DeprecationType" json:"deprecation_type,omitempty"` // * object is the object that is deprecated Object string `protobuf:"bytes,2,opt,name=object,proto3" json:"object,omitempty"` diff --git a/pkg/schema/arrows.go b/pkg/schema/arrows.go index 021f282050..0e57b39e04 100644 --- a/pkg/schema/arrows.go +++ b/pkg/schema/arrows.go @@ -107,6 +107,30 @@ func (as *ArrowSet) collectArrowInformationForRewrite(ctx context.Context, rewri } } +func (as *ArrowSet) registerTupleToUsersetArrows(ctx context.Context, ttu *core.TupleToUserset, def *ValidatedDefinition, relation *core.Relation, updatedPath string, tuplesetRelation string, computedUsersetRelation string) error { + as.add(ttu, updatedPath, def.Namespace().Name, relation.Name) + allowedSubjectTypes, err := def.AllowedSubjectRelations(tuplesetRelation) + if err != nil { + return err + } + + for _, ast := range allowedSubjectTypes { + def, err := as.ts.GetValidatedDefinition(ctx, ast.Namespace) + if err != nil { + return err + } + + // NOTE: this is explicitly added to the arrowsByComputedUsersetNamespaceAndRelation without + // checking if the relation/permission exists, because it's needed for schema diff tracking. + as.arrowsByComputedUsersetNamespaceAndRelation.Add(ast.Namespace+"#"+computedUsersetRelation, ArrowInformation{Path: updatedPath, Arrow: ttu, ParentRelationName: relation.Name}) + if def.HasRelation(computedUsersetRelation) { + as.reachableComputedUsersetRelationsByTuplesetRelation.Add(ast.Namespace+"#"+tuplesetRelation, ast.Namespace+"#"+computedUsersetRelation) + } + } + + return nil +} + func (as *ArrowSet) collectArrowInformationForSetOperation(ctx context.Context, so *core.SetOperation, def *ValidatedDefinition, relation *core.Relation, path string) error { for index, childOneof := range so.Child { updatedPath := path + "." + strconv.Itoa(index) @@ -121,25 +145,24 @@ func (as *ArrowSet) collectArrowInformationForSetOperation(ctx context.Context, } case *core.SetOperation_Child_TupleToUserset: - as.add(child.TupleToUserset, updatedPath, def.Namespace().Name, relation.Name) - - allowedSubjectTypes, err := def.AllowedSubjectRelations(child.TupleToUserset.Tupleset.Relation) + err := as.registerTupleToUsersetArrows(ctx, child.TupleToUserset, def, relation, updatedPath, child.TupleToUserset.Tupleset.Relation, child.TupleToUserset.ComputedUserset.Relation) if err != nil { return err } - for _, ast := range allowedSubjectTypes { - def, err := as.ts.GetValidatedDefinition(ctx, ast.Namespace) - if err != nil { - return err - } - - // NOTE: this is explicitly added to the arrowsByComputedUsersetNamespaceAndRelation without - // checking if the relation/permission exists, because its needed for schema diff tracking. - as.arrowsByComputedUsersetNamespaceAndRelation.Add(ast.Namespace+"#"+child.TupleToUserset.ComputedUserset.Relation, ArrowInformation{Path: path, Arrow: child.TupleToUserset, ParentRelationName: relation.Name}) - if def.HasRelation(child.TupleToUserset.ComputedUserset.Relation) { - as.reachableComputedUsersetRelationsByTuplesetRelation.Add(ast.Namespace+"#"+child.TupleToUserset.Tupleset.Relation, ast.Namespace+"#"+child.TupleToUserset.ComputedUserset.Relation) - } + case *core.SetOperation_Child_FunctionedTupleToUserset: + // Convert FunctionedTupleToUserset to regular TupleToUserset for arrow tracking + // since the arrow relationship structure is the same regardless of function type + ttu := &core.TupleToUserset{ + Tupleset: &core.TupleToUserset_Tupleset{ + Relation: child.FunctionedTupleToUserset.Tupleset.Relation, + }, + ComputedUserset: child.FunctionedTupleToUserset.ComputedUserset, + } + + err := as.registerTupleToUsersetArrows(ctx, ttu, def, relation, updatedPath, child.FunctionedTupleToUserset.Tupleset.Relation, child.FunctionedTupleToUserset.ComputedUserset.Relation) + if err != nil { + return err } case *core.SetOperation_Child_XThis: diff --git a/pkg/schema/arrows_test.go b/pkg/schema/arrows_test.go index 2914d5b321..437a51b3b7 100644 --- a/pkg/schema/arrows_test.go +++ b/pkg/schema/arrows_test.go @@ -43,6 +43,50 @@ func TestLookupTuplesetArrows(t *testing.T) { "resource#view": {}, }, }, + { + name: "functioned arrow any", + schemaText: ` + definition user {} + + definition organization { + relation member: user + } + + definition resource { + relation org: organization + relation viewer: user + permission view = org.any(member) + viewer + } + `, + expected: map[string][]string{ + "organization#member": {}, + "resource#viewer": {}, + "resource#org": {"org->member"}, + "resource#view": {}, + }, + }, + { + name: "functioned arrow all", + schemaText: ` + definition user {} + + definition organization { + relation member: user + } + + definition resource { + relation org: organization + relation viewer: user + permission view = org.all(member) + viewer + } + `, + expected: map[string][]string{ + "organization#member": {}, + "resource#viewer": {}, + "resource#org": {"org->member"}, + "resource#view": {}, + }, + }, { name: "multiple arrows", schemaText: ` @@ -139,6 +183,46 @@ func TestAllReachableRelations(t *testing.T) { "resource#org", }, }, + { + name: "functioned arrow any", + schemaText: ` + definition user {} + + definition organization { + relation member: user + } + + definition resource { + relation org: organization + relation viewer: user + permission view = org.any(member) + viewer + } + `, + expected: []string{ + "organization#member", + "resource#org", + }, + }, + { + name: "functioned arrow all", + schemaText: ` + definition user {} + + definition organization { + relation member: user + } + + definition resource { + relation org: organization + relation viewer: user + permission view = org.all(member) + viewer + } + `, + expected: []string{ + "organization#member", + "resource#org", + }, + }, { name: "multiple arrows", schemaText: ` diff --git a/pkg/schema/full_reachability.go b/pkg/schema/full_reachability.go index a6143b538b..0372e2ed14 100644 --- a/pkg/schema/full_reachability.go +++ b/pkg/schema/full_reachability.go @@ -211,6 +211,9 @@ func setOperationReferencesRelation(ctx context.Context, so *core.SetOperation, case *core.SetOperation_Child_TupleToUserset: // Nothing to do, handled above via arrow set + case *core.SetOperation_Child_FunctionedTupleToUserset: + // Nothing to do, handled above via arrow set + case *core.SetOperation_Child_XThis: // Nothing to do diff --git a/pkg/schema/full_reachability_test.go b/pkg/schema/full_reachability_test.go index c2f450f419..0656a634df 100644 --- a/pkg/schema/full_reachability_test.go +++ b/pkg/schema/full_reachability_test.go @@ -244,6 +244,68 @@ func TestRelationsReferencing(t *testing.T) { "resource#view": {}, }, }, + { + name: "functioned arrow any", + schemaText: ` + definition user {} + + definition organization { + relation direct_member: user + permission member = direct_member + } + + definition resource { + relation viewer: user + relation org: organization + permission view = org.any(member) + viewer + }`, + expected: map[string][]expectedRelation{ + "organization#direct_member": { + {Namespace: "organization", Relation: "member", Type: RelationInExpression}, + }, + "organization#member": { + {Namespace: "organization", Relation: "org", Type: RelationIsComputedUsersetForArrow}, + }, + "resource#viewer": { + {Namespace: "resource", Relation: "view", Type: RelationInExpression}, + }, + "resource#org": { + {Namespace: "resource", Relation: "view", Type: RelationIsTuplesetForArrow}, + }, + "resource#view": {}, + }, + }, + { + name: "functioned arrow all", + schemaText: ` + definition user {} + + definition organization { + relation direct_member: user + permission member = direct_member + } + + definition resource { + relation viewer: user + relation org: organization + permission view = org.all(member) + viewer + }`, + expected: map[string][]expectedRelation{ + "organization#direct_member": { + {Namespace: "organization", Relation: "member", Type: RelationInExpression}, + }, + "organization#member": { + {Namespace: "organization", Relation: "org", Type: RelationIsComputedUsersetForArrow}, + }, + "resource#viewer": { + {Namespace: "resource", Relation: "view", Type: RelationInExpression}, + }, + "resource#org": { + {Namespace: "resource", Relation: "view", Type: RelationIsTuplesetForArrow}, + }, + "resource#view": {}, + }, + }, { name: "referencing permission", schemaText: ` diff --git a/pkg/schemadsl/compiler/translator.go b/pkg/schemadsl/compiler/translator.go index e418c9dacd..3490deab04 100644 --- a/pkg/schemadsl/compiler/translator.go +++ b/pkg/schemadsl/compiler/translator.go @@ -103,6 +103,13 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) } } + if slices.Contains(tctx.allowedFlags, "deprecation") && slices.Contains(tctx.enabledFlags, "deprecation") { + err := deprecateRelationsAndObjects(deprecationDefinition, objectDefinitions) + if err != nil { + return nil, err + } + } + // Strip the type annotation metadata if typechecking isn't enabled. if !slices.Contains(tctx.enabledFlags, "typechecking") { for _, def := range objectDefinitions { @@ -115,13 +122,6 @@ func translate(tctx *translationContext, root *dslNode) (*CompiledSchema, error) } } - if slices.Contains(tctx.allowedFlags, "deprecation") && slices.Contains(tctx.enabledFlags, "deprecation") { - err := deprecateRelationsAndObjects(deprecationDefinition, objectDefinitions) - if err != nil { - return nil, err - } - } - return &CompiledSchema{ CaveatDefinitions: caveatDefinitions, ObjectDefinitions: objectDefinitions, From f436b79a91dbe968654399917bb1550e4ea028ae Mon Sep 17 00:00:00 2001 From: Kartikay Date: Sun, 20 Jul 2025 22:07:29 +0530 Subject: [PATCH 6/6] fix conflict Signed-off-by: Kartikay --- e2e/go.mod | 2 +- internal/services/v1/relationships.go | 1 - pkg/schemadsl/compiler/translator.go | 3 --- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index 698fc09bd1..4a0229521a 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -82,4 +82,4 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/controller-runtime v0.21.0 // indirect -) \ No newline at end of file +) diff --git a/internal/services/v1/relationships.go b/internal/services/v1/relationships.go index 11e64f12db..338cc89ca4 100644 --- a/internal/services/v1/relationships.go +++ b/internal/services/v1/relationships.go @@ -658,7 +658,6 @@ func checkForDeprecatedRelationsAndObjects(ctx context.Context, update *v1.Relat case corev1.DeprecationType_DEPRECATED_TYPE_ERROR: return shared.NewDeprecationError(update.Relationship.Resource.ObjectType, update.Relationship.Relation, relDef.Deprecation.Comments) } - } nsdef, _, err := reader.ReadNamespaceByName(ctx, resource.ObjectType) if err != nil { diff --git a/pkg/schemadsl/compiler/translator.go b/pkg/schemadsl/compiler/translator.go index eb5cc2c71c..008999eb21 100644 --- a/pkg/schemadsl/compiler/translator.go +++ b/pkg/schemadsl/compiler/translator.go @@ -305,7 +305,6 @@ func translateObjectDefinition(tctx *translationContext, defNode *dslNode) (*cor } func deprecateRelationsAndObjects(deprecations []*core.Deprecation, namespaces []*core.NamespaceDefinition) error { - objectMap := make(map[string]*core.NamespaceDefinition) relationMap := make(map[string]*core.Relation) @@ -313,7 +312,6 @@ func deprecateRelationsAndObjects(deprecations []*core.Deprecation, namespaces [ ns.Deprecation = &core.Deprecation{DeprecationType: core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED} objectMap[ns.GetName()] = ns for _, rel := range ns.GetRelation() { - // check if the relation already has a deprecation defined inside a definition if rel.Deprecation == nil { rel.Deprecation = &core.Deprecation{DeprecationType: core.DeprecationType_DEPRECATED_TYPE_UNSPECIFIED} @@ -509,7 +507,6 @@ func translatePermission(tctx *translationContext, permissionNode *dslNode) (*co return permission, nil } - func translateDeprecation(tctx *translationContext, depNode *dslNode) (*core.Deprecation, error) { if !slices.Contains(tctx.allowedFlags, "deprecation") || !slices.Contains(tctx.enabledFlags, "deprecation") { return nil, depNode.Errorf("deprecation not enabled")