From 326f8d386ff8891b6b028a6391f41109aece76c0 Mon Sep 17 00:00:00 2001 From: Doria Keung Date: Wed, 20 Nov 2024 12:31:32 -0500 Subject: [PATCH 01/14] Fix annotation for FIELD_NOT_REQUIRED rule (#3483) --- .../bufcheckserver/internal/bufcheckserverhandle/lint.go | 1 + 1 file changed, 1 insertion(+) diff --git a/private/bufpkg/bufcheck/bufcheckserver/internal/bufcheckserverhandle/lint.go b/private/bufpkg/bufcheck/bufcheckserver/internal/bufcheckserverhandle/lint.go index 361acdc030..fbb23df043 100644 --- a/private/bufpkg/bufcheck/bufcheckserver/internal/bufcheckserverhandle/lint.go +++ b/private/bufpkg/bufcheck/bufcheckserver/internal/bufcheckserverhandle/lint.go @@ -408,6 +408,7 @@ func handleLintFieldNotRequired( field.NameLocation(), nil, `Field named %q should not be required.`, + field.Name(), ) } return nil From 5c43a09f0001226bc1007377d2d23c9d52cdc423 Mon Sep 17 00:00:00 2001 From: Miguel Young Date: Thu, 21 Nov 2024 12:58:38 -0500 Subject: [PATCH 02/14] Add more types of hovers to LSP (#3486) This PR adds three new hoverable things in the LSP: 1. You can hover over the path of an import to show the contents of that file. 2. You can hover over the tag of a field to show its varint encoding. 3. You can hover over the number of an enum value to show its varint encoding and hex/bin values. --- private/buf/buflsp/symbol.go | 93 ++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/private/buf/buflsp/symbol.go b/private/buf/buflsp/symbol.go index 451f2e43fc..1886272ef1 100644 --- a/private/buf/buflsp/symbol.go +++ b/private/buf/buflsp/symbol.go @@ -31,6 +31,7 @@ import ( "github.com/bufbuild/buf/private/pkg/slicesext" "github.com/bufbuild/protocompile/ast" "go.lsp.dev/protocol" + "google.golang.org/protobuf/encoding/protowire" ) // symbol represents a named symbol inside of a buflsp.file @@ -96,10 +97,16 @@ type builtin struct { name string } +type fieldTag struct { + tag ast.IntValueNode + def *symbol +} + func (*definition) isSymbolKind() {} func (*reference) isSymbolKind() {} func (*import_) isSymbolKind() {} func (*builtin) isSymbolKind() {} +func (*fieldTag) isSymbolKind() {} // Range constructs an LSP protocol code range for this symbol. func (s *symbol) Range() protocol.Range { @@ -403,6 +410,72 @@ func (s *symbol) FormatDocs(ctx context.Context) string { node = kind.node path = kind.path + case *import_: + return fmt.Sprintf("```proto\n%s\n```", kind.file.text) + + case *fieldTag: + var value uint64 + if v, ok := kind.tag.AsInt64(); ok { + value = uint64(v) + } else { + value, _ = kind.tag.AsUint64() + } + + plural := func(i int) string { + if i == 1 { + return "" + } + return "s" + } + + var ty protowire.Type + var packed bool + // Only definition symbols are placed into the def field of fieldTag, so + // doing an unchecked assertion here is ok. + switch def := kind.def.kind.(*definition).node.(type) { + case *ast.EnumValueNode: + varint := protowire.AppendVarint(nil, value) + return fmt.Sprintf( + "`0x%x`, `0b%b`\n\nencoded (hex): `%X` (%d byte%s)", + value, value, varint, len(varint), plural(len(varint)), + ) + case *ast.MapFieldNode: + ty = protowire.BytesType + case *ast.GroupNode: + ty = protowire.StartGroupType + case *ast.FieldNode: + switch def.FldType.AsIdentifier() { + case "bool", "int32", "int64", "uint32", "uint64", "sint32", "sint64": + ty = protowire.VarintType + packed = def.Label.Repeated + case "fixed32", "sfixed32", "float": + ty = protowire.Fixed32Type + packed = def.Label.Repeated + case "fixed64", "sfixed64", "double": + ty = protowire.Fixed64Type + packed = def.Label.Repeated + default: + ty = protowire.BytesType + } + } + + // Don't use AppendTag because that wants to truncate value to int32. + varint := protowire.AppendVarint(nil, value<<3|uint64(ty)) + doc := fmt.Sprintf( + "encoded (hex): `%X` (%d byte%s)", + varint, len(varint), plural(len(varint)), + ) + + if packed { + packed := protowire.AppendVarint(nil, value<<3|uint64(protowire.BytesType)) + return doc + fmt.Sprintf( + "\n\npacked (hex): `%X` (%d byte%s)", + packed, len(packed), plural(len(varint)), + ) + } + + return doc + default: return "" } @@ -597,15 +670,18 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { } case *ast.GroupNode: + def := w.newDef(node, node.Name) w.newDef(node, node.Name) + w.newTag(node.Tag, def) // TODO: also do the name of the generated field. for _, decl := range node.Decls { w.Walk(decl, node) } case *ast.FieldNode: - w.newDef(node, node.Name) + def := w.newDef(node, node.Name) w.newRef(node.FldType) + w.newTag(node.Tag, def) if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) @@ -613,9 +689,10 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { } case *ast.MapFieldNode: - w.newDef(node, node.Name) + def := w.newDef(node, node.Name) w.newRef(node.MapType.KeyType) w.newRef(node.MapType.ValueType) + w.newTag(node.Tag, def) if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) @@ -639,7 +716,8 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { } case *ast.EnumValueNode: - w.newDef(node, node.Name) + def := w.newDef(node, node.Name) + w.newTag(node.Number, def) if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) @@ -713,6 +791,15 @@ func (w *symbolWalker) newDef(node ast.Node, name *ast.IdentNode) *symbol { return symbol } +// newTag creates a new symbol for a field tag, and adds it to the running list. +// +// Returns a new symbol for that tag. +func (w *symbolWalker) newTag(tag ast.IntValueNode, def *symbol) *symbol { + symbol := w.newSymbol(tag) + symbol.kind = &fieldTag{tag, def} + return symbol +} + // newDef creates a new symbol for a name reference, and adds it to the running list. // // newRef performs same-file Protobuf name resolution. It searches for a partial package From 0302d79b6f8f4da3efd1c01b3dca28ea1a922888 Mon Sep 17 00:00:00 2001 From: Edward McFarlane <3036610+emcfarlane@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:32:01 +0000 Subject: [PATCH 03/14] Add registry plugin commands (#3468) --- CHANGELOG.md | 2 +- private/buf/bufcli/errors.go | 12 ++ private/buf/bufcli/flags_args.go | 16 ++ private/buf/bufprint/bufprint.go | 26 +++ private/buf/cmd/buf/buf.go | 22 ++- .../module/moduleupdate/moduleupdate.go | 2 +- .../plugin/plugincreate/plugincreate.go | 185 ++++++++++++++++++ .../registry/plugin/plugincreate/usage.gen.go | 19 ++ .../plugin/plugindelete/plugindelete.go | 114 +++++++++++ .../registry/plugin/plugindelete/usage.gen.go | 19 ++ .../registry/plugin/plugininfo/plugininfo.go | 121 ++++++++++++ .../registry/plugin/plugininfo/usage.gen.go | 19 ++ .../plugin/pluginupdate/pluginupdate.go | 138 +++++++++++++ .../registry/plugin/pluginupdate/usage.gen.go | 19 ++ 14 files changed, 708 insertions(+), 6 deletions(-) create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincreate/plugincreate.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincreate/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugindelete/plugindelete.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugindelete/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugininfo/plugininfo.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugininfo/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginupdate/pluginupdate.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginupdate/usage.gen.go diff --git a/CHANGELOG.md b/CHANGELOG.md index cc2a049253..7c593ef31f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] -- No changes yet. +- Add `buf registry plugin {create,delete,info,update}` commands to manage BSR plugins. ## [v1.47.2] - 2024-11-14 diff --git a/private/buf/bufcli/errors.go b/private/buf/bufcli/errors.go index 0e0de9344d..3a82786174 100644 --- a/private/buf/bufcli/errors.go +++ b/private/buf/bufcli/errors.go @@ -54,6 +54,12 @@ func NewLabelNameAlreadyExistsError(name string) error { return fmt.Errorf("a label named %q already exists", name) } +// NewPluginNameAlreadyExistsError informs the user that a plugin +// with that name already exists. +func NewPluginNameAlreadyExistsError(name string) error { + return fmt.Errorf("a plugin named %q already exists", name) +} + // NewOrganizationNotFoundError informs the user that an organization with // that name does not exist. func NewOrganizationNotFoundError(name string) error { @@ -88,6 +94,12 @@ func NewTokenNotFoundError(tokenID string) error { return fmt.Errorf("a token with ID %q does not exist", tokenID) } +// NewPluginNotFoundError informs the user that a plugin with +// that name does not exist. +func NewPluginNotFoundError(name string) error { + return fmt.Errorf("a plugin named %q does not exist", name) +} + // NewInvalidRemoteError informs the user that the given remote is invalid. func NewInvalidRemoteError(err error, remote string, moduleFullName string) error { var connectErr *connect.Error diff --git a/private/buf/bufcli/flags_args.go b/private/buf/bufcli/flags_args.go index a2238f7c67..e8d2ca56f7 100644 --- a/private/buf/bufcli/flags_args.go +++ b/private/buf/bufcli/flags_args.go @@ -19,6 +19,7 @@ import ( "fmt" modulev1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/module/v1" + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" "github.com/bufbuild/buf/private/buf/buffetch" "github.com/bufbuild/buf/private/pkg/app" "github.com/bufbuild/buf/private/pkg/app/appcmd" @@ -302,6 +303,21 @@ func VisibilityFlagToVisibilityAllowUnspecified(visibility string) (modulev1.Mod } } +// VisibilityFlagToPluginVisibilityAllowUnspecified parses the given string as a pluginv1.PluginVisibility +// where an empty string will be parsed as unspecified. +func VisibilityFlagToPluginVisibilityAllowUnspecified(visibility string) (pluginv1beta1.PluginVisibility, error) { + switch visibility { + case publicVisibility: + return pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_PUBLIC, nil + case privateVisibility: + return pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_PRIVATE, nil + case "": + return pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_UNSPECIFIED, nil + default: + return 0, fmt.Errorf("invalid visibility: %s", visibility) + } +} + // ArchiveStatusFlagToArchiveStatusFilter parses the given string as a modulev1.ListLabelsRequest_ArchiveFilter. func ArchiveStatusFlagToArchiveStatusFilter(archiveStatus string) (modulev1.ListLabelsRequest_ArchiveFilter, error) { switch archiveStatus { diff --git a/private/buf/bufprint/bufprint.go b/private/buf/bufprint/bufprint.go index c4e6402816..28dd537109 100644 --- a/private/buf/bufprint/bufprint.go +++ b/private/buf/bufprint/bufprint.go @@ -27,6 +27,7 @@ import ( modulev1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/module/v1" ownerv1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/owner/v1" + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" "github.com/bufbuild/buf/private/bufpkg/bufparse" registryv1alpha1 "github.com/bufbuild/buf/private/gen/proto/go/buf/alpha/registry/v1alpha1" "github.com/bufbuild/buf/private/pkg/protoencoding" @@ -248,6 +249,18 @@ func NewOrganizationEntity(organization *ownerv1.Organization, remote string) En } } +// NewPluginEntity returns a new plugin entity to print. +func NewPluginEntity(plugin *pluginv1beta1.Plugin, pluginFullName bufparse.FullName) Entity { + return outputPlugin{ + ID: plugin.Id, + Remote: pluginFullName.Registry(), + Owner: pluginFullName.Owner(), + Name: pluginFullName.Name(), + FullName: pluginFullName.String(), + CreateTime: plugin.CreateTime.AsTime(), + } +} + // NewUserEntity returns a new user entity to print. func NewUserEntity(user *registryv1alpha1.User) Entity { return outputUser{ @@ -466,6 +479,19 @@ func (o outputOrganization) fullName() string { return o.FullName } +type outputPlugin struct { + ID string `json:"id,omitempty"` + Remote string `json:"remote,omitempty"` + Owner string `json:"owner,omitempty"` + Name string `json:"name,omitempty"` + FullName string `json:"-" bufprint:"Name"` + CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"` +} + +func (m outputPlugin) fullName() string { + return m.FullName +} + type outputUser struct { Username string `json:"username,omitempty"` FullName string `json:"-" bufprint:"Name"` diff --git a/private/buf/cmd/buf/buf.go b/private/buf/cmd/buf/buf.go index 57dcc15bfc..776b611c06 100644 --- a/private/buf/cmd/buf/buf.go +++ b/private/buf/cmd/buf/buf.go @@ -35,8 +35,8 @@ import ( "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/bufpluginv2" "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/lsp" "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/price" - "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/plugin/plugindelete" - "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/plugin/pluginpush" + betaplugindelete "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/plugin/plugindelete" + betapluginpush "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/plugin/pluginpush" "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/webhook/webhookcreate" "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/webhook/webhookdelete" "github.com/bufbuild/buf/private/buf/cmd/buf/command/beta/registry/webhook/webhooklist" @@ -81,6 +81,10 @@ import ( "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationdelete" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationinfo" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationupdate" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincreate" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugindelete" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugininfo" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginupdate" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/registrycc" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/registrylogin" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/registrylogout" @@ -252,6 +256,16 @@ func NewRootCommand(name string) *appcmd.Command { moduleupdate.NewCommand("update", builder), }, }, + { + Use: "plugin", + Short: "Manage BSR plugins", + SubCommands: []*appcmd.Command{ + plugincreate.NewCommand("create", builder), + plugininfo.NewCommand("info", builder), + plugindelete.NewCommand("delete", builder), + pluginupdate.NewCommand("update", builder), + }, + }, }, }, { @@ -282,8 +296,8 @@ func NewRootCommand(name string) *appcmd.Command { Use: "plugin", Short: "Manage plugins on the Buf Schema Registry", SubCommands: []*appcmd.Command{ - pluginpush.NewCommand("push", builder), - plugindelete.NewCommand("delete", builder), + betapluginpush.NewCommand("push", builder), + betaplugindelete.NewCommand("delete", builder), }, }, }, diff --git a/private/buf/cmd/buf/command/registry/module/moduleupdate/moduleupdate.go b/private/buf/cmd/buf/command/registry/module/moduleupdate/moduleupdate.go index f4c66ab26c..a6463a1700 100644 --- a/private/buf/cmd/buf/command/registry/module/moduleupdate/moduleupdate.go +++ b/private/buf/cmd/buf/command/registry/module/moduleupdate/moduleupdate.go @@ -139,7 +139,7 @@ func run( } return err } - if _, err := fmt.Fprintln(container.Stdout(), "Module updated."); err != nil { + if _, err := fmt.Fprintf(container.Stdout(), "Updated %s.\n", moduleFullName); err != nil { return syserror.Wrap(err) } return nil diff --git a/private/buf/cmd/buf/command/registry/plugin/plugincreate/plugincreate.go b/private/buf/cmd/buf/command/registry/plugin/plugincreate/plugincreate.go new file mode 100644 index 0000000000..5cbf0b2572 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugincreate/plugincreate.go @@ -0,0 +1,185 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugincreate + +import ( + "context" + "fmt" + + ownerv1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/owner/v1" + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/buf/bufprint" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/stringutil" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const ( + formatFlagName = "format" + visibilityFlagName = "visibility" + defaultLabeFlagName = "default-label-name" + typeFlagName = "type" + + defaultDefaultLabel = "main" + + pluginTypeCheck = "check" +) + +var ( + allPluginTypeStrings = []string{ + pluginTypeCheck, + } +) + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Create a BSR plugin", + Args: appcmd.ExactArgs(1), + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Format string + Visibility string + DefautlLabel string + Type string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + bufcli.BindVisibility(flagSet, &f.Visibility, visibilityFlagName, false) + flagSet.StringVar( + &f.Format, + formatFlagName, + bufprint.FormatText.String(), + fmt.Sprintf(`The output format to use. Must be one of %s`, bufprint.AllFormatsString), + ) + flagSet.StringVar( + &f.DefautlLabel, + defaultLabeFlagName, + defaultDefaultLabel, + "The default label name of the module", + ) + flagSet.StringVar( + &f.Type, + typeFlagName, + "", + fmt.Sprintf( + "The type of the plugin. Must be one of %s", + stringutil.SliceToString(allPluginTypeStrings), + ), + ) + _ = appcmd.MarkFlagRequired(flagSet, typeFlagName) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginFullName, err := bufparse.ParseFullName(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + visibility, err := bufcli.VisibilityFlagToPluginVisibilityAllowUnspecified(flags.Visibility) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + format, err := bufprint.ParseFormat(flags.Format) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + pluginType, err := typeFlagToPluginType(flags.Type) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig). + V1Beta1PluginServiceClient(pluginFullName.Registry()) + + pluginResponse, err := pluginServiceClient.CreatePlugins(ctx, connect.NewRequest( + &pluginv1beta1.CreatePluginsRequest{ + Values: []*pluginv1beta1.CreatePluginsRequest_Value{ + { + OwnerRef: &ownerv1.OwnerRef{ + Value: &ownerv1.OwnerRef_Name{ + Name: pluginFullName.Owner(), + }, + }, + Name: pluginFullName.Name(), + Visibility: visibility, + Type: pluginType, + }, + }, + }, + )) + if err != nil { + if connect.CodeOf(err) == connect.CodeAlreadyExists { + return bufcli.NewPluginNameAlreadyExistsError(pluginFullName.String()) + } + return err + } + plugins := pluginResponse.Msg.Plugins + if len(plugins) != 1 { + return syserror.Newf("unexpected number of plugins returned from server: %d", len(plugins)) + } + if format == bufprint.FormatText { + _, err = fmt.Fprintf(container.Stdout(), "Created %s.\n", pluginFullName) + if err != nil { + return syserror.Wrap(err) + } + return nil + } + return bufprint.PrintNames( + container.Stdout(), + format, + bufprint.NewPluginEntity(plugins[0], pluginFullName), + ) +} + +// typeFlagToPluginType parses the given string as a pluginv1.PluginType. +func typeFlagToPluginType(pluginType string) (pluginv1beta1.PluginType, error) { + switch pluginType { + case pluginTypeCheck: + return pluginv1beta1.PluginType_PLUGIN_TYPE_CHECK, nil + default: + return 0, fmt.Errorf("invalid plugin type: %s", pluginType) + } +} diff --git a/private/buf/cmd/buf/command/registry/plugin/plugincreate/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/plugincreate/usage.gen.go new file mode 100644 index 0000000000..6934f63116 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugincreate/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package plugincreate + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/plugindelete/plugindelete.go b/private/buf/cmd/buf/command/registry/plugin/plugindelete/plugindelete.go new file mode 100644 index 0000000000..0734e95c33 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugindelete/plugindelete.go @@ -0,0 +1,114 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugindelete + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const forceFlagName = "force" + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Delete a BSR plugin", + Args: appcmd.ExactArgs(1), + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Force bool +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + flagSet.BoolVar( + &f.Force, + forceFlagName, + false, + "Force deletion without confirming. Use with caution", + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginFullName, err := bufparse.ParseFullName(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + if !flags.Force { + if err := bufcli.PromptUserForDelete(container, "entity", pluginFullName.Name()); err != nil { + return err + } + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig). + V1Beta1PluginServiceClient(pluginFullName.Registry()) + + if _, err := pluginServiceClient.DeletePlugins(ctx, connect.NewRequest( + &pluginv1beta1.DeletePluginsRequest{ + PluginRefs: []*pluginv1beta1.PluginRef{ + { + Value: &pluginv1beta1.PluginRef_Name_{ + Name: &pluginv1beta1.PluginRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + }, + }, + }, + }, + }, + )); err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewPluginNotFoundError(container.Arg(0)) + } + return err + } + if _, err := fmt.Fprintf(container.Stdout(), "Deleted %s.\n", pluginFullName); err != nil { + return syserror.Wrap(err) + } + return nil +} diff --git a/private/buf/cmd/buf/command/registry/plugin/plugindelete/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/plugindelete/usage.gen.go new file mode 100644 index 0000000000..34654783cf --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugindelete/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package plugindelete + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/plugininfo/plugininfo.go b/private/buf/cmd/buf/command/registry/plugin/plugininfo/plugininfo.go new file mode 100644 index 0000000000..0d10a1cce3 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugininfo/plugininfo.go @@ -0,0 +1,121 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugininfo + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/buf/bufprint" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const formatFlagName = "format" + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Get a BSR plugin", + Args: appcmd.ExactArgs(1), + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Format string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + flagSet.StringVar( + &f.Format, + formatFlagName, + bufprint.FormatText.String(), + fmt.Sprintf(`The output format to use. Must be one of %s`, bufprint.AllFormatsString), + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginFullName, err := bufparse.ParseFullName(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + format, err := bufprint.ParseFormat(flags.Format) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig). + V1Beta1PluginServiceClient(pluginFullName.Registry()) + + pluginsResponse, err := pluginServiceClient.GetPlugins(ctx, connect.NewRequest( + &pluginv1beta1.GetPluginsRequest{ + PluginRefs: []*pluginv1beta1.PluginRef{ + { + Value: &pluginv1beta1.PluginRef_Name_{ + Name: &pluginv1beta1.PluginRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + }, + }, + }, + }, + }, + )) + if err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewPluginNotFoundError(container.Arg(0)) + } + return err + } + plugins := pluginsResponse.Msg.Plugins + if len(plugins) != 1 { + return syserror.Newf("unexpected number of plugins returned from server: %d", len(plugins)) + } + return bufprint.PrintEntity( + container.Stdout(), + format, + bufprint.NewPluginEntity(plugins[0], pluginFullName), + ) +} diff --git a/private/buf/cmd/buf/command/registry/plugin/plugininfo/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/plugininfo/usage.gen.go new file mode 100644 index 0000000000..7889165761 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugininfo/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package plugininfo + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginupdate/pluginupdate.go b/private/buf/cmd/buf/command/registry/plugin/pluginupdate/pluginupdate.go new file mode 100644 index 0000000000..5656c1dc7b --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginupdate/pluginupdate.go @@ -0,0 +1,138 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginupdate + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const ( + visibilityFlagName = "visibility" + descriptionFlagName = "description" + urlFlagName = "url" +) + +// NewCommand returns a new Command. +func NewCommand(name string, builder appext.SubCommandBuilder) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Update BSR plugin settings", + Args: appcmd.ExactArgs(1), + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Visibility string + Description *string + URL *string + DefaultLabel string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + bufcli.BindVisibility(flagSet, &f.Visibility, visibilityFlagName, true) + bufcli.BindStringPointer( + flagSet, + descriptionFlagName, + &f.Description, + "The new description for the plugin", + ) + bufcli.BindStringPointer( + flagSet, + urlFlagName, + &f.URL, + "The new URL for the plugin", + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginFullName, err := bufparse.ParseFullName(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + visibility, err := bufcli.VisibilityFlagToPluginVisibilityAllowUnspecified(flags.Visibility) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + var visibilityUpdate *pluginv1beta1.PluginVisibility + if visibility != pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_UNSPECIFIED { + visibilityUpdate = &visibility + } + + pluginServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig). + V1Beta1PluginServiceClient(pluginFullName.Registry()) + + pluginResponse, err := pluginServiceClient.UpdatePlugins(ctx, connect.NewRequest( + &pluginv1beta1.UpdatePluginsRequest{ + Values: []*pluginv1beta1.UpdatePluginsRequest_Value{ + { + PluginRef: &pluginv1beta1.PluginRef{ + Value: &pluginv1beta1.PluginRef_Name_{ + Name: &pluginv1beta1.PluginRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + }, + }, + }, + Visibility: visibilityUpdate, + }, + }, + }, + )) + if err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewModuleNotFoundError(container.Arg(0)) + } + return err + } + plugins := pluginResponse.Msg.Plugins + if len(plugins) != 1 { + return syserror.Newf("unexpected number of plugins returned from server: %d", len(plugins)) + } + _, err = fmt.Fprintf(container.Stdout(), "Updated %s.\n", pluginFullName) + if err != nil { + return syserror.Wrap(err) + } + return nil +} diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginupdate/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/pluginupdate/usage.gen.go new file mode 100644 index 0000000000..23136ff2a4 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginupdate/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginupdate + +import _ "github.com/bufbuild/buf/private/usage" From 4ed0117d90ca7a48cc1f92b941adc8fdfd1419cd Mon Sep 17 00:00:00 2001 From: "buf-release-bot[bot]" <116301919+buf-release-bot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:33:09 -0500 Subject: [PATCH 04/14] Make upgrade (#3494) Co-authored-by: github-actions[bot] --- go.mod | 22 +++++++++++----------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index 2cd1848eec..aab2d4b101 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,11 @@ require ( connectrpc.com/otelconnect v0.7.1 github.com/bufbuild/protocompile v0.14.1 github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a - github.com/bufbuild/protovalidate-go v0.7.3-0.20241015162221-1446f1e1d576 + github.com/bufbuild/protovalidate-go v0.7.3 github.com/docker/docker v27.3.1+incompatible github.com/go-chi/chi/v5 v5.1.0 github.com/gofrs/flock v0.12.1 - github.com/google/cel-go v0.22.0 + github.com/google/cel-go v0.22.1 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 github.com/google/uuid v1.6.0 @@ -34,7 +34,7 @@ require ( github.com/rs/cors v1.11.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/tetratelabs/wazero v1.8.1 go.lsp.dev/jsonrpc2 v0.10.0 go.lsp.dev/protocol v0.12.0 @@ -53,14 +53,14 @@ require ( ) require ( - buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.1-20241007202033-cf42259fcbfc.1 // indirect + buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.2-20241007202033-cf42259fcbfc.1 // indirect cel.dev/expr v0.18.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect - github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/containerd v1.7.23 // indirect + github.com/containerd/cgroups/v3 v3.0.4 // indirect + github.com/containerd/containerd v1.7.24 // indirect github.com/containerd/continuity v0.4.5 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect @@ -84,7 +84,7 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect + github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -98,7 +98,7 @@ require ( github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/onsi/ginkgo/v2 v2.21.0 // indirect + github.com/onsi/ginkgo/v2 v2.22.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect @@ -107,7 +107,7 @@ require ( github.com/quic-go/qpack v0.5.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect - github.com/segmentio/encoding v0.4.0 // indirect + github.com/segmentio/encoding v0.4.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/vbatts/tar-split v0.11.6 // indirect @@ -122,7 +122,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/grpc v1.68.0 // indirect ) diff --git a/go.sum b/go.sum index 4190f7615c..cf3c84d1b8 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241025140216-aa40f2c9 buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241025140216-aa40f2c93090.1/go.mod h1:5iwF5l+9lKCnvr1zLvDgUHrv6X+vU5nNPjvig1sbnao= buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241025140216-aa40f2c93090.1 h1:a1OY15kRBrD1AF0SYIPYFLE8GCC1d85zqENnzUC3lNM= buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241025140216-aa40f2c93090.1/go.mod h1:EQCcR04Wp6ffVPfxNb4ZXAVJXrZJopDNKQWp37BDCgU= -buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.1-20241007202033-cf42259fcbfc.1 h1:rPi3qs3qpDIXIl5QW2IPOaYZhppRkvuVKwEZrfhpy78= -buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.1-20241007202033-cf42259fcbfc.1/go.mod h1:4IVMTaeh4JIjBYcGFLlTorfWpKVEXDjDfHAgKTeR0Ds= +buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.2-20241007202033-cf42259fcbfc.1 h1:FcoYwX9eJhc73MdVlqyJjMOQ863akpHK0VEQ/+Zkt9U= +buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.2-20241007202033-cf42259fcbfc.1/go.mod h1:uTCf/J5B6H9XCTgHuI91LC9qaNqxJxQFh0kDY/GLn2k= buf.build/go/bufplugin v0.6.0 h1:3lhoh+0z+IUPS3ZajTPn/27LaLIkero2BDVnV7yXD1s= buf.build/go/bufplugin v0.6.0/go.mod h1:hWCjxxv24xdR6F5pNlQavZV2oo0J3uF4Ff1XEoyV6vU= buf.build/go/protoyaml v0.2.0 h1:2g3OHjtLDqXBREIOjpZGHmQ+U/4mkN1YiQjxNB68Ip8= @@ -36,8 +36,8 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a h1:l3RhVoG0RtC61h6TVWnkniGj4TgBebuyPQRdleFAmTg= github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a/go.mod h1:c5D8gWRIZ2HLWO3gXYTtUfw/hbJyD8xikv2ooPxnklQ= -github.com/bufbuild/protovalidate-go v0.7.3-0.20241015162221-1446f1e1d576 h1:A4TfjZJqApnAvGKDgxHqA1rG6BK1OswyNcTcnSrDbJc= -github.com/bufbuild/protovalidate-go v0.7.3-0.20241015162221-1446f1e1d576/go.mod h1:R/UFeIPyFAh0eH7Ic/JJbO2ABdkxFuZZKDbzsI5UiwM= +github.com/bufbuild/protovalidate-go v0.7.3 h1:kKnoSueygR3xxppvuBpm9SEwIsP359MMRfMBGmRByPg= +github.com/bufbuild/protovalidate-go v0.7.3/go.mod h1:CFv34wMqiBzAHdQ4q/tWYi9ILFYKuaC3/4zh6eqdUck= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -52,10 +52,10 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= -github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= -github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4= +github.com/containerd/cgroups/v3 v3.0.4/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= +github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= +github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -137,8 +137,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g= -github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= +github.com/google/cel-go v0.22.1 h1:AfVXx3chM2qwoSbM7Da8g8hX8OVSkBFwX+rz2+PcK40= +github.com/google/cel-go v0.22.1/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -151,8 +151,8 @@ github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= -github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b h1:SXO0REt4iu865upYCk8aKBBJQ4BqoE0ReP23ClMu60s= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -203,8 +203,8 @@ github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -239,8 +239,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= -github.com/segmentio/encoding v0.4.0 h1:MEBYvRqiUB2nfR2criEXWqwdY6HJOUrCn5hboVOVmy8= -github.com/segmentio/encoding v0.4.0/go.mod h1:/d03Cd8PoaDeceuhUUUQWjU0KhWjrmYrWPgtJHYZSnI= +github.com/segmentio/encoding v0.4.1 h1:KLGaLSW0jrmhB58Nn4+98spfvPvmo4Ci1P/WIQ9wn7w= +github.com/segmentio/encoding v0.4.1/go.mod h1:/d03Cd8PoaDeceuhUUUQWjU0KhWjrmYrWPgtJHYZSnI= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -256,8 +256,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= @@ -375,10 +375,10 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f h1:M65LEviCfuZTfrfzwwEoxVtgvfkFkBUbFnRbxCXuXhU= -google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f/go.mod h1:Yo94eF2nj7igQt+TiJ49KxjIH8ndLYPZMIRSiRcEbg0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ= +google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= From b93d0e4c0c8becbd11183dd9a6f080d974e26873 Mon Sep 17 00:00:00 2001 From: Miguel Young Date: Mon, 25 Nov 2024 13:04:29 -0500 Subject: [PATCH 05/14] Fix a crash when opening files that contain fields with no numbers (#3487) The crash is a nil dereference when creating a tag symbol, if the tag happens to be nil. This can happen if the field is missing a tag number (and under other circumstances). --- private/buf/buflsp/symbol.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/private/buf/buflsp/symbol.go b/private/buf/buflsp/symbol.go index 1886272ef1..f9c07f577b 100644 --- a/private/buf/buflsp/symbol.go +++ b/private/buf/buflsp/symbol.go @@ -672,7 +672,9 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { case *ast.GroupNode: def := w.newDef(node, node.Name) w.newDef(node, node.Name) - w.newTag(node.Tag, def) + if node.Tag != nil { + w.newTag(node.Tag, def) + } // TODO: also do the name of the generated field. for _, decl := range node.Decls { w.Walk(decl, node) @@ -681,7 +683,9 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { case *ast.FieldNode: def := w.newDef(node, node.Name) w.newRef(node.FldType) - w.newTag(node.Tag, def) + if node.Tag != nil { + w.newTag(node.Tag, def) + } if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) @@ -692,7 +696,9 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { def := w.newDef(node, node.Name) w.newRef(node.MapType.KeyType) w.newRef(node.MapType.ValueType) - w.newTag(node.Tag, def) + if node.Tag != nil { + w.newTag(node.Tag, def) + } if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) @@ -717,7 +723,9 @@ func (w *symbolWalker) Walk(node, parent ast.Node) { case *ast.EnumValueNode: def := w.newDef(node, node.Name) - w.newTag(node.Number, def) + if node.Number != nil { + w.newTag(node.Number, def) + } if node.Options != nil { for _, option := range node.Options.Options { w.Walk(option, node) From 3623d54d1743190ac84151225df43eb74915ecc6 Mon Sep 17 00:00:00 2001 From: Tommy Ma <33741651+cyinma@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:23:39 -0500 Subject: [PATCH 06/14] Add audit logging events for plugin label (#3495) --- .../go/buf/alpha/audit/v1alpha1/event.pb.go | 1590 +++++++++++------ proto/buf/alpha/audit/v1alpha1/event.proto | 59 + 2 files changed, 1096 insertions(+), 553 deletions(-) diff --git a/private/gen/proto/go/buf/alpha/audit/v1alpha1/event.pb.go b/private/gen/proto/go/buf/alpha/audit/v1alpha1/event.pb.go index a23579d8b8..9369463474 100644 --- a/private/gen/proto/go/buf/alpha/audit/v1alpha1/event.pb.go +++ b/private/gen/proto/go/buf/alpha/audit/v1alpha1/event.pb.go @@ -107,6 +107,7 @@ const ( ResourceType_RESOURCE_TYPE_REPOSITORY_LABEL ResourceType = 12 ResourceType_RESOURCE_TYPE_SERVER ResourceType = 13 ResourceType_RESOURCE_TYPE_DEVICE_AUTHORIZATION_GRANT ResourceType = 14 + ResourceType_RESOURCE_TYPE_PLUGIN_LABEL ResourceType = 16 ) // Enum value maps for ResourceType. @@ -128,6 +129,7 @@ var ( 12: "RESOURCE_TYPE_REPOSITORY_LABEL", 13: "RESOURCE_TYPE_SERVER", 14: "RESOURCE_TYPE_DEVICE_AUTHORIZATION_GRANT", + 16: "RESOURCE_TYPE_PLUGIN_LABEL", } ResourceType_value = map[string]int32{ "RESOURCE_TYPE_UNSPECIFIED": 0, @@ -146,6 +148,7 @@ var ( "RESOURCE_TYPE_REPOSITORY_LABEL": 12, "RESOURCE_TYPE_SERVER": 13, "RESOURCE_TYPE_DEVICE_AUTHORIZATION_GRANT": 14, + "RESOURCE_TYPE_PLUGIN_LABEL": 16, } ) @@ -224,6 +227,10 @@ const ( EventType_EVENT_TYPE_USER_AUTO_MERGED_FROM_NEW_IDP EventType = 37 EventType_EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_APPROVED EventType = 41 EventType_EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_DENIED EventType = 42 + EventType_EVENT_TYPE_PLUGIN_LABEL_CREATED EventType = 44 + EventType_EVENT_TYPE_PLUGIN_LABEL_MOVED EventType = 45 + EventType_EVENT_TYPE_PLUGIN_LABEL_ARCHIVED EventType = 46 + EventType_EVENT_TYPE_PLUGIN_LABEL_UNARCHIVED EventType = 47 ) // Enum value maps for EventType. @@ -273,6 +280,10 @@ var ( 37: "EVENT_TYPE_USER_AUTO_MERGED_FROM_NEW_IDP", 41: "EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_APPROVED", 42: "EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_DENIED", + 44: "EVENT_TYPE_PLUGIN_LABEL_CREATED", + 45: "EVENT_TYPE_PLUGIN_LABEL_MOVED", + 46: "EVENT_TYPE_PLUGIN_LABEL_ARCHIVED", + 47: "EVENT_TYPE_PLUGIN_LABEL_UNARCHIVED", } EventType_value = map[string]int32{ "EVENT_TYPE_UNSPECIFIED": 0, @@ -319,6 +330,10 @@ var ( "EVENT_TYPE_USER_AUTO_MERGED_FROM_NEW_IDP": 37, "EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_APPROVED": 41, "EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_DENIED": 42, + "EVENT_TYPE_PLUGIN_LABEL_CREATED": 44, + "EVENT_TYPE_PLUGIN_LABEL_MOVED": 45, + "EVENT_TYPE_PLUGIN_LABEL_ARCHIVED": 46, + "EVENT_TYPE_PLUGIN_LABEL_UNARCHIVED": 47, } ) @@ -611,6 +626,10 @@ type Event struct { // *Event_UserAutoMergedFromNewIdp // *Event_DeviceAuthorizationGrantApproved // *Event_DeviceAuthorizationGrantDenied + // *Event_PluginLabelCreated + // *Event_PluginLabelMoved + // *Event_PluginLabelArchived + // *Event_PluginLabelUnarchived Payload isEvent_Payload `protobuf_oneof:"payload"` } @@ -994,6 +1013,34 @@ func (x *Event) GetDeviceAuthorizationGrantDenied() *PayloadDeviceAuthorizationG return nil } +func (x *Event) GetPluginLabelCreated() *PayloadPluginLabelCreated { + if x, ok := x.GetPayload().(*Event_PluginLabelCreated); ok { + return x.PluginLabelCreated + } + return nil +} + +func (x *Event) GetPluginLabelMoved() *PayloadPluginLabelMoved { + if x, ok := x.GetPayload().(*Event_PluginLabelMoved); ok { + return x.PluginLabelMoved + } + return nil +} + +func (x *Event) GetPluginLabelArchived() *PayloadPluginLabelArchived { + if x, ok := x.GetPayload().(*Event_PluginLabelArchived); ok { + return x.PluginLabelArchived + } + return nil +} + +func (x *Event) GetPluginLabelUnarchived() *PayloadPluginLabelUnarchived { + if x, ok := x.GetPayload().(*Event_PluginLabelUnarchived); ok { + return x.PluginLabelUnarchived + } + return nil +} + type isEvent_Payload interface { isEvent_Payload() } @@ -1170,6 +1217,22 @@ type Event_DeviceAuthorizationGrantDenied struct { DeviceAuthorizationGrantDenied *PayloadDeviceAuthorizationGrantDenied `protobuf:"bytes,48,opt,name=device_authorization_grant_denied,json=deviceAuthorizationGrantDenied,proto3,oneof"` } +type Event_PluginLabelCreated struct { + PluginLabelCreated *PayloadPluginLabelCreated `protobuf:"bytes,50,opt,name=plugin_label_created,json=pluginLabelCreated,proto3,oneof"` +} + +type Event_PluginLabelMoved struct { + PluginLabelMoved *PayloadPluginLabelMoved `protobuf:"bytes,51,opt,name=plugin_label_moved,json=pluginLabelMoved,proto3,oneof"` +} + +type Event_PluginLabelArchived struct { + PluginLabelArchived *PayloadPluginLabelArchived `protobuf:"bytes,52,opt,name=plugin_label_archived,json=pluginLabelArchived,proto3,oneof"` +} + +type Event_PluginLabelUnarchived struct { + PluginLabelUnarchived *PayloadPluginLabelUnarchived `protobuf:"bytes,53,opt,name=plugin_label_unarchived,json=pluginLabelUnarchived,proto3,oneof"` +} + func (*Event_OrganizationCreated) isEvent_Payload() {} func (*Event_OrganizationDeleted) isEvent_Payload() {} @@ -1256,6 +1319,14 @@ func (*Event_DeviceAuthorizationGrantApproved) isEvent_Payload() {} func (*Event_DeviceAuthorizationGrantDenied) isEvent_Payload() {} +func (*Event_PluginLabelCreated) isEvent_Payload() {} + +func (*Event_PluginLabelMoved) isEvent_Payload() {} + +func (*Event_PluginLabelArchived) isEvent_Payload() {} + +func (*Event_PluginLabelUnarchived) isEvent_Payload() {} + type PayloadOrganizationCreated struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3835,6 +3906,325 @@ func (x *PayloadDeviceAuthorizationGrantDenied) GetClientId() string { return "" } +type PayloadPluginLabelCreated struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // owner_id is the id of the owner of the plugin on which the label was created. + OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // owner_name is the name of the owner of the plugin on which the label was created. + OwnerName string `protobuf:"bytes,2,opt,name=owner_name,json=ownerName,proto3" json:"owner_name,omitempty"` + // plugin_id is the id of the plugin on which the label was created. + PluginId string `protobuf:"bytes,3,opt,name=plugin_id,json=pluginId,proto3" json:"plugin_id,omitempty"` + // plugin_name is the name of the plugin from which the label was created. + PluginName string `protobuf:"bytes,4,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"` + // commit_id is the id of the commit on which the label was created. + CommitId string `protobuf:"bytes,6,opt,name=commit_id,json=commitId,proto3" json:"commit_id,omitempty"` +} + +func (x *PayloadPluginLabelCreated) Reset() { + *x = PayloadPluginLabelCreated{} + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayloadPluginLabelCreated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayloadPluginLabelCreated) ProtoMessage() {} + +func (x *PayloadPluginLabelCreated) ProtoReflect() protoreflect.Message { + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[47] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayloadPluginLabelCreated.ProtoReflect.Descriptor instead. +func (*PayloadPluginLabelCreated) Descriptor() ([]byte, []int) { + return file_buf_alpha_audit_v1alpha1_event_proto_rawDescGZIP(), []int{47} +} + +func (x *PayloadPluginLabelCreated) GetOwnerId() string { + if x != nil { + return x.OwnerId + } + return "" +} + +func (x *PayloadPluginLabelCreated) GetOwnerName() string { + if x != nil { + return x.OwnerName + } + return "" +} + +func (x *PayloadPluginLabelCreated) GetPluginId() string { + if x != nil { + return x.PluginId + } + return "" +} + +func (x *PayloadPluginLabelCreated) GetPluginName() string { + if x != nil { + return x.PluginName + } + return "" +} + +func (x *PayloadPluginLabelCreated) GetCommitId() string { + if x != nil { + return x.CommitId + } + return "" +} + +type PayloadPluginLabelMoved struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // owner_id is the id of the owner of the plugin on which the label was moved. + OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // owner_name is the name of the owner of the plugin on which the label was moved. + OwnerName string `protobuf:"bytes,2,opt,name=owner_name,json=ownerName,proto3" json:"owner_name,omitempty"` + // plugin_id is the id of the plugin on which the label was moved. + PluginId string `protobuf:"bytes,3,opt,name=plugin_id,json=pluginId,proto3" json:"plugin_id,omitempty"` + // plugin_name is the name of the plugin from which the label was moved. + PluginName string `protobuf:"bytes,4,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"` + // to_commit_id is the id of the commit on which the label was moved to. + ToCommitId string `protobuf:"bytes,6,opt,name=to_commit_id,json=toCommitId,proto3" json:"to_commit_id,omitempty"` + // from_commit_id is the id of the commit on which the label was moved from. + FromCommitId string `protobuf:"bytes,7,opt,name=from_commit_id,json=fromCommitId,proto3" json:"from_commit_id,omitempty"` +} + +func (x *PayloadPluginLabelMoved) Reset() { + *x = PayloadPluginLabelMoved{} + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayloadPluginLabelMoved) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayloadPluginLabelMoved) ProtoMessage() {} + +func (x *PayloadPluginLabelMoved) ProtoReflect() protoreflect.Message { + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[48] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayloadPluginLabelMoved.ProtoReflect.Descriptor instead. +func (*PayloadPluginLabelMoved) Descriptor() ([]byte, []int) { + return file_buf_alpha_audit_v1alpha1_event_proto_rawDescGZIP(), []int{48} +} + +func (x *PayloadPluginLabelMoved) GetOwnerId() string { + if x != nil { + return x.OwnerId + } + return "" +} + +func (x *PayloadPluginLabelMoved) GetOwnerName() string { + if x != nil { + return x.OwnerName + } + return "" +} + +func (x *PayloadPluginLabelMoved) GetPluginId() string { + if x != nil { + return x.PluginId + } + return "" +} + +func (x *PayloadPluginLabelMoved) GetPluginName() string { + if x != nil { + return x.PluginName + } + return "" +} + +func (x *PayloadPluginLabelMoved) GetToCommitId() string { + if x != nil { + return x.ToCommitId + } + return "" +} + +func (x *PayloadPluginLabelMoved) GetFromCommitId() string { + if x != nil { + return x.FromCommitId + } + return "" +} + +type PayloadPluginLabelArchived struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // owner_id is the id of the owner of the plugin on which the label was archived. + OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // owner_name is the name of the owner of the plugin on which the label was archived. + OwnerName string `protobuf:"bytes,2,opt,name=owner_name,json=ownerName,proto3" json:"owner_name,omitempty"` + // plugin_id is the id of the plugin on which the label was archived. + PluginId string `protobuf:"bytes,3,opt,name=plugin_id,json=pluginId,proto3" json:"plugin_id,omitempty"` + // plugin_name is the name of the plugin from which the label was archived. + PluginName string `protobuf:"bytes,4,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"` +} + +func (x *PayloadPluginLabelArchived) Reset() { + *x = PayloadPluginLabelArchived{} + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayloadPluginLabelArchived) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayloadPluginLabelArchived) ProtoMessage() {} + +func (x *PayloadPluginLabelArchived) ProtoReflect() protoreflect.Message { + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[49] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayloadPluginLabelArchived.ProtoReflect.Descriptor instead. +func (*PayloadPluginLabelArchived) Descriptor() ([]byte, []int) { + return file_buf_alpha_audit_v1alpha1_event_proto_rawDescGZIP(), []int{49} +} + +func (x *PayloadPluginLabelArchived) GetOwnerId() string { + if x != nil { + return x.OwnerId + } + return "" +} + +func (x *PayloadPluginLabelArchived) GetOwnerName() string { + if x != nil { + return x.OwnerName + } + return "" +} + +func (x *PayloadPluginLabelArchived) GetPluginId() string { + if x != nil { + return x.PluginId + } + return "" +} + +func (x *PayloadPluginLabelArchived) GetPluginName() string { + if x != nil { + return x.PluginName + } + return "" +} + +type PayloadPluginLabelUnarchived struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // owner_id is the id of the owner of the plugin on which the label was unarchived. + OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + // owner_name is the name of the owner of the plugin on which the label was unarchived. + OwnerName string `protobuf:"bytes,2,opt,name=owner_name,json=ownerName,proto3" json:"owner_name,omitempty"` + // plugin_id is the id of the plugin on which the label was unarchived. + PluginId string `protobuf:"bytes,3,opt,name=plugin_id,json=pluginId,proto3" json:"plugin_id,omitempty"` + // plugin_name is the name of the plugin from which the label was unarchived. + PluginName string `protobuf:"bytes,4,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"` +} + +func (x *PayloadPluginLabelUnarchived) Reset() { + *x = PayloadPluginLabelUnarchived{} + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PayloadPluginLabelUnarchived) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PayloadPluginLabelUnarchived) ProtoMessage() {} + +func (x *PayloadPluginLabelUnarchived) ProtoReflect() protoreflect.Message { + mi := &file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[50] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PayloadPluginLabelUnarchived.ProtoReflect.Descriptor instead. +func (*PayloadPluginLabelUnarchived) Descriptor() ([]byte, []int) { + return file_buf_alpha_audit_v1alpha1_event_proto_rawDescGZIP(), []int{50} +} + +func (x *PayloadPluginLabelUnarchived) GetOwnerId() string { + if x != nil { + return x.OwnerId + } + return "" +} + +func (x *PayloadPluginLabelUnarchived) GetOwnerName() string { + if x != nil { + return x.OwnerName + } + return "" +} + +func (x *PayloadPluginLabelUnarchived) GetPluginId() string { + if x != nil { + return x.PluginId + } + return "" +} + +func (x *PayloadPluginLabelUnarchived) GetPluginName() string { + if x != nil { + return x.PluginName + } + return "" +} + var File_buf_alpha_audit_v1alpha1_event_proto protoreflect.FileDescriptor var file_buf_alpha_audit_v1alpha1_event_proto_rawDesc = []byte{ @@ -3870,7 +4260,7 @@ var file_buf_alpha_audit_v1alpha1_event_proto_rawDesc = []byte{ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x22, 0x91, 0x2a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x22, 0xbb, 0x2d, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, @@ -4207,563 +4597,645 @@ var file_buf_alpha_audit_v1alpha1_event_proto_rawDesc = []byte{ 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x48, 0x00, 0x52, 0x1e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0x1c, 0x0a, 0x1a, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, - 0x1c, 0x0a, 0x1a, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xa9, 0x02, - 0x0a, 0x1e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x41, 0x64, 0x64, 0x65, 0x64, - 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, - 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, - 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xe4, 0x03, 0x0a, 0x24, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, - 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, - 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x52, 0x6f, - 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x68, 0x0a, 0x16, - 0x6f, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, + 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x12, 0x67, 0x0a, 0x14, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x32, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x12, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, + 0x61, 0x0a, 0x12, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x62, 0x75, + 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x48, 0x00, + 0x52, 0x10, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4d, 0x6f, 0x76, + 0x65, 0x64, 0x12, 0x6a, 0x0a, 0x15, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x34, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x34, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x48, 0x00, 0x52, 0x13, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x70, + 0x0a, 0x17, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x75, + 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x36, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x55, 0x6e, 0x61, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x48, 0x00, 0x52, 0x15, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, + 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x1c, 0x0a, 0x1a, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x1c, 0x0a, 0x1a, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xa9, 0x02, 0x0a, 0x1e, 0x50, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, + 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x4e, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, + 0x12, 0x61, 0x0a, 0x12, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x13, 0x6f, 0x6c, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x16, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, + 0x65, 0x52, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x22, 0xe4, 0x03, 0x0a, 0x24, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x48, 0x0a, 0x08, + 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, + 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, + 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6e, + 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x68, 0x0a, 0x16, 0x6f, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x13, 0x6e, 0x65, 0x77, + 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x13, 0x6f, 0x6c, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x22, 0xab, 0x02, 0x0a, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, - 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, + 0x12, 0x68, 0x0a, 0x16, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, + 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x52, - 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x10, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x78, - 0x0a, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x50, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x41, 0x64, 0x64, - 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x7a, 0x0a, 0x22, 0x50, 0x61, 0x79, 0x6c, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x13, 0x6e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xab, 0x02, 0x0a, 0x20, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, + 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, + 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x62, 0x75, 0x66, + 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, + 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6c, 0x65, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x10, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, + 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x78, 0x0a, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x44, 0x50, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x27, - 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x18, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x76, - 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x27, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x18, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, - 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x76, 0x69, 0x73, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, - 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x22, 0xa0, 0x02, 0x0a, 0x1d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x50, 0x75, - 0x73, 0x68, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, - 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x72, 0x61, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x27, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, - 0x73, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x35, 0x5f, 0x64, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x35, 0x44, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x21, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, + 0x44, 0x50, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x22, 0x7a, 0x0a, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4f, 0x72, 0x67, + 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x50, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x72, + 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xcb, + 0x01, 0x0a, 0x18, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x6f, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, - 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0xc1, 0x02, 0x0a, 0x27, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52, 0x6f, 0x6c, 0x65, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x46, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, - 0x6f, 0x6c, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, - 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x22, - 0x85, 0x02, 0x0a, 0x23, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x56, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, - 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x6f, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0xfe, 0x01, 0x0a, 0x22, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x56, 0x69, 0x73, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x19, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2c, + 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9d, 0x01, 0x0a, + 0x18, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0xa0, 0x02, 0x0a, + 0x1d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, - 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, - 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6f, 0x6c, 0x64, 0x56, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x4e, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, - 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, - 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x56, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x28, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, + 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x72, + 0x61, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x64, 0x72, 0x61, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x44, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x35, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x35, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, + 0x83, 0x02, 0x0a, 0x21, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, + 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x33, 0x0a, 0x16, 0x6f, 0x6c, 0x64, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x13, 0x6f, 0x6c, 0x64, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x6e, 0x65, 0x77, 0x5f, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6e, 0x65, 0x77, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x25, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x44, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, - 0x12, 0x6f, 0x6c, 0x64, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x62, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6c, 0x64, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x2c, 0x0a, 0x12, 0x6e, - 0x65, 0x77, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x71, 0x0a, 0x14, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, + 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x6f, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0xc1, 0x02, 0x0a, 0x27, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, + 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x6f, 0x6c, 0x64, + 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, + 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x52, 0x6f, 0x6c, + 0x65, 0x12, 0x46, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, + 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x22, 0x85, 0x02, 0x0a, 0x23, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0x71, 0x0a, 0x14, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, - 0xb0, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x50, 0x75, 0x73, 0x68, 0x65, 0x64, 0x12, 0x19, 0x0a, + 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, + 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x56, 0x0a, 0x10, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x6f, 0x6c, 0x65, + 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52, 0x6f, 0x6c, + 0x65, 0x22, 0xfe, 0x01, 0x0a, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, + 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6f, 0x6c, 0x64, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x12, 0x4e, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x66, + 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x28, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x6f, 0x6c, 0x64, + 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6f, 0x6c, 0x64, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, + 0x0a, 0x16, 0x6e, 0x65, 0x77, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, + 0x6e, 0x65, 0x77, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x25, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x31, 0x5f, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x31, 0x44, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x22, 0x14, 0x0a, 0x12, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x6c, 0x64, 0x5f, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6c, 0x64, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x77, 0x5f, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x22, 0x71, 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0x71, 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x19, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x50, 0x75, 0x73, 0x68, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x31, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x31, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x14, 0x0a, 0x12, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x22, 0x14, 0x0a, 0x12, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x49, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x4f, 0x75, - 0x74, 0x22, 0x21, 0x0a, 0x1f, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, - 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x65, - 0x77, 0x49, 0x64, 0x50, 0x22, 0x57, 0x0a, 0x1b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, - 0x75, 0x72, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x57, 0x0a, - 0x1b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x75, 0x72, 0x61, 0x74, 0x65, 0x64, 0x50, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x78, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, + 0x72, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x22, 0x18, 0x0a, 0x16, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x15, 0x0a, 0x13, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x67, 0x65, + 0x64, 0x49, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x22, 0x21, 0x0a, 0x1f, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x65, 0x72, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x65, + 0x72, 0x67, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x65, 0x77, 0x49, 0x64, 0x50, 0x22, 0x57, + 0x0a, 0x1b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x75, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x46, 0x0a, 0x11, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, - 0x22, 0x30, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x57, 0x0a, 0x1b, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x43, 0x75, 0x72, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x22, 0x78, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x49, 0x64, 0x22, 0x61, 0x0a, 0x17, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x43, 0x49, - 0x4d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x46, 0x0a, - 0x11, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, - 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x53, 0x43, 0x49, 0x4d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, - 0x22, 0xc7, 0x01, 0x0a, 0x1e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, - 0x72, 0x61, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x64, 0x72, 0x61, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x1d, 0x50, + 0x49, 0x64, 0x12, 0x46, 0x0a, 0x11, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x30, 0x0a, 0x13, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x61, 0x0a, 0x17, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x43, 0x49, 0x4d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x11, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, + 0x19, 0x0a, 0x17, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x43, 0x49, 0x4d, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xc7, 0x01, 0x0a, 0x1e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x0f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x22, 0x9a, - 0x02, 0x0a, 0x1b, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, - 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x0f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x02, 0x18, 0x01, 0x52, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, - 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x1e, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x79, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, - 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x28, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x4f, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x12, 0x3d, 0x0a, 0x18, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x75, 0x6e, 0x73, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x16, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x55, 0x6e, 0x73, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, - 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x75, 0x6e, 0x73, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2b, 0x0a, - 0x29, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x71, 0x75, - 0x65, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x22, 0x27, 0x0a, 0x25, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x46, 0x0a, 0x27, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x41, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, + 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x72, 0x61, 0x66, 0x74, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x72, 0x61, 0x66, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x1d, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, + 0x0a, 0x0f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x22, 0x9a, 0x02, 0x0a, 0x1b, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x4d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x2b, 0x0a, 0x0f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, + 0x0c, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, + 0x24, 0x0a, 0x0e, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x49, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x1e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, + 0x22, 0xaa, 0x01, 0x0a, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x55, 0x6e, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd7, 0x01, + 0x0a, 0x28, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, + 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x08, 0x63, 0x61, + 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x62, + 0x75, 0x66, 0x2e, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x79, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x72, 0x65, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, + 0x79, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x18, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x16, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x55, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x22, 0x2b, 0x0a, 0x29, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x27, 0x0a, 0x25, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x55, 0x6e, 0x69, + 0x71, 0x75, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x46, 0x0a, 0x27, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x44, 0x0a, + 0x25, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x22, 0x44, 0x0a, 0x25, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x44, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x2a, 0x53, 0x0a, 0x09, 0x41, 0x63, 0x74, - 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x43, 0x54, 0x4f, 0x52, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x02, 0x2a, 0xa3, - 0x04, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, - 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x74, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x22, 0xd9, 0x01, 0x0a, 0x17, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4d, 0x6f, 0x76, + 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, + 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x74, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x49, 0x64, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x1c, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x55, 0x6e, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x2a, 0x53, 0x0a, 0x09, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x1a, 0x0a, 0x16, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, + 0x43, 0x54, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, + 0x12, 0x15, 0x0a, 0x11, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, + 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x02, 0x2a, 0xc3, 0x04, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, + 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, + 0x1e, 0x0a, 0x1a, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, + 0x25, 0x0a, 0x21, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, + 0x4d, 0x42, 0x45, 0x52, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x03, 0x12, 0x28, 0x0a, - 0x24, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, - 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x50, 0x5f, - 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x09, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, - 0x4f, 0x52, 0x59, 0x10, 0x04, 0x12, 0x28, 0x0a, 0x24, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, - 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x10, 0x05, 0x12, - 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, - 0x49, 0x54, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x07, 0x12, 0x1f, - 0x0a, 0x1b, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0f, 0x12, - 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, - 0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x10, 0x0a, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x49, 0x4d, - 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x10, 0x0b, 0x12, 0x22, 0x0a, 0x1e, 0x52, 0x45, 0x53, 0x4f, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x50, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x09, + 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x04, 0x12, 0x28, + 0x0a, 0x24, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, + 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, - 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, - 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, - 0x52, 0x56, 0x45, 0x52, 0x10, 0x0d, 0x12, 0x2c, 0x0a, 0x28, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x41, - 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x41, - 0x4e, 0x54, 0x10, 0x0e, 0x2a, 0x8b, 0x0e, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, - 0x0a, 0x1f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, - 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x44, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x44, 0x45, 0x44, - 0x10, 0x03, 0x12, 0x2f, 0x0a, 0x2b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, - 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, - 0x44, 0x10, 0x04, 0x12, 0x2a, 0x0a, 0x26, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, - 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x05, 0x12, - 0x2b, 0x0a, 0x27, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, - 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x50, 0x5f, 0x47, - 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x15, 0x12, 0x2d, 0x0a, 0x29, + 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x06, 0x12, 0x18, 0x0a, + 0x14, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, + 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, + 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x0f, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x53, 0x4f, + 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, + 0x44, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x4f, 0x4b, 0x45, + 0x4e, 0x10, 0x0a, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x49, 0x4d, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x10, + 0x0b, 0x12, 0x22, 0x0a, 0x1e, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, + 0x42, 0x45, 0x4c, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x0d, 0x12, + 0x2c, 0x0a, 0x28, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x10, 0x0e, 0x12, 0x1e, 0x0a, + 0x1a, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, + 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x10, 0x10, 0x2a, 0xa1, 0x0f, + 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, + 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x45, 0x4e, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, - 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x50, 0x5f, 0x47, 0x52, 0x4f, 0x55, - 0x50, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x16, 0x12, 0x21, 0x0a, 0x1d, 0x45, - 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, - 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x21, - 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, - 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, - 0x07, 0x12, 0x27, 0x0a, 0x23, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, - 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x45, 0x44, 0x10, 0x08, 0x12, 0x2b, 0x0a, 0x27, 0x45, 0x56, - 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, - 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x5f, - 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x09, 0x12, 0x32, 0x0a, 0x2e, 0x45, 0x56, 0x45, 0x4e, 0x54, + 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, + 0x02, 0x12, 0x28, 0x0a, 0x24, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x4d, + 0x42, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x2f, 0x0a, 0x2b, 0x45, + 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, + 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, 0x4f, + 0x4c, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x04, 0x12, 0x2a, 0x0a, 0x26, + 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, + 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x52, + 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x05, 0x12, 0x2b, 0x0a, 0x27, 0x45, 0x56, 0x45, 0x4e, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x50, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x41, 0x44, + 0x44, 0x45, 0x44, 0x10, 0x15, 0x12, 0x2d, 0x0a, 0x29, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x49, 0x44, 0x50, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, + 0x45, 0x44, 0x10, 0x16, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x52, + 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, - 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x4f, 0x4c, - 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x2d, 0x0a, 0x29, 0x45, - 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, - 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, - 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x0b, 0x12, 0x2c, 0x0a, 0x28, 0x45, 0x56, + 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x27, 0x0a, 0x23, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, - 0x4f, 0x52, 0x59, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x0c, 0x12, 0x34, 0x0a, 0x30, 0x45, 0x56, 0x45, 0x4e, + 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x45, + 0x44, 0x10, 0x08, 0x12, 0x2b, 0x0a, 0x27, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, + 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x09, + 0x12, 0x32, 0x0a, 0x2e, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, + 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, + 0x42, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, + 0x45, 0x44, 0x10, 0x0a, 0x12, 0x2d, 0x0a, 0x29, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, + 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, + 0x44, 0x10, 0x0b, 0x12, 0x2c, 0x0a, 0x28, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x56, 0x49, 0x53, + 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, + 0x0c, 0x12, 0x34, 0x0a, 0x30, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, + 0x4c, 0x54, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x48, + 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x28, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x56, 0x45, 0x4e, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, + 0x54, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, + 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x45, 0x44, 0x10, 0x2b, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x56, + 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, 0x44, + 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, + 0x14, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x1f, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x56, 0x45, 0x4e, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x43, 0x52, 0x45, 0x41, + 0x54, 0x45, 0x44, 0x10, 0x0f, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, + 0x10, 0x10, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, + 0x44, 0x10, 0x11, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4c, 0x4f, 0x47, 0x47, 0x45, 0x44, 0x5f, 0x49, 0x4e, + 0x10, 0x12, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4c, 0x4f, 0x47, 0x47, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, + 0x10, 0x13, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x17, + 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, + 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x18, 0x12, 0x1f, + 0x0a, 0x1b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, + 0x52, 0x5f, 0x52, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x44, 0x10, 0x19, 0x12, + 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, + 0x49, 0x4d, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, + 0x10, 0x1a, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x53, 0x43, 0x49, 0x4d, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, + 0x54, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x28, 0x0a, 0x24, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, + 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x1c, 0x12, + 0x27, 0x0a, 0x23, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x1d, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, - 0x59, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, - 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x28, 0x12, 0x1d, - 0x0a, 0x19, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, - 0x47, 0x49, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x1d, 0x0a, - 0x19, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, - 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x23, 0x0a, 0x1f, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, - 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x50, 0x55, 0x53, 0x48, 0x45, 0x44, 0x10, - 0x2b, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x43, - 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x14, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x55, 0x52, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x50, - 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x1f, 0x12, - 0x1b, 0x0a, 0x17, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, - 0x45, 0x52, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x0f, 0x12, 0x1b, 0x0a, 0x17, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, - 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x10, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x56, 0x45, - 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x41, - 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x44, 0x10, 0x11, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x56, - 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4c, 0x4f, - 0x47, 0x47, 0x45, 0x44, 0x5f, 0x49, 0x4e, 0x10, 0x12, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x56, 0x45, - 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x4c, 0x4f, 0x47, - 0x47, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x13, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x56, 0x45, - 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x43, 0x52, - 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x17, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x56, 0x45, 0x4e, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, - 0x54, 0x45, 0x44, 0x10, 0x18, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, - 0x41, 0x54, 0x45, 0x44, 0x10, 0x19, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x49, 0x4d, 0x5f, 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x1a, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, - 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x49, 0x4d, 0x5f, 0x54, 0x4f, 0x4b, - 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x28, 0x0a, 0x24, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, - 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x4c, - 0x45, 0x54, 0x45, 0x44, 0x10, 0x1c, 0x12, 0x27, 0x0a, 0x23, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, - 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x1d, 0x12, - 0x25, 0x0a, 0x21, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, - 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4d, - 0x4f, 0x56, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x28, 0x0a, 0x24, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, - 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x26, - 0x12, 0x2a, 0x0a, 0x26, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, - 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, - 0x55, 0x4e, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x27, 0x12, 0x34, 0x0a, 0x30, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, - 0x52, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, - 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, - 0x10, 0x20, 0x12, 0x35, 0x0a, 0x31, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, 0x47, - 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, - 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x21, 0x12, 0x30, 0x0a, 0x2c, 0x45, 0x56, 0x45, + 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x1e, 0x12, + 0x28, 0x0a, 0x24, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x41, + 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x26, 0x12, 0x2a, 0x0a, 0x26, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, - 0x52, 0x59, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x42, 0x52, 0x41, 0x4e, 0x43, - 0x48, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x22, 0x12, 0x2f, 0x0a, 0x2b, 0x45, + 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x41, 0x52, 0x43, 0x48, 0x49, + 0x56, 0x45, 0x44, 0x10, 0x27, 0x12, 0x34, 0x0a, 0x30, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, + 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, + 0x59, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x20, 0x12, 0x35, 0x0a, 0x31, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, - 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x4f, 0x4c, 0x49, - 0x43, 0x59, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x23, 0x12, 0x30, 0x0a, 0x2c, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, - 0x52, 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x4f, 0x4c, - 0x49, 0x43, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x24, 0x12, 0x2c, - 0x0a, 0x28, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, - 0x52, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x4d, 0x45, 0x52, 0x47, 0x45, 0x44, 0x5f, 0x46, 0x52, - 0x4f, 0x4d, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x49, 0x44, 0x50, 0x10, 0x25, 0x12, 0x32, 0x0a, 0x2e, - 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, - 0x45, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x47, 0x52, 0x41, 0x4e, 0x54, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x29, - 0x12, 0x30, 0x0a, 0x2c, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, - 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, - 0x10, 0x2a, 0x42, 0x82, 0x02, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x75, - 0x66, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, - 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x75, 0x64, 0x69, 0x74, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x41, 0x41, 0xaa, 0x02, 0x18, 0x42, - 0x75, 0x66, 0x2e, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x18, 0x42, 0x75, 0x66, 0x5c, 0x41, 0x6c, - 0x70, 0x68, 0x61, 0x5c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0xe2, 0x02, 0x24, 0x42, 0x75, 0x66, 0x5c, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x41, - 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1b, 0x42, 0x75, 0x66, 0x3a, - 0x3a, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x3a, 0x3a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x3a, 0x3a, 0x56, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5f, 0x42, 0x52, 0x45, 0x41, 0x4b, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, + 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, + 0x10, 0x21, 0x12, 0x30, 0x0a, 0x2c, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x5f, 0x42, 0x52, 0x41, 0x4e, 0x43, 0x48, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, + 0x45, 0x44, 0x10, 0x22, 0x12, 0x2f, 0x0a, 0x2b, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, + 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x45, 0x4e, 0x41, 0x42, + 0x4c, 0x45, 0x44, 0x10, 0x23, 0x12, 0x30, 0x0a, 0x2c, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x49, 0x51, 0x55, + 0x45, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x44, 0x49, 0x53, + 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x24, 0x12, 0x2c, 0x0a, 0x28, 0x45, 0x56, 0x45, 0x4e, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x5f, + 0x4d, 0x45, 0x52, 0x47, 0x45, 0x44, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x4e, 0x45, 0x57, 0x5f, + 0x49, 0x44, 0x50, 0x10, 0x25, 0x12, 0x32, 0x0a, 0x2e, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x4f, + 0x52, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x5f, 0x41, + 0x50, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x29, 0x12, 0x30, 0x0a, 0x2c, 0x45, 0x56, 0x45, + 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x41, + 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x52, 0x41, + 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x2a, 0x12, 0x23, 0x0a, 0x1f, 0x45, + 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, + 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x2c, + 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, + 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x45, + 0x44, 0x10, 0x2d, 0x12, 0x24, 0x0a, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x41, + 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x2e, 0x12, 0x26, 0x0a, 0x22, 0x45, 0x56, 0x45, + 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x5f, 0x4c, + 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, + 0x2f, 0x42, 0x82, 0x02, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x75, 0x66, 0x2e, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x75, 0x66, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x62, + 0x75, 0x66, 0x2f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x61, 0x75, 0x64, 0x69, 0x74, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x41, 0x41, 0xaa, 0x02, 0x18, 0x42, 0x75, + 0x66, 0x2e, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x18, 0x42, 0x75, 0x66, 0x5c, 0x41, 0x6c, 0x70, + 0x68, 0x61, 0x5c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0xe2, 0x02, 0x24, 0x42, 0x75, 0x66, 0x5c, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1b, 0x42, 0x75, 0x66, 0x3a, 0x3a, + 0x41, 0x6c, 0x70, 0x68, 0x61, 0x3a, 0x3a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x3a, 0x3a, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4779,7 +5251,7 @@ func file_buf_alpha_audit_v1alpha1_event_proto_rawDescGZIP() []byte { } var file_buf_alpha_audit_v1alpha1_event_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_buf_alpha_audit_v1alpha1_event_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_buf_alpha_audit_v1alpha1_event_proto_msgTypes = make([]protoimpl.MessageInfo, 51) var file_buf_alpha_audit_v1alpha1_event_proto_goTypes = []any{ (ActorType)(0), // 0: buf.alpha.audit.v1alpha1.ActorType (ResourceType)(0), // 1: buf.alpha.audit.v1alpha1.ResourceType @@ -4831,12 +5303,16 @@ var file_buf_alpha_audit_v1alpha1_event_proto_goTypes = []any{ (*PayloadServerUniquenessPolicyDisabled)(nil), // 47: buf.alpha.audit.v1alpha1.PayloadServerUniquenessPolicyDisabled (*PayloadDeviceAuthorizationGrantApproved)(nil), // 48: buf.alpha.audit.v1alpha1.PayloadDeviceAuthorizationGrantApproved (*PayloadDeviceAuthorizationGrantDenied)(nil), // 49: buf.alpha.audit.v1alpha1.PayloadDeviceAuthorizationGrantDenied - (*timestamppb.Timestamp)(nil), // 50: google.protobuf.Timestamp - (v1alpha1.OrganizationRole)(0), // 51: buf.alpha.registry.v1alpha1.OrganizationRole - (v1alpha1.OrganizationRoleSource)(0), // 52: buf.alpha.registry.v1alpha1.OrganizationRoleSource - (v1alpha1.Visibility)(0), // 53: buf.alpha.registry.v1alpha1.Visibility - (v1alpha1.RepositoryRole)(0), // 54: buf.alpha.registry.v1alpha1.RepositoryRole - (v1alpha1.BreakingChangeCategory)(0), // 55: buf.alpha.registry.v1alpha1.BreakingChangeCategory + (*PayloadPluginLabelCreated)(nil), // 50: buf.alpha.audit.v1alpha1.PayloadPluginLabelCreated + (*PayloadPluginLabelMoved)(nil), // 51: buf.alpha.audit.v1alpha1.PayloadPluginLabelMoved + (*PayloadPluginLabelArchived)(nil), // 52: buf.alpha.audit.v1alpha1.PayloadPluginLabelArchived + (*PayloadPluginLabelUnarchived)(nil), // 53: buf.alpha.audit.v1alpha1.PayloadPluginLabelUnarchived + (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp + (v1alpha1.OrganizationRole)(0), // 55: buf.alpha.registry.v1alpha1.OrganizationRole + (v1alpha1.OrganizationRoleSource)(0), // 56: buf.alpha.registry.v1alpha1.OrganizationRoleSource + (v1alpha1.Visibility)(0), // 57: buf.alpha.registry.v1alpha1.Visibility + (v1alpha1.RepositoryRole)(0), // 58: buf.alpha.registry.v1alpha1.RepositoryRole + (v1alpha1.BreakingChangeCategory)(0), // 59: buf.alpha.registry.v1alpha1.BreakingChangeCategory } var file_buf_alpha_audit_v1alpha1_event_proto_depIdxs = []int32{ 0, // 0: buf.alpha.audit.v1alpha1.Actor.type:type_name -> buf.alpha.audit.v1alpha1.ActorType @@ -4844,7 +5320,7 @@ var file_buf_alpha_audit_v1alpha1_event_proto_depIdxs = []int32{ 2, // 2: buf.alpha.audit.v1alpha1.Event.type:type_name -> buf.alpha.audit.v1alpha1.EventType 3, // 3: buf.alpha.audit.v1alpha1.Event.actor:type_name -> buf.alpha.audit.v1alpha1.Actor 4, // 4: buf.alpha.audit.v1alpha1.Event.resource:type_name -> buf.alpha.audit.v1alpha1.Resource - 50, // 5: buf.alpha.audit.v1alpha1.Event.event_time:type_name -> google.protobuf.Timestamp + 54, // 5: buf.alpha.audit.v1alpha1.Event.event_time:type_name -> google.protobuf.Timestamp 5, // 6: buf.alpha.audit.v1alpha1.Event.metadata:type_name -> buf.alpha.audit.v1alpha1.EventMetadata 7, // 7: buf.alpha.audit.v1alpha1.Event.organization_created:type_name -> buf.alpha.audit.v1alpha1.PayloadOrganizationCreated 8, // 8: buf.alpha.audit.v1alpha1.Event.organization_deleted:type_name -> buf.alpha.audit.v1alpha1.PayloadOrganizationDeleted @@ -4889,30 +5365,34 @@ var file_buf_alpha_audit_v1alpha1_event_proto_depIdxs = []int32{ 32, // 47: buf.alpha.audit.v1alpha1.Event.user_auto_merged_from_new_idp:type_name -> buf.alpha.audit.v1alpha1.PayloadUserAutoMergedFromNewIdP 48, // 48: buf.alpha.audit.v1alpha1.Event.device_authorization_grant_approved:type_name -> buf.alpha.audit.v1alpha1.PayloadDeviceAuthorizationGrantApproved 49, // 49: buf.alpha.audit.v1alpha1.Event.device_authorization_grant_denied:type_name -> buf.alpha.audit.v1alpha1.PayloadDeviceAuthorizationGrantDenied - 51, // 50: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberAdded.member_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole - 52, // 51: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberAdded.member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource - 51, // 52: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.old_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole - 51, // 53: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.new_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole - 52, // 54: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.old_member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource - 52, // 55: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.new_member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource - 51, // 56: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRemoved.member_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole - 52, // 57: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRemoved.member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource - 53, // 58: buf.alpha.audit.v1alpha1.PayloadRepositoryCreated.visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility - 53, // 59: buf.alpha.audit.v1alpha1.PayloadRepositoryDeleted.visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility - 54, // 60: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorAdded.contributor_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole - 54, // 61: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRoleChanged.old_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole - 54, // 62: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRoleChanged.new_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole - 54, // 63: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRemoved.contributor_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole - 53, // 64: buf.alpha.audit.v1alpha1.PayloadRepositoryVisibilityChanged.old_visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility - 53, // 65: buf.alpha.audit.v1alpha1.PayloadRepositoryVisibilityChanged.new_visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility - 50, // 66: buf.alpha.audit.v1alpha1.PayloadTokenCreated.token_expiry_time:type_name -> google.protobuf.Timestamp - 50, // 67: buf.alpha.audit.v1alpha1.PayloadSCIMTokenCreated.token_expiry_time:type_name -> google.protobuf.Timestamp - 55, // 68: buf.alpha.audit.v1alpha1.PayloadServerBreakingChangePolicyEnabled.category:type_name -> buf.alpha.registry.v1alpha1.BreakingChangeCategory - 69, // [69:69] is the sub-list for method output_type - 69, // [69:69] is the sub-list for method input_type - 69, // [69:69] is the sub-list for extension type_name - 69, // [69:69] is the sub-list for extension extendee - 0, // [0:69] is the sub-list for field type_name + 50, // 50: buf.alpha.audit.v1alpha1.Event.plugin_label_created:type_name -> buf.alpha.audit.v1alpha1.PayloadPluginLabelCreated + 51, // 51: buf.alpha.audit.v1alpha1.Event.plugin_label_moved:type_name -> buf.alpha.audit.v1alpha1.PayloadPluginLabelMoved + 52, // 52: buf.alpha.audit.v1alpha1.Event.plugin_label_archived:type_name -> buf.alpha.audit.v1alpha1.PayloadPluginLabelArchived + 53, // 53: buf.alpha.audit.v1alpha1.Event.plugin_label_unarchived:type_name -> buf.alpha.audit.v1alpha1.PayloadPluginLabelUnarchived + 55, // 54: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberAdded.member_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole + 56, // 55: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberAdded.member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource + 55, // 56: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.old_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole + 55, // 57: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.new_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole + 56, // 58: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.old_member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource + 56, // 59: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRoleChanged.new_member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource + 55, // 60: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRemoved.member_role:type_name -> buf.alpha.registry.v1alpha1.OrganizationRole + 56, // 61: buf.alpha.audit.v1alpha1.PayloadOrganizationMemberRemoved.member_role_source:type_name -> buf.alpha.registry.v1alpha1.OrganizationRoleSource + 57, // 62: buf.alpha.audit.v1alpha1.PayloadRepositoryCreated.visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility + 57, // 63: buf.alpha.audit.v1alpha1.PayloadRepositoryDeleted.visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility + 58, // 64: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorAdded.contributor_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole + 58, // 65: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRoleChanged.old_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole + 58, // 66: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRoleChanged.new_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole + 58, // 67: buf.alpha.audit.v1alpha1.PayloadRepositoryContributorRemoved.contributor_role:type_name -> buf.alpha.registry.v1alpha1.RepositoryRole + 57, // 68: buf.alpha.audit.v1alpha1.PayloadRepositoryVisibilityChanged.old_visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility + 57, // 69: buf.alpha.audit.v1alpha1.PayloadRepositoryVisibilityChanged.new_visibility:type_name -> buf.alpha.registry.v1alpha1.Visibility + 54, // 70: buf.alpha.audit.v1alpha1.PayloadTokenCreated.token_expiry_time:type_name -> google.protobuf.Timestamp + 54, // 71: buf.alpha.audit.v1alpha1.PayloadSCIMTokenCreated.token_expiry_time:type_name -> google.protobuf.Timestamp + 59, // 72: buf.alpha.audit.v1alpha1.PayloadServerBreakingChangePolicyEnabled.category:type_name -> buf.alpha.registry.v1alpha1.BreakingChangeCategory + 73, // [73:73] is the sub-list for method output_type + 73, // [73:73] is the sub-list for method input_type + 73, // [73:73] is the sub-list for extension type_name + 73, // [73:73] is the sub-list for extension extendee + 0, // [0:73] is the sub-list for field type_name } func init() { file_buf_alpha_audit_v1alpha1_event_proto_init() } @@ -4964,6 +5444,10 @@ func file_buf_alpha_audit_v1alpha1_event_proto_init() { (*Event_UserAutoMergedFromNewIdp)(nil), (*Event_DeviceAuthorizationGrantApproved)(nil), (*Event_DeviceAuthorizationGrantDenied)(nil), + (*Event_PluginLabelCreated)(nil), + (*Event_PluginLabelMoved)(nil), + (*Event_PluginLabelArchived)(nil), + (*Event_PluginLabelUnarchived)(nil), } file_buf_alpha_audit_v1alpha1_event_proto_msgTypes[41].OneofWrappers = []any{} type x struct{} @@ -4972,7 +5456,7 @@ func file_buf_alpha_audit_v1alpha1_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_buf_alpha_audit_v1alpha1_event_proto_rawDesc, NumEnums: 3, - NumMessages: 47, + NumMessages: 51, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/buf/alpha/audit/v1alpha1/event.proto b/proto/buf/alpha/audit/v1alpha1/event.proto index 67df286c86..70d037c2d7 100644 --- a/proto/buf/alpha/audit/v1alpha1/event.proto +++ b/proto/buf/alpha/audit/v1alpha1/event.proto @@ -57,6 +57,7 @@ enum ResourceType { RESOURCE_TYPE_REPOSITORY_LABEL = 12; RESOURCE_TYPE_SERVER = 13; RESOURCE_TYPE_DEVICE_AUTHORIZATION_GRANT = 14; + RESOURCE_TYPE_PLUGIN_LABEL = 16; } // Resource is the affected resource by the audited event. @@ -115,6 +116,10 @@ enum EventType { EVENT_TYPE_USER_AUTO_MERGED_FROM_NEW_IDP = 37; EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_APPROVED = 41; EVENT_TYPE_DEVICE_AUTHORIZATION_GRANT_DENIED = 42; + EVENT_TYPE_PLUGIN_LABEL_CREATED = 44; + EVENT_TYPE_PLUGIN_LABEL_MOVED = 45; + EVENT_TYPE_PLUGIN_LABEL_ARCHIVED = 46; + EVENT_TYPE_PLUGIN_LABEL_UNARCHIVED = 47; } // EventMetadata provides additional details about the audited event. @@ -188,6 +193,10 @@ message Event { PayloadUserAutoMergedFromNewIdP user_auto_merged_from_new_idp = 43; PayloadDeviceAuthorizationGrantApproved device_authorization_grant_approved = 47; PayloadDeviceAuthorizationGrantDenied device_authorization_grant_denied = 48; + PayloadPluginLabelCreated plugin_label_created = 50; + PayloadPluginLabelMoved plugin_label_moved = 51; + PayloadPluginLabelArchived plugin_label_archived = 52; + PayloadPluginLabelUnarchived plugin_label_unarchived = 53; } } @@ -530,3 +539,53 @@ message PayloadDeviceAuthorizationGrantDenied { // client_id is the id of the registered oauth2 client of the grant. string client_id = 1; } + +message PayloadPluginLabelCreated { + // owner_id is the id of the owner of the plugin on which the label was created. + string owner_id = 1; + // owner_name is the name of the owner of the plugin on which the label was created. + string owner_name = 2; + // plugin_id is the id of the plugin on which the label was created. + string plugin_id = 3; + // plugin_name is the name of the plugin from which the label was created. + string plugin_name = 4; + // commit_id is the id of the commit on which the label was created. + string commit_id = 6; +} + +message PayloadPluginLabelMoved { + // owner_id is the id of the owner of the plugin on which the label was moved. + string owner_id = 1; + // owner_name is the name of the owner of the plugin on which the label was moved. + string owner_name = 2; + // plugin_id is the id of the plugin on which the label was moved. + string plugin_id = 3; + // plugin_name is the name of the plugin from which the label was moved. + string plugin_name = 4; + // to_commit_id is the id of the commit on which the label was moved to. + string to_commit_id = 6; + // from_commit_id is the id of the commit on which the label was moved from. + string from_commit_id = 7; +} + +message PayloadPluginLabelArchived { + // owner_id is the id of the owner of the plugin on which the label was archived. + string owner_id = 1; + // owner_name is the name of the owner of the plugin on which the label was archived. + string owner_name = 2; + // plugin_id is the id of the plugin on which the label was archived. + string plugin_id = 3; + // plugin_name is the name of the plugin from which the label was archived. + string plugin_name = 4; +} + +message PayloadPluginLabelUnarchived { + // owner_id is the id of the owner of the plugin on which the label was unarchived. + string owner_id = 1; + // owner_name is the name of the owner of the plugin on which the label was unarchived. + string owner_name = 2; + // plugin_id is the id of the plugin on which the label was unarchived. + string plugin_id = 3; + // plugin_name is the name of the plugin from which the label was unarchived. + string plugin_name = 4; +} From 1d8835c30e33b511f4eb73bf612e731f0d1ffa67 Mon Sep 17 00:00:00 2001 From: Doria Keung Date: Mon, 25 Nov 2024 17:39:29 -0500 Subject: [PATCH 07/14] Add debug logging interceptor for RPC logs (#3496) Co-authored-by: Edward McFarlane <3036610+emcfarlane@users.noreply.github.com> --- private/buf/bufcli/connectclient_config.go | 1 + private/bufpkg/bufconnect/interceptors.go | 54 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/private/buf/bufcli/connectclient_config.go b/private/buf/bufcli/connectclient_config.go index b7548e6ba3..0bd0083b00 100644 --- a/private/buf/bufcli/connectclient_config.go +++ b/private/buf/bufcli/connectclient_config.go @@ -81,6 +81,7 @@ func newConnectClientConfigWithOptions(container appext.Container, opts ...conne bufconnect.NewAugmentedConnectErrorInterceptor(), bufconnect.NewSetCLIVersionInterceptor(Version), bufconnect.NewCLIWarningInterceptor(container), + bufconnect.NewDebugLoggingInterceptor(container), otelconnectInterceptor, }, ), diff --git a/private/bufpkg/bufconnect/interceptors.go b/private/bufpkg/bufconnect/interceptors.go index eb44224d5b..922004033e 100644 --- a/private/bufpkg/bufconnect/interceptors.go +++ b/private/bufpkg/bufconnect/interceptors.go @@ -18,10 +18,14 @@ import ( "context" "errors" "fmt" + "log/slog" "net/http" + "strings" + "time" "connectrpc.com/connect" "github.com/bufbuild/buf/private/pkg/app/appext" + "google.golang.org/protobuf/proto" ) const ( @@ -140,3 +144,53 @@ func NewAuthorizationInterceptorProvider(tokenProviders ...TokenProvider) func(s return interceptor } } + +// NewDebugLoggingInterceptor returns a new Connect Interceptor that adds debug log +// statements for each rpc call. +// +// The following information is collected for logging: duration, status code, peer name, +// rpc system, request size, and response size. +func NewDebugLoggingInterceptor(container appext.LoggerContainer) connect.UnaryInterceptorFunc { + interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { + return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + var requestSize int + if req.Any() != nil { + msg, ok := req.Any().(proto.Message) + if ok { + requestSize = proto.Size(msg) + } + } + startTime := time.Now() + resp, err := next(ctx, req) + duration := time.Since(startTime) + var status connect.Code + if err != nil { + status = connect.CodeOf(err) + } + var responseSize int + if resp != nil && resp.Any() != nil { + msg, ok := resp.Any().(proto.Message) + if ok { + responseSize = proto.Size(msg) + } + } + attrs := []slog.Attr{ + slog.Duration("duration", duration), + slog.String("status", status.String()), + slog.String("net.peer.name", req.Peer().Addr), + slog.String("rpc.system", req.Peer().Protocol), + slog.Int("message.sent.uncompressed_size", requestSize), + slog.Int("message.received.uncompressed_size", responseSize), + } + container.Logger().LogAttrs( + ctx, + slog.LevelDebug, + // Remove the leading "/" from Procedure name + strings.TrimPrefix(req.Spec().Procedure, "/"), + attrs..., + ) + return resp, err + } + } + return interceptor +} From 9e94044a34ec7df665ef8d2ff2bcc86b064d2111 Mon Sep 17 00:00:00 2001 From: Miguel Young Date: Tue, 26 Nov 2024 17:55:47 -0500 Subject: [PATCH 08/14] Implement breaking lints in the LSP (#3404) --- .golangci.yml | 5 + CHANGELOG.md | 1 + private/buf/buflsp/buflsp.go | 43 +++- private/buf/buflsp/config.go | 63 ++++++ private/buf/buflsp/file.go | 368 +++++++++++++++++++------------ private/buf/buflsp/image.go | 141 ++++++++++++ private/buf/buflsp/server.go | 53 ++++- private/pkg/git/git.go | 94 ++++++++ private/pkg/refcount/refcount.go | 14 ++ 9 files changed, 630 insertions(+), 152 deletions(-) create mode 100644 private/buf/buflsp/config.go create mode 100644 private/buf/buflsp/image.go diff --git a/.golangci.yml b/.golangci.yml index a53b93cc05..ba5a81b1c1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -115,6 +115,11 @@ issues: # G115 checks for use of truncating conversions. path: private/buf/buflsp/file.go text: "G115:" + - linters: + - gosec + # G115 checks for use of truncating conversions. + path: private/buf/buflsp/image.go + text: "G115:" - linters: - gosec # G115 checks for use of truncating conversions. diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c593ef31f..fcd8101d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] - Add `buf registry plugin {create,delete,info,update}` commands to manage BSR plugins. +- Breaking analysis support for `buf beta lsp`. ## [v1.47.2] - 2024-11-14 diff --git a/private/buf/buflsp/buflsp.go b/private/buf/buflsp/buflsp.go index 9d04d840e3..536cf71d43 100644 --- a/private/buf/buflsp/buflsp.go +++ b/private/buf/buflsp/buflsp.go @@ -65,6 +65,7 @@ func Serve( &connWrapper{Conn: conn, logger: container.Logger()}, zap.NewNop(), // The logging from protocol itself isn't very good, we've replaced it with connAdapter here. ), + container: container, logger: container.Logger(), controller: controller, checkClient: checkClient, @@ -89,8 +90,9 @@ func Serve( // Its handler methods are not defined in buflsp.go; they are defined in other files, grouped // according to the groupings in type lsp struct { - conn jsonrpc2.Conn - client protocol.Client + conn jsonrpc2.Conn + client protocol.Client + container appext.Container logger *slog.Logger controller bufctl.Controller @@ -130,19 +132,38 @@ func (l *lsp) init(_ context.Context, params *protocol.InitializeParams) error { // to inject debug logging, tracing, and timeouts to requests. func (l *lsp) newHandler() jsonrpc2.Handler { actual := protocol.ServerHandler(newServer(l), nil) - return func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) (retErr error) { - defer slogext.DebugProfile(l.logger, slog.String("method", req.Method()), slog.Any("params", req.Params()))() + return jsonrpc2.AsyncHandler(func(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { + l.logger.Debug( + "handling request", + slog.String("method", req.Method()), + slog.Any("params", req.Params()), + ) + defer slogext.DebugProfile( + l.logger, + slog.String("method", req.Method()), + slog.Any("params", req.Params()), + )() replier := l.wrapReplier(reply, req) - // Verify that the server has been initialized if this isn't the initialization - // request. + var err error if req.Method() != protocol.MethodInitialize && l.initParams.Load() == nil { - return replier(ctx, nil, fmt.Errorf("the first call to the server must be the %q method", protocol.MethodInitialize)) + // Verify that the server has been initialized if this isn't the initialization + // request. + err = replier(ctx, nil, fmt.Errorf("the first call to the server must be the %q method", protocol.MethodInitialize)) + } else { + l.lock.Lock() + err = actual(ctx, replier, req) + l.lock.Unlock() } - l.lock.Lock() - defer l.lock.Unlock() - return actual(ctx, replier, req) - } + if err != nil { + l.logger.Error( + "error while replying to request", + slog.String("method", req.Method()), + slogext.ErrorAttr(err), + ) + } + return nil + }) } diff --git a/private/buf/buflsp/config.go b/private/buf/buflsp/config.go new file mode 100644 index 0000000000..53618ffb22 --- /dev/null +++ b/private/buf/buflsp/config.go @@ -0,0 +1,63 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package buflsp + +// Configuration keys for the LSP. +// +// These are part of the public API of the LSP server, in that any user of +// the LSP can configure it using these keys. The server requests them over +// the LSP protocol as-needed. +// +// Keep in sync with bufbuild/vscode-buf package.json. +const ( + // The strategy for how to calculate the --against input for a breaking + // check. This must be one of the following values: + // + // - "git". Use a particular Git revision to find the against file. + // + // - "disk". Use the last-saved value on disk as the against file. + ConfigBreakingStrategy = "buf.checks.breaking.againstStrategy" + // The Git revision to use for calculating the --against input for a + // breaking check when using the "git" strategy. + ConfigBreakingGitRef = "buf.checks.breaking.againstGitRef" +) + +const ( + // Compare against the configured git branch. + againstGit againstStrategy = iota + 1 + // Against the last saved file on disk (i.e. saved vs unsaved changes). + againstDisk +) + +// againstStrategy is a strategy for selecting which version of a file to use as +// --against for the purposes of breaking lints. +type againstStrategy int + +// parseAgainstStrategy parses an againstKind from a config setting sent by +// the client. +// +// Returns againstTrunk, false if the value is not recognized. +func parseAgainstStrategy(s string) (againstStrategy, bool) { + switch s { + // These values are the same as those present in the package.json for the + // VSCode client. + case "git": + return againstGit, true + case "disk": + return againstDisk, true + default: + return againstGit, false + } +} diff --git a/private/buf/buflsp/file.go b/private/buf/buflsp/file.go index bbd8d9188a..8bad05ec37 100644 --- a/private/buf/buflsp/file.go +++ b/private/buf/buflsp/file.go @@ -17,6 +17,7 @@ package buflsp import ( + "bytes" "context" "errors" "fmt" @@ -31,18 +32,15 @@ import ( "github.com/bufbuild/buf/private/bufpkg/bufcheck" "github.com/bufbuild/buf/private/bufpkg/bufimage" "github.com/bufbuild/buf/private/bufpkg/bufmodule" + "github.com/bufbuild/buf/private/pkg/git" "github.com/bufbuild/buf/private/pkg/ioext" + "github.com/bufbuild/buf/private/pkg/normalpath" "github.com/bufbuild/buf/private/pkg/slogext" "github.com/bufbuild/buf/private/pkg/storage" - "github.com/bufbuild/protocompile" "github.com/bufbuild/protocompile/ast" - "github.com/bufbuild/protocompile/linker" "github.com/bufbuild/protocompile/parser" - "github.com/bufbuild/protocompile/protoutil" "github.com/bufbuild/protocompile/reporter" - "github.com/google/uuid" "go.lsp.dev/protocol" - "google.golang.org/protobuf/reflect/protoreflect" ) const descriptorPath = "google/protobuf/descriptor.proto" @@ -60,20 +58,22 @@ type file struct { // diagnostics or symbols an operating refers to. version int32 hasText bool // Whether this file has ever had text read into it. - // Always set false->true. Once true, never becomes false again. workspace bufworkspace.Workspace module bufmodule.Module + againstStrategy againstStrategy + againstGitRef string + objectInfo storage.ObjectInfo importablePathToObject map[string]storage.ObjectInfo - fileNode *ast.FileNode - packageNode *ast.PackageNode - diagnostics []protocol.Diagnostic - importToFile map[string]*file - symbols []*symbol - image bufimage.Image + fileNode *ast.FileNode + packageNode *ast.PackageNode + diagnostics []protocol.Diagnostic + importToFile map[string]*file + symbols []*symbol + image, againstImage bufimage.Image } // IsWKT returns whether this file corresponds to a well-known type. @@ -170,6 +170,99 @@ func (f *file) Update(ctx context.Context, version int32, text string) { f.hasText = true } +// FetchSettings refreshes configuration settings for this file. +// +// This only needs to happen when the file is open or when the client signals +// that configuration settings have changed. +func (f *file) RefreshSettings(ctx context.Context) { + settings, err := f.lsp.client.Configuration(ctx, &protocol.ConfigurationParams{ + Items: []protocol.ConfigurationItem{ + {ScopeURI: f.uri, Section: ConfigBreakingStrategy}, + {ScopeURI: f.uri, Section: ConfigBreakingGitRef}, + }, + }) + if err != nil { + // We can throw the error away, since the handler logs it for us. + return + } + + // NOTE: indices here are those from the array in the call to Configuration above. + f.againstStrategy = getSetting(f, settings, ConfigBreakingStrategy, 0, parseAgainstStrategy) + f.againstGitRef = getSetting(f, settings, ConfigBreakingGitRef, 1, func(s string) (string, bool) { return s, true }) + + switch f.againstStrategy { + case againstDisk: + f.againstGitRef = "" + case againstGit: + // Check to see if the user setting is a valid Git ref. + err := git.IsValidRef( + ctx, + f.lsp.container, + normalpath.Dir(f.uri.Filename()), + f.againstGitRef, + ) + if err != nil { + f.lsp.logger.Warn( + "failed to validate buf.againstGit", + slog.String("uri", string(f.uri)), + slogext.ErrorAttr(err), + ) + f.againstGitRef = "" + } else { + f.lsp.logger.Debug( + "found remote branch", + slog.String("uri", string(f.uri)), + slog.String("ref", f.againstGitRef), + ) + } + } +} + +// getSetting is a helper that extracts a configuration setting from the return +// value of [protocol.Client.Configuration]. +// +// The parse function should convert the JSON value we get from the protocol +// (such as a string), potentially performing validation, and returning a default +// value on validation failure. +func getSetting[T, U any](f *file, settings []any, name string, index int, parse func(T) (U, bool)) (value U) { + if len(settings) <= index { + f.lsp.logger.Warn( + "missing config setting", + slog.String("setting", name), + slog.String("uri", string(f.uri)), + ) + } + + if raw, ok := settings[index].(T); ok { + // For invalid settings, this will default to againstTrunk for us! + value, ok = parse(raw) + if !ok { + f.lsp.logger.Warn( + "invalid config setting", + slog.String("setting", name), + slog.String("uri", string(f.uri)), + slog.Any("raw", raw), + ) + } + } else { + f.lsp.logger.Warn( + "invalid config setting", + slog.String("setting", name), + slog.String("uri", string(f.uri)), + slog.Any("raw", raw), + ) + } + + f.lsp.logger.Debug( + "parsed config setting", + slog.String("setting", name), + slog.String("uri", string(f.uri)), + slog.Any("value", value), + ) + + return value +} + // Refresh rebuilds all of a file's internal book-keeping. // // If deep is set, this will also load imports and refresh those, too. @@ -188,12 +281,13 @@ func (f *file) Refresh(ctx context.Context) { progress.Report(ctx, "Indexing Imports", 2.0/6) f.IndexImports(ctx) - progress.Report(ctx, "Detecting Module", 3.0/6) + progress.Report(ctx, "Detecting Buf Module", 3.0/6) f.FindModule(ctx) - progress.Report(ctx, "Linking Descriptors", 4.0/6) - f.BuildImage(ctx) + progress.Report(ctx, "Running Checks", 4.0/6) + f.BuildImages(ctx) f.RunLints(ctx) + f.RunBreaking(ctx) progress.Report(ctx, "Indexing Symbols", 5.0/6) f.IndexSymbols(ctx) @@ -210,10 +304,6 @@ func (f *file) Refresh(ctx context.Context) { // // Returns whether a reparse was necessary. func (f *file) RefreshAST(ctx context.Context) bool { - if f.fileNode != nil { - return false - } - // NOTE: We intentionally do not use var report report here, because we need // report to be non-nil when empty; this is because if it is nil, when calling // PublishDiagnostics() below it will be serialized as JSON null. @@ -429,132 +519,113 @@ func (f *file) IndexImports(ctx context.Context) { // Parse the imported file and find all symbols in it, but do not // index symbols in the import's imports, otherwise we will recursively // index the universe and that would be quite slow. - file.RefreshAST(ctx) + + if f.fileNode != nil { + file.RefreshAST(ctx) + } file.IndexSymbols(ctx) } } -// BuildImage builds a Buf Image for this file. This does not use the controller to build -// the image, because we need delicate control over the input files: namely, for the case -// when we depend on a file that has been opened and modified in the editor. +// newFileOpener returns a fileOpener for the context of this file. // -// This operation requires IndexImports(). -func (f *file) BuildImage(ctx context.Context) { - importable := f.importablePathToObject - fileInfo := f.objectInfo - - if importable == nil || fileInfo == nil { - return - } - - var report report - var symbols linker.Symbols - compiler := protocompile.Compiler{ - SourceInfoMode: protocompile.SourceInfoExtraOptionLocations, - Resolver: &protocompile.SourceResolver{ - Accessor: func(path string) (io.ReadCloser, error) { - var uri protocol.URI - fileInfo, ok := importable[path] - if ok { - uri = protocol.URI("file://" + fileInfo.LocalPath()) - } else { - uri = protocol.URI("file://" + path) - } - - if file := f.Manager().Get(uri); file != nil { - return ioext.CompositeReadCloser(strings.NewReader(file.text), ioext.NopCloser), nil - } else if !ok { - return nil, os.ErrNotExist - } - - return os.Open(fileInfo.LocalPath()) - }, - }, - Symbols: &symbols, - Reporter: &report, - } - - compiled, err := compiler.Compile(ctx, fileInfo.Path()) - if err != nil { - f.diagnostics = report.diagnostics - } - if compiled[0] == nil { - return +// May return nil, if insufficient information is present to open the file. +func (f *file) newFileOpener() fileOpener { + if f.importablePathToObject == nil { + return nil } - var imageFiles []bufimage.ImageFile - seen := map[string]bool{} - - queue := []protoreflect.FileDescriptor{compiled[0]} - for len(queue) > 0 { - descriptor := queue[len(queue)-1] - queue = queue[:len(queue)-1] - - if seen[descriptor.Path()] { - continue + return func(path string) (io.ReadCloser, error) { + var uri protocol.URI + fileInfo, ok := f.importablePathToObject[path] + if ok { + uri = protocol.URI("file://" + fileInfo.LocalPath()) + } else { + uri = protocol.URI("file://" + path) } - seen[descriptor.Path()] = true - unused, ok := report.pathToUnusedImports[descriptor.Path()] - var unusedIndices []int32 - if ok { - unusedIndices = make([]int32, 0, len(unused)) + if file := f.Manager().Get(uri); file != nil { + return ioext.CompositeReadCloser(strings.NewReader(file.text), ioext.NopCloser), nil + } else if !ok { + return nil, os.ErrNotExist } - imports := descriptor.Imports() - for i := 0; i < imports.Len(); i++ { - dep := imports.Get(i).FileDescriptor - if dep == nil { - f.lsp.logger.Warn(fmt.Sprintf("found nil FileDescriptor for import %s", imports.Get(i).Path())) - continue - } + return os.Open(fileInfo.LocalPath()) + } +} - queue = append(queue, dep) +// newAgainstFileOpener returns a fileOpener for building the --against file +// for this file. In other words, this pulls files out of the git index, if +// necessary. +// +// May return nil, if there is insufficient information to build an --against +// file. +func (f *file) newAgainstFileOpener(ctx context.Context) fileOpener { + if !f.IsLocal() || f.importablePathToObject == nil { + return nil + } - if unused != nil { - if _, ok := unused[dep.Path()]; ok { - unusedIndices = append(unusedIndices, int32(i)) - } - } - } + if f.againstStrategy == againstGit && f.againstGitRef == "" { + return nil + } - descriptorProto := protoutil.ProtoFromFileDescriptor(descriptor) - if descriptorProto == nil { - err = fmt.Errorf("protoutil.ProtoFromFileDescriptor() returned nil for %q", descriptor.Path()) - break + return func(path string) (io.ReadCloser, error) { + fileInfo, ok := f.importablePathToObject[path] + if !ok { + return nil, fmt.Errorf("failed to resolve import: %s", path) } - var imageFile bufimage.ImageFile - imageFile, err = bufimage.NewImageFile( - descriptorProto, - nil, - uuid.UUID{}, - "", - descriptor.Path(), - descriptor.Path() != fileInfo.Path(), - report.syntaxMissing[descriptor.Path()], - unusedIndices, + var ( + data []byte + err error ) - if err != nil { - break + if f.againstGitRef != "" { + data, err = git.ReadFileAtRef( + ctx, + f.lsp.container, + fileInfo.LocalPath(), + f.againstGitRef, + ) + } + + if data == nil || errors.Is(err, git.ErrInvalidGitCheckout) { + return os.Open(fileInfo.LocalPath()) } - imageFiles = append(imageFiles, imageFile) - f.lsp.logger.Debug(fmt.Sprintf("added image file for %s", descriptor.Path())) + return ioext.CompositeReadCloser(bytes.NewReader(data), ioext.NopCloser), err } +} - if err != nil { - f.lsp.logger.Warn("could not build image", slog.String("uri", string(f.uri)), slogext.ErrorAttr(err)) +// BuildImages builds Buf Images for this file, to be used with linting +// routines. +// +// This operation requires IndexImports(). +func (f *file) BuildImages(ctx context.Context) { + if f.objectInfo == nil { return } - image, err := bufimage.NewImage(imageFiles) - if err != nil { - f.lsp.logger.Warn("could not build image", slog.String("uri", string(f.uri)), slogext.ErrorAttr(err)) - return + if opener := f.newFileOpener(); opener != nil { + image, diagnostics := buildImage(ctx, f.objectInfo.Path(), f.lsp.logger, opener) + if len(diagnostics) > 0 { + f.diagnostics = diagnostics + } + f.image = image + } else { + f.lsp.logger.Warn("not building image", slog.String("uri", string(f.uri))) } - f.image = image + if opener := f.newAgainstFileOpener(ctx); opener != nil { + // We explicitly throw the diagnostics away. + image, diagnostics := buildImage(ctx, f.objectInfo.Path(), f.lsp.logger, opener) + + f.againstImage = image + if image == nil { + f.lsp.logger.Warn("failed to build --against image", slog.Any("diagnostics", diagnostics)) + } + } else { + f.lsp.logger.Warn("not building --against image", slog.String("uri", string(f.uri))) + } } // RunLints runs linting on this file. Returns whether any lints failed. @@ -566,41 +637,61 @@ func (f *file) RunLints(ctx context.Context) bool { return false } - workspace := f.workspace - module := f.module - image := f.image - - if module == nil || image == nil { + if f.module == nil || f.image == nil { f.lsp.logger.Warn(fmt.Sprintf("could not find image for %q", f.uri)) return false } - f.lsp.logger.Debug(fmt.Sprintf("running lint for %q in %v", f.uri, module.FullName())) + f.lsp.logger.Debug(fmt.Sprintf("running lint for %q in %v", f.uri, f.module.FullName())) + return f.appendLintErrors("buf lint", f.lsp.checkClient.Lint( + ctx, + f.workspace.GetLintConfigForOpaqueID(f.module.OpaqueID()), + f.image, + bufcheck.WithPluginConfigs(f.workspace.PluginConfigs()...), + )) +} - lintConfig := workspace.GetLintConfigForOpaqueID(module.OpaqueID()) - err := f.lsp.checkClient.Lint( +// RunBreaking runs breaking lints on this file. Returns whether any lints failed. +// +// This operation requires BuildImage(). +func (f *file) RunBreaking(ctx context.Context) bool { + if f.IsWKT() { + // Well-known types are not linted. + return false + } + + if f.module == nil || f.image == nil || f.againstImage == nil { + f.lsp.logger.Warn(fmt.Sprintf("could not find --against image for %q", f.uri)) + return false + } + + f.lsp.logger.Debug(fmt.Sprintf("running breaking for %q in %v", f.uri, f.module.FullName())) + return f.appendLintErrors("buf breaking", f.lsp.checkClient.Breaking( ctx, - lintConfig, - image, - bufcheck.WithPluginConfigs(workspace.PluginConfigs()...), - ) + f.workspace.GetBreakingConfigForOpaqueID(f.module.OpaqueID()), + f.image, + f.againstImage, + bufcheck.WithPluginConfigs(f.workspace.PluginConfigs()...), + )) +} +func (f *file) appendLintErrors(source string, err error) bool { if err == nil { - f.lsp.logger.Warn(fmt.Sprintf("lint generated no errors for %s", f.uri)) + f.lsp.logger.Debug(fmt.Sprintf("%s generated no errors for %s", source, f.uri)) return false } var annotations bufanalysis.FileAnnotationSet if !errors.As(err, &annotations) { - f.lsp.logger.Warn("error while linting", slog.String("uri", string(f.uri)), slogext.ErrorAttr(err)) + f.lsp.logger.Warn( + "error while linting", + slog.String("uri", string(f.uri)), + slogext.ErrorAttr(err), + ) return false } - f.lsp.logger.Warn(fmt.Sprintf("lint generated %d error(s) for %s", len(annotations.FileAnnotations()), f.uri)) - for _, annotation := range annotations.FileAnnotations() { - f.lsp.logger.Info(annotation.FileInfo().Path(), " ", annotation.FileInfo().ExternalPath()) - f.diagnostics = append(f.diagnostics, protocol.Diagnostic{ Range: protocol.Range{ Start: protocol.Position{ @@ -614,10 +705,11 @@ func (f *file) RunLints(ctx context.Context) bool { }, Code: annotation.Type(), Severity: protocol.DiagnosticSeverityError, - Source: serverName, + Source: source, Message: annotation.Message(), }) } + return true } diff --git a/private/buf/buflsp/image.go b/private/buf/buflsp/image.go new file mode 100644 index 0000000000..0e4bc7df5b --- /dev/null +++ b/private/buf/buflsp/image.go @@ -0,0 +1,141 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package buflsp + +import ( + "context" + "fmt" + "io" + "log/slog" + + "github.com/bufbuild/buf/private/bufpkg/bufimage" + "github.com/bufbuild/buf/private/pkg/slogext" + "github.com/bufbuild/protocompile" + "github.com/bufbuild/protocompile/linker" + "github.com/bufbuild/protocompile/protoutil" + "github.com/google/uuid" + "go.lsp.dev/protocol" + "google.golang.org/protobuf/reflect/protoreflect" +) + +// fileOpener is a function that opens files as they are named in the import +// statements of .proto files. +// +// This is the context given to [buildImage] to control what text to look up for +// specific files, so that we can e.g. use file contents that are still unsaved +// in the editor, or use files from a different commit for building an --against +// image. +type fileOpener func(string) (io.ReadCloser, error) + +// buildImage builds a Buf Image for the given path. This does not use the controller to build +// the image, because we need delicate control over the input files: namely, for the case +// when we depend on a file that has been opened and modified in the editor. +func buildImage( + ctx context.Context, + path string, + logger *slog.Logger, + opener fileOpener, +) (bufimage.Image, []protocol.Diagnostic) { + var report report + var symbols linker.Symbols + compiler := protocompile.Compiler{ + SourceInfoMode: protocompile.SourceInfoExtraOptionLocations, + Resolver: &protocompile.SourceResolver{Accessor: opener}, + Symbols: &symbols, + Reporter: &report, + } + + compiled, err := compiler.Compile(ctx, path) + if err != nil { + logger.Warn("error building image", slog.String("path", path), slogext.ErrorAttr(err)) + } + if compiled[0] == nil { + return nil, report.diagnostics + } + + var imageFiles []bufimage.ImageFile + seen := map[string]bool{} + + queue := []protoreflect.FileDescriptor{compiled[0]} + for len(queue) > 0 { + descriptor := queue[len(queue)-1] + queue = queue[:len(queue)-1] + + if seen[descriptor.Path()] { + continue + } + seen[descriptor.Path()] = true + + unused, ok := report.pathToUnusedImports[descriptor.Path()] + var unusedIndices []int32 + if ok { + unusedIndices = make([]int32, 0, len(unused)) + } + + imports := descriptor.Imports() + for i := 0; i < imports.Len(); i++ { + dep := imports.Get(i).FileDescriptor + if dep == nil { + logger.Warn(fmt.Sprintf("found nil FileDescriptor for import %s", imports.Get(i).Path())) + continue + } + + queue = append(queue, dep) + + if unused != nil { + if _, ok := unused[dep.Path()]; ok { + unusedIndices = append(unusedIndices, int32(i)) + } + } + } + + descriptorProto := protoutil.ProtoFromFileDescriptor(descriptor) + if descriptorProto == nil { + err = fmt.Errorf("protoutil.ProtoFromFileDescriptor() returned nil for %q", descriptor.Path()) + break + } + + var imageFile bufimage.ImageFile + imageFile, err = bufimage.NewImageFile( + descriptorProto, + nil, + uuid.UUID{}, + "", + descriptor.Path(), + descriptor.Path() != path, + report.syntaxMissing[descriptor.Path()], + unusedIndices, + ) + if err != nil { + break + } + + imageFiles = append(imageFiles, imageFile) + logger.Debug(fmt.Sprintf("added image file for %s", descriptor.Path())) + } + + if err != nil { + logger.Warn("could not build image", slog.String("path", path), slogext.ErrorAttr(err)) + return nil, report.diagnostics + } + + image, err := bufimage.NewImage(imageFiles) + if err != nil { + logger.Warn("could not build image", slog.String("path", path), slogext.ErrorAttr(err)) + return nil, report.diagnostics + } + + return image, report.diagnostics +} diff --git a/private/buf/buflsp/server.go b/private/buf/buflsp/server.go index c52d2f85ad..e6f79f1512 100644 --- a/private/buf/buflsp/server.go +++ b/private/buf/buflsp/server.go @@ -114,6 +114,9 @@ func (s *server) Initialize( // usually get especially huge, so this simplifies our logic without // necessarily making the LSP slow. Change: protocol.TextDocumentSyncKindFull, + Save: &protocol.SaveOptions{ + IncludeText: false, + }, }, DefinitionProvider: &protocol.DefinitionOptions{ WorkDoneProgressOptions: protocol.WorkDoneProgressOptions{WorkDoneProgress: true}, @@ -139,6 +142,15 @@ func (s *server) Initialized( ctx context.Context, params *protocol.InitializedParams, ) error { + if s.initParams.Load().Capabilities.Workspace.DidChangeConfiguration.DynamicRegistration { + // The error is logged for us by the client wrapper. + _ = s.client.RegisterCapability(ctx, &protocol.RegistrationParams{ + Registrations: []protocol.Registration{ + {Method: protocol.MethodWorkspaceDidChangeConfiguration}, + }, + }) + } + return nil } @@ -166,6 +178,24 @@ func (s *server) Exit(ctx context.Context) error { return s.lsp.conn.Close() } +// DidChangeConfiguration is sent whenever the client changes its config settings. +func (s *server) DidChangeConfiguration( + ctx context.Context, + params *protocol.DidChangeConfigurationParams, +) error { + // We need to refresh every open file's settings, and refresh the file + // itself. + s.fileManager.uriToFile.Range(func(_ protocol.URI, file *file) bool { + if file.IsOpenInEditor() { + file.RefreshSettings(ctx) + file.Refresh(ctx) + } + return true + }) + + return nil +} + // -- File synchronization methods. // DidOpen is called whenever the client opens a document. This is our signal to parse @@ -175,8 +205,9 @@ func (s *server) DidOpen( params *protocol.DidOpenTextDocumentParams, ) error { file := s.fileManager.Open(ctx, params.TextDocument.URI) + file.RefreshSettings(ctx) file.Update(ctx, params.TextDocument.Version, params.TextDocument.Text) - file.Refresh(context.WithoutCancel(ctx)) + file.Refresh(ctx) return nil } @@ -193,7 +224,23 @@ func (s *server) DidChange( } file.Update(ctx, params.TextDocument.Version, params.ContentChanges[0].Text) - file.Refresh(context.WithoutCancel(ctx)) + file.Refresh(ctx) + return nil +} + +// DidSave is called whenever the client saves a document. +func (s *server) DidSave( + ctx context.Context, + params *protocol.DidSaveTextDocumentParams, +) error { + // We use this as an opportunity to do a refresh; some lints, such as + // breaking-against-last-saved, rely on this. + file := s.fileManager.Get(params.TextDocument.URI) + if file == nil { + // Update for a file we don't know about? Seems bad! + return fmt.Errorf("received update for file that was not open: %q", params.TextDocument.URI) + } + file.Refresh(ctx) return nil } @@ -217,7 +264,7 @@ func (s *server) Formatting( } } if errorCount > 0 { - return nil, fmt.Errorf("cannot format file %q, %v error(s) found.", file.uri.Filename(), errorCount) + return nil, fmt.Errorf("cannot format file %q, %v error(s) found", file.uri.Filename(), errorCount) } // Currently we have no way to honor any of the parameters. diff --git a/private/pkg/git/git.go b/private/pkg/git/git.go index 339fad2bd4..ea2b4faa09 100644 --- a/private/pkg/git/git.go +++ b/private/pkg/git/git.go @@ -21,7 +21,9 @@ import ( "errors" "fmt" "log/slog" + "os" "os/exec" + "path/filepath" "regexp" "strings" @@ -46,6 +48,11 @@ var ( // ErrInvalidGitCheckout is returned from CheckDirectoryIsValidGitCheckout when the // specified directory is not a valid git checkout. ErrInvalidGitCheckout = errors.New("invalid git checkout") + + // ErrInvalidRef is returned from IsValidRef if the ref does not exist in the + // repository containing the given directory (or, if the directory is not + // a valid git checkout). + ErrInvalidRef = errors.New("invalid git ref") ) // Name is a name identifiable by git. @@ -346,6 +353,93 @@ func GetRefsForGitCommitAndRemote( return refs, nil } +// IsValidRef returns whether or not ref is a valid git ref for the git +// repository that contains dir. Returns nil if the ref is valid. +func IsValidRef( + ctx context.Context, + envContainer app.EnvContainer, + dir, ref string, +) error { + stdout := bytes.NewBuffer(nil) + stderr := bytes.NewBuffer(nil) + if err := execext.Run( + ctx, + gitCommand, + execext.WithArgs("rev-parse", "--verify", ref), + execext.WithStdout(stdout), + execext.WithStderr(stderr), + execext.WithDir(dir), + execext.WithEnv(app.Environ(envContainer)), + ); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + if exitErr.ExitCode() == 128 { + return fmt.Errorf("could not find ref %s in %s: %w", ref, dir, ErrInvalidRef) + } + } + return err + } + return nil +} + +// ReadFileAtRef will read the file at path rolled back to the given ref, if +// it exists at that ref. +// +// Specifically, this will take path, and find the associated .git directory +// (and thus, repository root) associated with that path, if any. It will then +// look up the commit corresponding to ref in that git directory, and within +// that commit, the blob corresponding to that path (relative to the repository +// root). +func ReadFileAtRef( + ctx context.Context, + envContainer app.EnvContainer, + path, ref string, +) ([]byte, error) { + orig := path + path, err := filepath.Abs(path) + if err != nil { + return nil, err + } + + // Find a directory with a .git directory. + dir := filepath.Dir(path) + for { + _, err := os.Stat(filepath.Join(dir, ".git")) + if err == nil { + break + } else if errors.Is(err, os.ErrNotExist) { + parent := filepath.Dir(dir) + if parent == dir { + return nil, fmt.Errorf("could not find .git directory for %s: %w", orig, ErrInvalidGitCheckout) + } + dir = parent + } else { + return nil, err + } + } + + // This gives us the name of the blob we're looking for. + rel, err := filepath.Rel(dir, path) + if err != nil { + return nil, err + } + + // Call git show to show us the file we want. + stdout := bytes.NewBuffer(nil) + stderr := bytes.NewBuffer(nil) + if err := execext.Run(ctx, gitCommand, + execext.WithArgs("--no-pager", "show", ref+":"+rel), + execext.WithStdout(stdout), + execext.WithStderr(stderr), + execext.WithDir(dir), + execext.WithEnv(app.Environ(envContainer)), + ); err != nil { + return nil, fmt.Errorf("failed to get text of file %s at ref %s: %w: %s", orig, ref, err, stderr.String()) + } + + return stdout.Bytes(), nil +} + func getAllTrimmedLinesFromBuffer(buffer *bytes.Buffer) []string { scanner := bufio.NewScanner(buffer) var lines []string diff --git a/private/pkg/refcount/refcount.go b/private/pkg/refcount/refcount.go index cdbdf3b63b..efed9b1971 100644 --- a/private/pkg/refcount/refcount.go +++ b/private/pkg/refcount/refcount.go @@ -83,6 +83,20 @@ func (m *Map[K, V]) Get(key K) *V { return &value.value } +// Range ranges over this map. Beware! While ranging, writes to the map will block. +// +// This implements [iter.Seq2] for Map[K, V]. +func (m *Map[K, V]) Range(yield func(k K, v *V) bool) { + m.lock.RLock() + defer m.lock.RUnlock() + + for k, v := range m.table { + if !yield(k, &v.value) { + break + } + } +} + // Delete deletes a key from the map. // // The key will only be evicted once [Map.Delete] has been called an equal number of times From bbefdb843ea0ad68f1ab72003dbf40683cf304c1 Mon Sep 17 00:00:00 2001 From: Edward McFarlane <3036610+emcfarlane@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:41:43 -0500 Subject: [PATCH 09/14] Update registry proto (#3497) --- go.mod | 4 ++-- go.sum | 8 ++++---- .../bufregistryapiplugin.go | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index aab2d4b101..7343665627 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ toolchain go1.23.3 require ( buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.35.2-20241031151143-70f632351282.1 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 - buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241025140216-aa40f2c93090.1 - buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241025140216-aa40f2c93090.1 + buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241125212318-4a305dc3b757.1 + buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241125212318-4a305dc3b757.1 buf.build/go/bufplugin v0.6.0 buf.build/go/protoyaml v0.2.0 buf.build/go/spdx v0.2.0 diff --git a/go.sum b/go.sum index cf3c84d1b8..2cdf4394c4 100644 --- a/go.sum +++ b/go.sum @@ -2,10 +2,10 @@ buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.35.2-20241031151143-70 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.35.2-20241031151143-70f632351282.1/go.mod h1:vKDy7lD1bsN2UjeLhqklPEjIsHfHAPgMb/PbRx2EFDc= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 h1:7QIeAuTdLp173vC/9JojRMDFcpmqtoYrxPmvdHAOynw= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI= -buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241025140216-aa40f2c93090.1 h1:FHQXg3T7S2jp8yc7/bQJgqEH1yza/rrDHXITUK2Tm0g= -buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241025140216-aa40f2c93090.1/go.mod h1:5iwF5l+9lKCnvr1zLvDgUHrv6X+vU5nNPjvig1sbnao= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241025140216-aa40f2c93090.1 h1:a1OY15kRBrD1AF0SYIPYFLE8GCC1d85zqENnzUC3lNM= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241025140216-aa40f2c93090.1/go.mod h1:EQCcR04Wp6ffVPfxNb4ZXAVJXrZJopDNKQWp37BDCgU= +buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241125212318-4a305dc3b757.1 h1:q3PKZJfOuSZR8KC0asyo7EFID/3613pDFzFYAAO+Gd4= +buf.build/gen/go/bufbuild/registry/connectrpc/go v1.17.0-20241125212318-4a305dc3b757.1/go.mod h1:w+XYJEgdkHK5XJ+44Eq2YD02DZVLFNFjfwFKPz0nZcg= +buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241125212318-4a305dc3b757.1 h1:m2QVURqXvfedovCeWV5CsWm3VIrD87RHL+9P9o7HB84= +buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.35.2-20241125212318-4a305dc3b757.1/go.mod h1:EQCcR04Wp6ffVPfxNb4ZXAVJXrZJopDNKQWp37BDCgU= buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.2-20241007202033-cf42259fcbfc.1 h1:FcoYwX9eJhc73MdVlqyJjMOQ863akpHK0VEQ/+Zkt9U= buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.35.2-20241007202033-cf42259fcbfc.1/go.mod h1:uTCf/J5B6H9XCTgHuI91LC9qaNqxJxQFh0kDY/GLn2k= buf.build/go/bufplugin v0.6.0 h1:3lhoh+0z+IUPS3ZajTPn/27LaLIkero2BDVnV7yXD1s= diff --git a/private/bufpkg/bufregistryapi/bufregistryapiplugin/bufregistryapiplugin.go b/private/bufpkg/bufregistryapi/bufregistryapiplugin/bufregistryapiplugin.go index 1cba7fb1f2..d9dc3314ee 100644 --- a/private/bufpkg/bufregistryapi/bufregistryapiplugin/bufregistryapiplugin.go +++ b/private/bufpkg/bufregistryapi/bufregistryapiplugin/bufregistryapiplugin.go @@ -30,6 +30,8 @@ var ( NopV1Beta1LabelServiceClientProvider V1Beta1LabelServiceClientProvider = nopClientProvider{} // NopV1Beta1PluginServiceClientProvider is a V1Beta1PluginServiceClientProvider that provides unimplemented services for testing. NopV1Beta1PluginServiceClientProvider V1Beta1PluginServiceClientProvider = nopClientProvider{} + // NopV1Beta1ResourceServiceClientProvider is a V1Beta1ResourceServiceClientProvider that provides unimplemented services for testing. + NopV1Beta1ResourceServiceClientProvider V1Beta1ResourceServiceClientProvider = nopClientProvider{} // NopV1Beta1UploadServiceClientProvider is a V1Beta1UploadServiceClientProvider that provides unimplemented services for testing. NopV1Beta1UploadServiceClientProvider V1Beta1UploadServiceClientProvider = nopClientProvider{} // NopClientProvider is a ClientProvider that provides unimplemented services for testing. @@ -56,6 +58,11 @@ type V1Beta1LabelServiceClientProvider interface { V1Beta1LabelServiceClient(registry string) pluginv1beta1connect.LabelServiceClient } +// V1Beta1ResourceServiceClientProvider provides ResourceServiceClients. +type V1Beta1ResourceServiceClientProvider interface { + V1Beta1ResourceServiceClient(registry string) pluginv1beta1connect.ResourceServiceClient +} + // V1Beta1PluginServiceClientProvider provides PluginServiceClients. type V1Beta1PluginServiceClientProvider interface { V1Beta1PluginServiceClient(registry string) pluginv1beta1connect.PluginServiceClient @@ -72,6 +79,7 @@ type ClientProvider interface { V1Beta1CommitServiceClientProvider V1Beta1DownloadServiceClientProvider V1Beta1LabelServiceClientProvider + V1Beta1ResourceServiceClientProvider V1Beta1PluginServiceClientProvider V1Beta1UploadServiceClientProvider } @@ -125,6 +133,14 @@ func (c *clientProvider) V1Beta1LabelServiceClient(registry string) pluginv1beta ) } +func (c *clientProvider) V1Beta1ResourceServiceClient(registry string) pluginv1beta1connect.ResourceServiceClient { + return connectclient.Make( + c.clientConfig, + registry, + pluginv1beta1connect.NewResourceServiceClient, + ) +} + func (c *clientProvider) V1Beta1PluginServiceClient(registry string) pluginv1beta1connect.PluginServiceClient { return connectclient.Make( c.clientConfig, @@ -159,6 +175,10 @@ func (nopClientProvider) V1Beta1LabelServiceClient(registry string) pluginv1beta return pluginv1beta1connect.UnimplementedLabelServiceHandler{} } +func (nopClientProvider) V1Beta1ResourceServiceClient(registry string) pluginv1beta1connect.ResourceServiceClient { + return pluginv1beta1connect.UnimplementedResourceServiceHandler{} +} + func (nopClientProvider) V1Beta1PluginServiceClient(registry string) pluginv1beta1connect.PluginServiceClient { return pluginv1beta1connect.UnimplementedPluginServiceHandler{} } From e5ec3c47bd29229854d6cae3b7d6c16af56316c9 Mon Sep 17 00:00:00 2001 From: Doria Keung Date: Tue, 3 Dec 2024 15:32:39 -0500 Subject: [PATCH 10/14] Upgrade wazero and quic-go (#3508) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 7343665627..556048c8af 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,12 @@ require ( github.com/klauspost/pgzip v1.2.6 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pkg/profile v1.7.0 - github.com/quic-go/quic-go v0.48.1 + github.com/quic-go/quic-go v0.48.2 github.com/rs/cors v1.11.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.10.0 - github.com/tetratelabs/wazero v1.8.1 + github.com/tetratelabs/wazero v1.8.2 go.lsp.dev/jsonrpc2 v0.10.0 go.lsp.dev/protocol v0.12.0 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index 2cdf4394c4..7e699d6d40 100644 --- a/go.sum +++ b/go.sum @@ -229,8 +229,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA= -github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE= +github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= @@ -258,8 +258,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= -github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= +github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4= +github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From 1729ad3e3cf2958c942efa85d6e5b6740131514d Mon Sep 17 00:00:00 2001 From: Doria Keung Date: Tue, 3 Dec 2024 15:39:28 -0500 Subject: [PATCH 11/14] Use ordered set for imports to iterate deterministically when filtering an image (#3507) --- CHANGELOG.md | 2 + .../bufimage/bufimageutil/bufimageutil.go | 79 ++++++++++++++++--- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcd8101d81..8579493b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Add `buf registry plugin {create,delete,info,update}` commands to manage BSR plugins. - Breaking analysis support for `buf beta lsp`. +- Fix bug when using the `--type` flag filter for `buf build` where import ordering is not + determinisitic. ## [v1.47.2] - 2024-11-14 diff --git a/private/bufpkg/bufimage/bufimageutil/bufimageutil.go b/private/bufpkg/bufimage/bufimageutil/bufimageutil.go index 414dbb7ef2..c37338791e 100644 --- a/private/bufpkg/bufimage/bufimageutil/bufimageutil.go +++ b/private/bufpkg/bufimage/bufimageutil/bufimageutil.go @@ -266,16 +266,20 @@ func ImageFilteredByTypesWithOptions(image bufimage.Image, types []string, opts // the file's WeakDependency field. indexFromTo := make(map[int32]int32) indexTo := 0 + // Only handle imports and dependencies if there are any. for indexFrom, importPath := range imageFileDescriptor.GetDependency() { path := append(basePath, int32(indexFrom)) - if _, ok := importsRequired[importPath]; ok { + // We check if the import path exists among required imports. If yes, we + // move and then delete from required imports as we go. + if importsRequired != nil && importsRequired.index(importPath) != -1 { sourcePathRemapper.markMoved(path, int32(indexTo)) indexFromTo[int32(indexFrom)] = int32(indexTo) imageFileDescriptor.Dependency[indexTo] = importPath indexTo++ - // markDeleted them as we go, so we know which ones weren't in the list - delete(importsRequired, importPath) + // delete them as we go, so we know which ones weren't in the list + importsRequired.delete(importPath) } else { + // Path did not exist in required imports, we mark as deleted. sourcePathRemapper.markDeleted(path) } } @@ -284,9 +288,12 @@ func ImageFilteredByTypesWithOptions(image bufimage.Image, types []string, opts // Add any other imports (which may not have been in the list because // they were picked up via a public import). The filtered files will not // use public imports. - for importPath := range importsRequired { - imageFileDescriptor.Dependency = append(imageFileDescriptor.Dependency, importPath) + // The imports are added in the order they are encountered when importing + // to maintain a deterministic ordering. + if importsRequired != nil { + imageFileDescriptor.Dependency = append(imageFileDescriptor.Dependency, importsRequired.keys()...) } + imageFileDescriptor.PublicDependency = nil sourcePathRemapper.markDeleted([]int32{filePublicDependencyTag}) @@ -458,9 +465,9 @@ type transitiveClosure struct { // entire package being included). The above fields are used to filter the // contents of files. But files named in this set will not be filtered. completeFiles map[string]struct{} - // The set of imports for each file. This allows for re-writing imports + // The ordered set of imports for each file. This allows for re-writing imports // for files whose contents have been pruned. - imports map[string]map[string]struct{} + imports map[string]*orderedImports } type closureInclusionMode int @@ -485,7 +492,7 @@ func newTransitiveClosure() *transitiveClosure { elements: map[namedDescriptor]closureInclusionMode{}, files: map[string]struct{}{}, completeFiles: map[string]struct{}{}, - imports: map[string]map[string]struct{}{}, + imports: map[string]*orderedImports{}, } } @@ -495,10 +502,10 @@ func (t *transitiveClosure) addImport(fromPath, toPath string) { } imps := t.imports[fromPath] if imps == nil { - imps = map[string]struct{}{} + imps = newOrderedImports() t.imports[fromPath] = imps } - imps[toPath] = struct{}{} + imps.add(toPath) } func (t *transitiveClosure) addFile(file string, imageIndex *imageIndex, opts *imageFilterOptions) error { @@ -1000,3 +1007,55 @@ func stripSourceRetentionOptionsFromFile(imageFile bufimage.ImageFile) (bufimage imageFile.UnusedDependencyIndexes(), ) } + +// orderedImports is a structure to maintain an ordered set of imports. This is needed +// because we want to be able to iterate through imports in a deterministic way when filtering +// the image. +type orderedImports struct { + pathToIndex map[string]int + paths []string +} + +// newOrderedImports creates a new orderedImports structure. +func newOrderedImports() *orderedImports { + return &orderedImports{ + pathToIndex: map[string]int{}, + } +} + +// index returns the index for a given path. If the path does not exist in index map, -1 +// is returned and should be considered deleted. +func (o *orderedImports) index(path string) int { + if index, ok := o.pathToIndex[path]; ok { + return index + } + return -1 +} + +// add appends a path to the paths list and the index in the map. If a key already exists, +// then this is a no-op. +func (o *orderedImports) add(path string) { + if _, ok := o.pathToIndex[path]; !ok { + o.pathToIndex[path] = len(o.paths) + o.paths = append(o.paths, path) + } +} + +// delete removes a key from the index map of ordered imports. If a non-existent path is +// set for deletion, then this is a no-op. +// Note that the path is not removed from the paths list. If you want to iterate through +// the paths, use keys() to get all non-deleted keys. +func (o *orderedImports) delete(path string) { + delete(o.pathToIndex, path) +} + +// keys provides all non-deleted keys from the ordered imports. +func (o *orderedImports) keys() []string { + keys := make([]string, 0, len(o.pathToIndex)) + for _, path := range o.paths { + if _, ok := o.pathToIndex[path]; ok { + keys = append(keys, path) + } + } + return keys +} From 1c39351b01603039d15d11ae75bce8b487debd9c Mon Sep 17 00:00:00 2001 From: Edward McFarlane <3036610+emcfarlane@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:19:29 -0700 Subject: [PATCH 12/14] Add `buf plugin push` command (#3474) --- CHANGELOG.md | 2 + private/buf/bufcli/uploader.go | 30 +- private/buf/cmd/buf/buf.go | 8 + .../command/plugin/pluginpush/pluginpush.go | 263 +++++++++++++++ .../command/plugin/pluginpush/usage.gen.go | 19 ++ private/buf/cmd/buf/command/push/push.go | 6 +- .../bufplugin/bufpluginapi/bufpluginapi.go | 15 + .../bufpkg/bufplugin/bufpluginapi/convert.go | 75 +++++ .../bufpkg/bufplugin/bufpluginapi/uploader.go | 312 ++++++++++++++++++ .../bufplugin/bufpluginapi/usage.gen.go | 19 ++ private/bufpkg/bufplugin/plugin.go | 244 ++++++++++++++ private/bufpkg/bufplugin/plugin_type.go | 46 +++ private/bufpkg/bufplugin/plugin_visibility.go | 43 +++ private/bufpkg/bufplugin/uploader.go | 156 +++++++++ 14 files changed, 1231 insertions(+), 7 deletions(-) create mode 100644 private/buf/cmd/buf/command/plugin/pluginpush/pluginpush.go create mode 100644 private/buf/cmd/buf/command/plugin/pluginpush/usage.gen.go create mode 100644 private/bufpkg/bufplugin/bufpluginapi/bufpluginapi.go create mode 100644 private/bufpkg/bufplugin/bufpluginapi/convert.go create mode 100644 private/bufpkg/bufplugin/bufpluginapi/uploader.go create mode 100644 private/bufpkg/bufplugin/bufpluginapi/usage.gen.go create mode 100644 private/bufpkg/bufplugin/plugin.go create mode 100644 private/bufpkg/bufplugin/plugin_type.go create mode 100644 private/bufpkg/bufplugin/plugin_visibility.go create mode 100644 private/bufpkg/bufplugin/uploader.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 8579493b7b..dc2dc40a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - Breaking analysis support for `buf beta lsp`. - Fix bug when using the `--type` flag filter for `buf build` where import ordering is not determinisitic. +- Add `buf plugin push` command to push a plugin to the Buf Schema Registry. + Only WebAssembly check plugins are supported at this time. ## [v1.47.2] - 2024-11-14 diff --git a/private/buf/bufcli/uploader.go b/private/buf/bufcli/uploader.go index df2d047a5e..4061c8114c 100644 --- a/private/buf/bufcli/uploader.go +++ b/private/buf/bufcli/uploader.go @@ -17,20 +17,32 @@ package bufcli import ( "github.com/bufbuild/buf/private/bufpkg/bufmodule" "github.com/bufbuild/buf/private/bufpkg/bufmodule/bufmoduleapi" + "github.com/bufbuild/buf/private/bufpkg/bufplugin" + "github.com/bufbuild/buf/private/bufpkg/bufplugin/bufpluginapi" "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapimodule" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" "github.com/bufbuild/buf/private/pkg/app/appext" ) -// NewUploader returns a new Uploader. -func NewUploader(container appext.Container) (bufmodule.Uploader, error) { +// NewModuleUploader returns a new Uploader for ModuleSets. +func NewModuleUploader(container appext.Container) (bufmodule.Uploader, error) { clientConfig, err := NewConnectClientConfig(container) if err != nil { return nil, err } - return newUploader(container, bufregistryapimodule.NewClientProvider(clientConfig)), nil + return newModuleUploader(container, bufregistryapimodule.NewClientProvider(clientConfig)), nil } -func newUploader( +// NewPluginUploader returns a new Uploader for Plugins. +func NewPluginUploader(container appext.Container) (bufplugin.Uploader, error) { + clientConfig, err := NewConnectClientConfig(container) + if err != nil { + return nil, err + } + return newPluginUploader(container, bufregistryapiplugin.NewClientProvider(clientConfig)), nil +} + +func newModuleUploader( container appext.Container, clientProvider bufregistryapimodule.ClientProvider, ) bufmodule.Uploader { @@ -41,3 +53,13 @@ func newUploader( bufmoduleapi.UploaderWithPublicRegistry(container.Env(publicRegistryEnvKey)), ) } + +func newPluginUploader( + container appext.Container, + clientProvider bufregistryapiplugin.ClientProvider, +) bufplugin.Uploader { + return bufpluginapi.NewUploader( + container.Logger(), + clientProvider, + ) +} diff --git a/private/buf/cmd/buf/buf.go b/private/buf/cmd/buf/buf.go index 776b611c06..df33dacabf 100644 --- a/private/buf/cmd/buf/buf.go +++ b/private/buf/cmd/buf/buf.go @@ -62,6 +62,7 @@ import ( "github.com/bufbuild/buf/private/buf/cmd/buf/command/mod/modlsbreakingrules" "github.com/bufbuild/buf/private/buf/cmd/buf/command/mod/modlslintrules" "github.com/bufbuild/buf/private/buf/cmd/buf/command/mod/modopen" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/plugin/pluginpush" "github.com/bufbuild/buf/private/buf/cmd/buf/command/push" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/module/modulecommit/modulecommitaddlabel" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/module/modulecommit/modulecommitinfo" @@ -175,6 +176,13 @@ func NewRootCommand(name string) *appcmd.Command { modlsbreakingrules.NewCommand("ls-breaking-rules", builder), }, }, + { + Use: "plugin", + Short: "Work with check plugins", + SubCommands: []*appcmd.Command{ + pluginpush.NewCommand("push", builder), + }, + }, { Use: "registry", Short: "Manage assets on the Buf Schema Registry", diff --git a/private/buf/cmd/buf/command/plugin/pluginpush/pluginpush.go b/private/buf/cmd/buf/command/plugin/pluginpush/pluginpush.go new file mode 100644 index 0000000000..4f509d1c01 --- /dev/null +++ b/private/buf/cmd/buf/command/plugin/pluginpush/pluginpush.go @@ -0,0 +1,263 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginpush + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/slicesext" + "github.com/bufbuild/buf/private/pkg/stringutil" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const ( + labelFlagName = "label" + binaryFlagName = "binary" + createFlagName = "create" + createVisibilityFlagName = "create-visibility" + createTypeFlagName = "create-type" + sourceControlURLFlagName = "source-control-url" +) + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Push a check plugin to a registry", + Long: `The first argument is the plugin full name in the format .`, + Args: appcmd.MaximumNArgs(1), + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Labels []string + Binary string + Create bool + CreateVisibility string + CreateType string + SourceControlURL string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + bufcli.BindCreateVisibility(flagSet, &f.CreateVisibility, createVisibilityFlagName, createFlagName) + flagSet.StringSliceVar( + &f.Labels, + labelFlagName, + nil, + "Associate the label with the plugins pushed. Can be used multiple times.", + ) + flagSet.StringVar( + &f.Binary, + binaryFlagName, + "", + "The path to the Wasm binary file to push.", + ) + flagSet.BoolVar( + &f.Create, + createFlagName, + false, + fmt.Sprintf( + "Create the plugin if it does not exist. Defaults to creating a private plugin on the BSR if --%s is not set. Must be used with --%s.", + createVisibilityFlagName, + createTypeFlagName, + ), + ) + flagSet.StringVar( + &f.CreateType, + createTypeFlagName, + "", + fmt.Sprintf( + "The plugin's type setting, if created. Can only be set with --%s. Must be one of %s", + createTypeFlagName, + stringutil.SliceToString(bufplugin.AllPluginTypeStrings), + ), + ) + flagSet.StringVar( + &f.SourceControlURL, + sourceControlURLFlagName, + "", + "The URL for viewing the source code of the pushed plugins (e.g. the specific commit in source control).", + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) (retErr error) { + if err := validateFlags(flags); err != nil { + return err + } + // We parse the plugin full name from the user-provided argument. + pluginFullName, err := bufparse.ParseFullName(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + commit, err := upload(ctx, container, flags, pluginFullName) + if err != nil { + return err + } + // Only one commit is returned. + if _, err := fmt.Fprintf(container.Stdout(), "%s\n", commit.PluginKey().String()); err != nil { + return syserror.Wrap(err) + } + return nil +} + +func upload( + ctx context.Context, + container appext.Container, + flags *flags, + pluginFullName bufparse.FullName, +) (_ bufplugin.Commit, retErr error) { + var plugin bufplugin.Plugin + switch { + case flags.Binary != "": + var err error + plugin, err = bufplugin.NewLocalWasmPlugin( + pluginFullName, + func() ([]byte, error) { + wasmBinary, err := os.ReadFile(flags.Binary) + if err != nil { + return nil, fmt.Errorf("could not read Wasm binary %q: %w", flags.Binary, err) + } + return wasmBinary, nil + }, + ) + if err != nil { + return nil, err + } + default: + // This should never happen because the flags are validated. + return nil, syserror.Newf("--%s must be set", binaryFlagName) + } + uploader, err := bufcli.NewPluginUploader(container) + if err != nil { + return nil, err + } + var options []bufplugin.UploadOption + if flags.Create { + createPluginVisibility, err := bufplugin.ParsePluginVisibility(flags.CreateVisibility) + if err != nil { + return nil, err + } + createPluginType, err := bufplugin.ParsePluginType(flags.CreateType) + if err != nil { + return nil, err + } + options = append(options, bufplugin.UploadWithCreateIfNotExist( + createPluginVisibility, + createPluginType, + )) + } + commits, err := uploader.Upload(ctx, []bufplugin.Plugin{plugin}, options...) + if err != nil { + return nil, err + } + if len(commits) != 1 { + return nil, syserror.Newf("unexpected number of commits returned from server: %d", len(commits)) + } + return commits[0], nil +} + +func validateFlags(flags *flags) error { + if err := validateLabelFlags(flags); err != nil { + return err + } + if err := validateTypeFlags(flags); err != nil { + return err + } + if err := validateCreateFlags(flags); err != nil { + return err + } + return nil +} + +func validateLabelFlags(flags *flags) error { + return validateLabelFlagValues(flags) +} + +func validateTypeFlags(flags *flags) error { + var typeFlags []string + if flags.Binary != "" { + typeFlags = append(typeFlags, binaryFlagName) + } + if len(typeFlags) > 1 { + usedFlagsErrStr := strings.Join( + slicesext.Map( + typeFlags, + func(flag string) string { return fmt.Sprintf("--%s", flag) }, + ), + ", ", + ) + return appcmd.NewInvalidArgumentErrorf("These flags cannot be used in combination with one another: %s", usedFlagsErrStr) + } + if len(typeFlags) == 0 { + return appcmd.NewInvalidArgumentErrorf("--%s must be set", binaryFlagName) + } + return nil +} + +func validateLabelFlagValues(flags *flags) error { + for _, label := range flags.Labels { + if label == "" { + return appcmd.NewInvalidArgumentErrorf("--%s requires a non-empty string", labelFlagName) + } + } + return nil +} + +func validateCreateFlags(flags *flags) error { + if flags.Create { + if flags.CreateVisibility == "" { + return appcmd.NewInvalidArgumentErrorf("--%s must be set if --%s is set", createVisibilityFlagName, createFlagName) + } + if _, err := bufplugin.ParsePluginVisibility(flags.CreateVisibility); err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + } + if flags.Create { + if flags.CreateType == "" { + return appcmd.NewInvalidArgumentErrorf("--%s must be set if --%s is set", createTypeFlagName, createFlagName) + } + if _, err := bufplugin.ParsePluginType(flags.CreateType); err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + } + return nil +} diff --git a/private/buf/cmd/buf/command/plugin/pluginpush/usage.gen.go b/private/buf/cmd/buf/command/plugin/pluginpush/usage.gen.go new file mode 100644 index 0000000000..3184fae49e --- /dev/null +++ b/private/buf/cmd/buf/command/plugin/pluginpush/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginpush + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/push/push.go b/private/buf/cmd/buf/command/push/push.go index 213db7689e..53e3545a86 100644 --- a/private/buf/cmd/buf/command/push/push.go +++ b/private/buf/cmd/buf/command/push/push.go @@ -126,7 +126,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) { createFlagName, false, fmt.Sprintf( - "Create the repository if it does not exist. Defaults to creating a private repository if --%s is not set.", + "Create the module if it does not exist. Defaults to creating a private module if --%s is not set.", createVisibilityFlagName, ), ) @@ -134,7 +134,7 @@ func (f *flags) Bind(flagSet *pflag.FlagSet) { &f.CreateDefaultLabel, createDefaultLabelFlagName, "", - `The repository's default label setting, if created. If this is not set, then the repository will be created with the default label "main".`, + `The module's default label setting, if created. If this is not set, then the module will be created with the default label "main".`, ) flagSet.StringVar( &f.SourceControlURL, @@ -218,7 +218,7 @@ func run( return err } - uploader, err := bufcli.NewUploader(container) + uploader, err := bufcli.NewModuleUploader(container) if err != nil { return err } diff --git a/private/bufpkg/bufplugin/bufpluginapi/bufpluginapi.go b/private/bufpkg/bufplugin/bufpluginapi/bufpluginapi.go new file mode 100644 index 0000000000..816d5770ad --- /dev/null +++ b/private/bufpkg/bufplugin/bufpluginapi/bufpluginapi.go @@ -0,0 +1,15 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufpluginapi diff --git a/private/bufpkg/bufplugin/bufpluginapi/convert.go b/private/bufpkg/bufplugin/bufpluginapi/convert.go new file mode 100644 index 0000000000..8b15660e68 --- /dev/null +++ b/private/bufpkg/bufplugin/bufpluginapi/convert.go @@ -0,0 +1,75 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufpluginapi + +import ( + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "github.com/bufbuild/buf/private/bufpkg/bufcas" + "github.com/bufbuild/buf/private/bufpkg/bufplugin" +) + +var ( + v1beta1ProtoDigestTypeToDigestType = map[pluginv1beta1.DigestType]bufplugin.DigestType{ + pluginv1beta1.DigestType_DIGEST_TYPE_P1: bufplugin.DigestTypeP1, + } +) + +// V1Beta1ProtoToDigest converts the given proto Digest to a Digest. +// +// Validation is performed to ensure the DigestType is known, and the value +// is a valid digest value for the given DigestType. +func V1Beta1ProtoToDigest(protoDigest *pluginv1beta1.Digest) (bufplugin.Digest, error) { + digestType, err := v1beta1ProtoToDigestType(protoDigest.Type) + if err != nil { + return nil, err + } + bufcasDigest, err := bufcas.NewDigest(protoDigest.Value) + if err != nil { + return nil, err + } + return bufplugin.NewDigest(digestType, bufcasDigest) +} + +// *** PRIVATE *** + +func pluginVisibilityToV1Beta1Proto(pluginVisibility bufplugin.PluginVisibility) (pluginv1beta1.PluginVisibility, error) { + switch pluginVisibility { + case bufplugin.PluginVisibilityPublic: + return pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_PUBLIC, nil + case bufplugin.PluginVisibilityPrivate: + return pluginv1beta1.PluginVisibility_PLUGIN_VISIBILITY_PRIVATE, nil + default: + return 0, fmt.Errorf("unknown PluginVisibility: %v", pluginVisibility) + } +} + +func pluginTypeToV1Beta1Proto(pluginType bufplugin.PluginType) (pluginv1beta1.PluginType, error) { + switch pluginType { + case bufplugin.PluginTypeCheck: + return pluginv1beta1.PluginType_PLUGIN_TYPE_CHECK, nil + default: + return 0, fmt.Errorf("unknown PluginType: %v", pluginType) + } +} + +func v1beta1ProtoToDigestType(protoDigestType pluginv1beta1.DigestType) (bufplugin.DigestType, error) { + digestType, ok := v1beta1ProtoDigestTypeToDigestType[protoDigestType] + if !ok { + return 0, fmt.Errorf("unknown pluginv1beta1.DigestType: %v", protoDigestType) + } + return digestType, nil +} diff --git a/private/bufpkg/bufplugin/bufpluginapi/uploader.go b/private/bufpkg/bufplugin/bufpluginapi/uploader.go new file mode 100644 index 0000000000..cca723d1a2 --- /dev/null +++ b/private/bufpkg/bufplugin/bufpluginapi/uploader.go @@ -0,0 +1,312 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufpluginapi + +import ( + "context" + "fmt" + "log/slog" + "time" + + ownerv1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/owner/v1" + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/bufpkg/bufplugin" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/slicesext" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/bufbuild/buf/private/pkg/uuidutil" + "github.com/klauspost/compress/zstd" +) + +// NewUploader returns a new Uploader for the given API client. +func NewUploader( + logger *slog.Logger, + pluginClientProvider interface { + bufregistryapiplugin.V1Beta1PluginServiceClientProvider + bufregistryapiplugin.V1Beta1UploadServiceClientProvider + }, + options ...UploaderOption, +) bufplugin.Uploader { + return newUploader(logger, pluginClientProvider, options...) +} + +// UploaderOption is an option for a new Uploader. +type UploaderOption func(*uploader) + +// *** PRIVATE *** + +type uploader struct { + logger *slog.Logger + pluginClientProvider interface { + bufregistryapiplugin.V1Beta1PluginServiceClientProvider + bufregistryapiplugin.V1Beta1UploadServiceClientProvider + } +} + +func newUploader( + logger *slog.Logger, + pluginClientProvider interface { + bufregistryapiplugin.V1Beta1PluginServiceClientProvider + bufregistryapiplugin.V1Beta1UploadServiceClientProvider + }, + options ...UploaderOption, +) *uploader { + uploader := &uploader{ + logger: logger, + pluginClientProvider: pluginClientProvider, + } + for _, option := range options { + option(uploader) + } + return uploader +} + +func (u *uploader) Upload( + ctx context.Context, + plugins []bufplugin.Plugin, + options ...bufplugin.UploadOption, +) ([]bufplugin.Commit, error) { + uploadOptions, err := bufplugin.NewUploadOptions(options) + if err != nil { + return nil, err + } + registryToIndexedPluginKeys := slicesext.ToIndexedValuesMap( + plugins, + func(plugin bufplugin.Plugin) string { + return plugin.FullName().Registry() + }, + ) + indexedCommits := make([]slicesext.Indexed[bufplugin.Commit], 0, len(plugins)) + for registry, indexedPluginKeys := range registryToIndexedPluginKeys { + indexedRegistryPluginDatas, err := u.uploadIndexedPluginsForRegistry( + ctx, + registry, + indexedPluginKeys, + uploadOptions, + ) + if err != nil { + return nil, err + } + indexedCommits = append(indexedCommits, indexedRegistryPluginDatas...) + } + return slicesext.IndexedToSortedValues(indexedCommits), nil +} + +func (u *uploader) uploadIndexedPluginsForRegistry( + ctx context.Context, + registry string, + indexedPlugins []slicesext.Indexed[bufplugin.Plugin], + uploadOptions bufplugin.UploadOptions, +) ([]slicesext.Indexed[bufplugin.Commit], error) { + if uploadOptions.CreateIfNotExist() { + // We must attempt to create each Plugin one at a time, since CreatePlugins will return + // an `AlreadyExists` if any of the Plugins we are attempting to create already exists, + // and no new Plugins will be created. + for _, indexedPlugin := range indexedPlugins { + plugin := indexedPlugin.Value + if _, err := u.createPluginIfNotExist( + ctx, + registry, + plugin, + uploadOptions.CreatePluginVisibility(), + uploadOptions.CreatePluginType(), + ); err != nil { + return nil, err + } + } + } + contents, err := slicesext.MapError(indexedPlugins, func(indexedPlugin slicesext.Indexed[bufplugin.Plugin]) (*pluginv1beta1.UploadRequest_Content, error) { + plugin := indexedPlugin.Value + if !plugin.IsLocal() { + return nil, syserror.New("expected local Plugin in uploadIndexedPluginsForRegistry") + } + if plugin.FullName() == nil { + return nil, syserror.Newf("expected Plugin name for local Plugin: %s", plugin.Description()) + } + data, err := plugin.Data() + if err != nil { + return nil, err + } + compressedWasmBinary, err := zstdCompress(data) + if err != nil { + return nil, fmt.Errorf("could not compress Plugin data %q: %w", plugin.OpaqueID(), err) + } + return &pluginv1beta1.UploadRequest_Content{ + PluginRef: &pluginv1beta1.PluginRef{ + Value: &pluginv1beta1.PluginRef_Name_{ + Name: &pluginv1beta1.PluginRef_Name{ + Owner: plugin.FullName().Owner(), + Plugin: plugin.FullName().Name(), + }, + }, + }, + CompressionType: pluginv1beta1.CompressionType_COMPRESSION_TYPE_ZSTD, + Content: compressedWasmBinary, + ScopedLabelRefs: slicesext.Map(uploadOptions.Labels(), func(label string) *pluginv1beta1.ScopedLabelRef { + return &pluginv1beta1.ScopedLabelRef{ + Value: &pluginv1beta1.ScopedLabelRef_Name{ + Name: label, + }, + } + }), + SourceControlUrl: uploadOptions.SourceControlURL(), + }, nil + }) + if err != nil { + return nil, err + } + + uploadResponse, err := u.pluginClientProvider.V1Beta1UploadServiceClient(registry).Upload( + ctx, + connect.NewRequest(&pluginv1beta1.UploadRequest{ + Contents: contents, + })) + if err != nil { + return nil, err + } + pluginCommits := uploadResponse.Msg.Commits + if len(pluginCommits) != len(indexedPlugins) { + return nil, syserror.Newf("expected %d Commits, found %d", len(indexedPlugins), len(pluginCommits)) + } + + indexedCommits := make([]slicesext.Indexed[bufplugin.Commit], 0, len(indexedPlugins)) + for i, pluginCommit := range pluginCommits { + pluginFullName := indexedPlugins[i].Value.FullName() + commitID, err := uuidutil.FromDashless(pluginCommit.Id) + if err != nil { + return nil, err + } + pluginKey, err := bufplugin.NewPluginKey( + pluginFullName, + commitID, + func() (bufplugin.Digest, error) { + return V1Beta1ProtoToDigest(pluginCommit.Digest) + }, + ) + if err != nil { + return nil, err + } + commit := bufplugin.NewCommit( + pluginKey, + func() (time.Time, error) { + return pluginCommit.CreateTime.AsTime(), nil + }, + ) + indexedCommits = append( + indexedCommits, + slicesext.Indexed[bufplugin.Commit]{ + Value: commit, + Index: i, + }, + ) + } + return indexedCommits, nil +} + +func (u *uploader) createPluginIfNotExist( + ctx context.Context, + primaryRegistry string, + plugin bufplugin.Plugin, + createPluginVisibility bufplugin.PluginVisibility, + createPluginType bufplugin.PluginType, +) (*pluginv1beta1.Plugin, error) { + v1Beta1ProtoCreatePluginVisibility, err := pluginVisibilityToV1Beta1Proto(createPluginVisibility) + if err != nil { + return nil, err + } + v1Beta1ProtoCreatePluginType, err := pluginTypeToV1Beta1Proto(createPluginType) + if err != nil { + return nil, err + } + response, err := u.pluginClientProvider.V1Beta1PluginServiceClient(primaryRegistry).CreatePlugins( + ctx, + connect.NewRequest( + &pluginv1beta1.CreatePluginsRequest{ + Values: []*pluginv1beta1.CreatePluginsRequest_Value{ + { + OwnerRef: &ownerv1.OwnerRef{ + Value: &ownerv1.OwnerRef_Name{ + Name: plugin.FullName().Owner(), + }, + }, + Name: plugin.FullName().Name(), + Visibility: v1Beta1ProtoCreatePluginVisibility, + Type: v1Beta1ProtoCreatePluginType, + }, + }, + }, + ), + ) + if err != nil { + if connect.CodeOf(err) == connect.CodeAlreadyExists { + // If a plugin already existed, then we check validate its contents. + plugins, err := u.validatePluginsExist(ctx, primaryRegistry, []bufplugin.Plugin{plugin}) + if err != nil { + return nil, err + } + if len(plugins) != 1 { + return nil, syserror.Newf("expected 1 Plugin, found %d", len(plugins)) + } + return plugins[0], nil + } + return nil, err + } + if len(response.Msg.Plugins) != 1 { + return nil, syserror.Newf("expected 1 Plugin, found %d", len(response.Msg.Plugins)) + } + // Otherwise we return the plugin we created. + return response.Msg.Plugins[0], nil +} + +func (u *uploader) validatePluginsExist( + ctx context.Context, + primaryRegistry string, + plugins []bufplugin.Plugin, +) ([]*pluginv1beta1.Plugin, error) { + response, err := u.pluginClientProvider.V1Beta1PluginServiceClient(primaryRegistry).GetPlugins( + ctx, + connect.NewRequest( + &pluginv1beta1.GetPluginsRequest{ + PluginRefs: slicesext.Map( + plugins, + func(plugin bufplugin.Plugin) *pluginv1beta1.PluginRef { + return &pluginv1beta1.PluginRef{ + Value: &pluginv1beta1.PluginRef_Name_{ + Name: &pluginv1beta1.PluginRef_Name{ + Owner: plugin.FullName().Owner(), + Plugin: plugin.FullName().Name(), + }, + }, + } + }, + ), + }, + ), + ) + if err != nil { + return nil, err + } + return response.Msg.Plugins, nil +} + +func zstdCompress(data []byte) ([]byte, error) { + encoder, err := zstd.NewWriter(nil) + if err != nil { + return nil, err + } + defer encoder.Close() + return encoder.EncodeAll(data, nil), nil +} diff --git a/private/bufpkg/bufplugin/bufpluginapi/usage.gen.go b/private/bufpkg/bufplugin/bufpluginapi/usage.gen.go new file mode 100644 index 0000000000..cba34bb462 --- /dev/null +++ b/private/bufpkg/bufplugin/bufpluginapi/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package bufpluginapi + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/bufpkg/bufplugin/plugin.go b/private/bufpkg/bufplugin/plugin.go new file mode 100644 index 0000000000..438f52a60f --- /dev/null +++ b/private/bufpkg/bufplugin/plugin.go @@ -0,0 +1,244 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufplugin + +import ( + "fmt" + "strings" + "sync" + + "github.com/bufbuild/buf/private/bufpkg/bufcas" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/google/uuid" +) + +// Plugin presents a BSR plugin. +type Plugin interface { + // OpaqueID returns an unstructured ID that can uniquely identify a Plugin + // relative to the Workspace. + // + // An OpaqueID's structure should not be relied upon, and is not a + // globally-unique identifier. It's uniqueness property only applies to + // the lifetime of the Plugin, and only within Plugin commonly built + // from the Workspace root. + // + // If two Plugins have the same FullName, they will have the same OpaqueID. + OpaqueID() string + // Path returns the path, including arguments, to invoke the binary plugin. + // + // This is not empty only when the plugin is local. + Path() []string + // FullName returns the FullName of the Plugin. + // + // This is nil + FullName() bufparse.FullName + // CommitID returns the BSR ID of the Commit. + // + // It is up to the caller to convert this to a dashless ID when necessary. + // + // May be empty, that is CommitID() == uuid.Nil may be true. + // Callers should not rely on this value being present. + // + // If FullName is nil, this will always be empty. + CommitID() uuid.UUID + // Description returns a human-readable description of the Plugin. + // + // This is used to construct descriptive error messages pointing to configured plugins. + // + // This will never be empty. If a description was not explicitly set, this falls back to + // OpaqueID. + Description() string + // Digest returns the Plugin digest for the given DigestType. + // + // Note this is *not* a bufcas.Digest - this is a Digest. + // bufcas.Digests are a lower-level type that just deal in terms of + // files and content. A Digest is a specific algorithm applied to the + // content of a Plugin. + // + // Will return an error if the Plugin is not a Wasm Plugin. + Digest(DigestType) (Digest, error) + // Data returns the bytes of the Plugin as a Wasm module. + // + // This is the raw bytes of the Wasm module in an uncompressed form. + // + // Will return an error if the Plugin is not a Wasm Plugin. + Data() ([]byte, error) + // IsWasm returns true if the Plugin is a Wasm Plugin. + // + // Plugins are either Wasm or not Wasm. + // + // A Wasm Plugin is a Plugin that is a Wasm module. Wasm Plugins are invoked + // with the wasm.Runtime. The Plugin will have Data and will be able to + // calculate Digests. + // + // Wasm Plugins will always have Data. + IsWasm() bool + // IsLocal returns true if the Plugin is a local Plugin. + // + // Plugins are either local or remote. + // + // A local Plugin is one that is built from sources from the "local context", + // such as a Workspace. Local Plugins are important for understanding what Plugins + // to push. + // + // Remote Plugins will always have FullNames. + IsLocal() bool + + isPlugin() +} + +// NewLocalWasmPlugin returns a new Plugin for a local Wasm plugin. +func NewLocalWasmPlugin( + pluginFullName bufparse.FullName, + getData func() ([]byte, error), +) (Plugin, error) { + return newPlugin( + "", // description + pluginFullName, + nil, // path + uuid.Nil, // commitID + true, // isWasm + true, // isLocal + getData, + ) +} + +// *** PRIVATE *** + +type plugin struct { + description string + pluginFullName bufparse.FullName + path []string + commitID uuid.UUID + isWasm bool + isLocal bool + getData func() ([]byte, error) + + digestTypeToGetDigest map[DigestType]func() (Digest, error) +} + +func newPlugin( + description string, + pluginFullName bufparse.FullName, + path []string, + commitID uuid.UUID, + isWasm bool, + isLocal bool, + getData func() ([]byte, error), +) (*plugin, error) { + if isWasm && getData == nil { + return nil, syserror.Newf("getData not present when constructing a Wasm Plugin") + } + if !isWasm && len(path) == 0 { + return nil, syserror.New("path not present when constructing a non-Wasm Plugin") + } + if !isLocal && pluginFullName == nil { + return nil, syserror.New("pluginFullName not present when constructing a remote Plugin") + } + if !isLocal && !isWasm { + return nil, syserror.New("non-Wasm remote Plugins are not supported") + } + if isLocal && commitID != uuid.Nil { + return nil, syserror.New("commitID present when constructing a local Plugin") + } + if pluginFullName == nil && commitID != uuid.Nil { + return nil, syserror.New("pluginFullName not present and commitID present when constructing a remote Plugin") + } + plugin := &plugin{ + description: description, + pluginFullName: pluginFullName, + path: path, + commitID: commitID, + isWasm: isWasm, + isLocal: isLocal, + getData: sync.OnceValues(getData), + } + plugin.digestTypeToGetDigest = newSyncOnceValueDigestTypeToGetDigestFuncForPlugin(plugin) + return plugin, nil +} + +func (p *plugin) OpaqueID() string { + if p.pluginFullName != nil { + return p.pluginFullName.String() + } + return strings.Join(p.path, " ") +} + +func (p *plugin) Path() []string { + return p.path +} + +func (p *plugin) FullName() bufparse.FullName { + return p.pluginFullName +} + +func (p *plugin) CommitID() uuid.UUID { + return p.commitID +} + +func (p *plugin) Description() string { + if p.description != "" { + return p.description + } + return p.OpaqueID() +} + +func (p *plugin) Data() ([]byte, error) { + if !p.isWasm { + return nil, fmt.Errorf("Plugin is not a Wasm Plugin") + } + return p.getData() +} + +func (p *plugin) Digest(digestType DigestType) (Digest, error) { + getDigest, ok := p.digestTypeToGetDigest[digestType] + if !ok { + return nil, syserror.Newf("DigestType %v was not in plugin.digestTypeToGetDigest", digestType) + } + return getDigest() +} + +func (p *plugin) IsWasm() bool { + return p.isWasm +} + +func (p *plugin) IsLocal() bool { + return p.isLocal +} + +func (p *plugin) isPlugin() {} + +func newSyncOnceValueDigestTypeToGetDigestFuncForPlugin(plugin *plugin) map[DigestType]func() (Digest, error) { + m := make(map[DigestType]func() (Digest, error)) + for digestType := range digestTypeToString { + m[digestType] = sync.OnceValues(newGetDigestFuncForPluginAndDigestType(plugin, digestType)) + } + return m +} + +func newGetDigestFuncForPluginAndDigestType(plugin *plugin, digestType DigestType) func() (Digest, error) { + return func() (Digest, error) { + data, err := plugin.getData() + if err != nil { + return nil, err + } + bufcasDigest, err := bufcas.NewDigest(data) + if err != nil { + return nil, err + } + return NewDigest(digestType, bufcasDigest) + } +} diff --git a/private/bufpkg/bufplugin/plugin_type.go b/private/bufpkg/bufplugin/plugin_type.go new file mode 100644 index 0000000000..2d06454ac4 --- /dev/null +++ b/private/bufpkg/bufplugin/plugin_type.go @@ -0,0 +1,46 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufplugin + +import ( + "fmt" +) + +const ( + // PluginTypeCheck says the Plugin is a check plugin. + PluginTypeCheck = iota + 1 +) + +var ( + // AllPluginTypeStrings is all format strings without aliases. + // + // Sorted in the order we want to display them. + AllPluginTypeStrings = []string{ + "check", + } +) + +// PluginType is the type of a Plugin. +type PluginType int + +// ParsePluginType parses the PluginType from the string. +func ParsePluginType(s string) (PluginType, error) { + switch s { + case "check": + return PluginVisibilityPublic, nil + default: + return 0, fmt.Errorf("unknown PluginType: %q", s) + } +} diff --git a/private/bufpkg/bufplugin/plugin_visibility.go b/private/bufpkg/bufplugin/plugin_visibility.go new file mode 100644 index 0000000000..d9523989c9 --- /dev/null +++ b/private/bufpkg/bufplugin/plugin_visibility.go @@ -0,0 +1,43 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufplugin + +import ( + "fmt" +) + +const ( + // PluginVisibilityPublic says the Plugin is public on the registry. + PluginVisibilityPublic = iota + 1 + // PluginVisibilityPublic says the Plugin is private on the registry. + PluginVisibilityPrivate +) + +// PluginVisibility is the visibility of a Plugin on a registry. +// +// Only used for Upload for now. +type PluginVisibility int + +// ParsePluginVisibility parses the PluginVisibility from the string. +func ParsePluginVisibility(s string) (PluginVisibility, error) { + switch s { + case "public": + return PluginVisibilityPublic, nil + case "private": + return PluginVisibilityPrivate, nil + default: + return 0, fmt.Errorf("unknown PluginVisibility: %q", s) + } +} diff --git a/private/bufpkg/bufplugin/uploader.go b/private/bufpkg/bufplugin/uploader.go new file mode 100644 index 0000000000..3eb4c06210 --- /dev/null +++ b/private/bufpkg/bufplugin/uploader.go @@ -0,0 +1,156 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bufplugin + +import ( + "context" + "errors" + "fmt" + "net/url" + + "github.com/bufbuild/buf/private/pkg/slicesext" +) + +var ( + // NopUploader is a no-op Uploader. + NopUploader Uploader = nopUploader{} +) + +// Uploader uploads Plugins. +type Uploader interface { + // Upload uploads the given Plugins. + Upload(ctx context.Context, plugins []Plugin, options ...UploadOption) ([]Commit, error) +} + +// UploadOption is an option for an Upload. +type UploadOption func(*uploadOptions) + +// UploadWithLabels returns a new UploadOption that adds the given labels. +// +// This can be called multiple times. The unique result set of labels will be used. +func UploadWithLabels(labels ...string) UploadOption { + return func(uploadOptions *uploadOptions) { + uploadOptions.labels = append(uploadOptions.labels, labels...) + } +} + +// UploadWithCreateIfNotExist returns a new UploadOption that will result in the +// Plugins being created on the registry with the given visibility if they do not exist. +func UploadWithCreateIfNotExist(createPluginVisibility PluginVisibility, createPluginType PluginType) UploadOption { + return func(uploadOptions *uploadOptions) { + uploadOptions.createIfNotExist = true + uploadOptions.createPluginVisibility = createPluginVisibility + uploadOptions.createPluginType = createPluginType + } +} + +// UploadWithSourceControlURL returns a new UploadOption that will set the source control +// url for the plugin contents uploaded. +func UploadWithSourceControlURL(sourceControlURL string) UploadOption { + return func(uploadOptions *uploadOptions) { + uploadOptions.sourceControlURL = sourceControlURL + } +} + +// UploadOptions are the possible options for upload. +// +// This is used by Uploader implementations. +type UploadOptions interface { + // Labels returns the unique and sorted set of labels to add. Labels + // are set using the `--label` flag when calling `buf plugin upload` + // and represent the labels that are set when uploading plugin data. + Labels() []string + // CreateIfNotExist says to create Plugins if they do not exist on the registry. + CreateIfNotExist() bool + // CreatePluginVisibility returns the visibility to create Plugins with. + // + // Will always be present if CreateIfNotExist() is true. + CreatePluginVisibility() PluginVisibility + // CreatePluginType returns the type to create Plugins with. + // + // Will always be present if CreateIfNotExist() is true. + CreatePluginType() PluginType + // SourceControlURL returns the source control URL set by the user for the plugin + // contents uploaded. We set the same source control URL for all plugin contents. + SourceControlURL() string + + isUploadOptions() +} + +// NewUploadOptions returns a new UploadOptions. +func NewUploadOptions(options []UploadOption) (UploadOptions, error) { + uploadOptions := newUploadOptions() + for _, option := range options { + option(uploadOptions) + } + if err := uploadOptions.validate(); err != nil { + return nil, err + } + return uploadOptions, nil +} + +// *** PRIVATE *** + +type nopUploader struct{} + +func (nopUploader) Upload(context.Context, []Plugin, ...UploadOption) ([]Commit, error) { + return nil, errors.New("unimplemented: no-op Uploader called") +} + +type uploadOptions struct { + labels []string + createIfNotExist bool + createPluginVisibility PluginVisibility + createPluginType PluginType + sourceControlURL string +} + +func newUploadOptions() *uploadOptions { + return &uploadOptions{} +} + +func (u *uploadOptions) Labels() []string { + return slicesext.ToUniqueSorted(u.labels) +} + +func (u *uploadOptions) CreateIfNotExist() bool { + return u.createIfNotExist +} + +func (u *uploadOptions) CreatePluginVisibility() PluginVisibility { + return u.createPluginVisibility +} + +func (u *uploadOptions) CreatePluginType() PluginType { + return u.createPluginType +} + +func (u *uploadOptions) SourceControlURL() string { + return u.sourceControlURL +} + +func (u *uploadOptions) isUploadOptions() {} + +func (u *uploadOptions) validate() error { + if u.createIfNotExist && u.createPluginVisibility == 0 { + return errors.New("must set a valid PluginVisibility if CreateIfNotExist was specified") + } + if u.sourceControlURL != "" { + if _, err := url.Parse(u.sourceControlURL); err != nil { + return fmt.Errorf("must set a valid url for the source control url: %w", err) + } + } + return nil +} From 1101ca10a3bd0d6d1c59acbc44ca26af4807dbdf Mon Sep 17 00:00:00 2001 From: Edward McFarlane <3036610+emcfarlane@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:25:58 -0700 Subject: [PATCH 13/14] Add `buf plugin registry commit` commands (#3498) --- CHANGELOG.md | 1 + private/buf/bufprint/bufprint.go | 44 +-- private/buf/cmd/buf/buf.go | 14 + .../plugincommitaddlabel.go | 149 ++++++++++ .../plugincommitaddlabel/usage.gen.go | 19 ++ .../plugincommitinfo/plugincommitinfo.go | 129 ++++++++ .../plugincommitinfo/usage.gen.go | 19 ++ .../plugincommitlist/plugincommitlist.go | 276 ++++++++++++++++++ .../plugincommitlist/usage.gen.go | 19 ++ .../plugincommitresolve.go | 128 ++++++++ .../plugincommitresolve/usage.gen.go | 19 ++ 11 files changed, 800 insertions(+), 17 deletions(-) create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/plugincommitaddlabel.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitinfo/plugincommitinfo.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitinfo/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitlist/plugincommitlist.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitlist/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitresolve/plugincommitresolve.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitresolve/usage.gen.go diff --git a/CHANGELOG.md b/CHANGELOG.md index dc2dc40a4d..066c0ab0cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ determinisitic. - Add `buf plugin push` command to push a plugin to the Buf Schema Registry. Only WebAssembly check plugins are supported at this time. +- Add `buf registry plugin commit {add-label,info,list,resolve}` to manage BSR plugin commits. ## [v1.47.2] - 2024-11-14 diff --git a/private/buf/bufprint/bufprint.go b/private/buf/bufprint/bufprint.go index 28dd537109..ad2524707f 100644 --- a/private/buf/bufprint/bufprint.go +++ b/private/buf/bufprint/bufprint.go @@ -199,28 +199,38 @@ func PrintEntity(writer io.Writer, format Format, entity Entity) error { } } -// NewLabelEntity returns a new label entity to print. -func NewLabelEntity(label *modulev1.Label, moduleFullName bufparse.FullName) Entity { +// NewLabelEntity returns a new label entity to print. It takes a label as an +// interface to allow for modulev1.Label and pluginv1beta1.Label to be passed. +func NewLabelEntity(label interface { + GetName() string + GetCommitId() string + GetCreateTime() *timestamppb.Timestamp + GetArchiveTime() *timestamppb.Timestamp +}, moduleFullName bufparse.FullName) Entity { var archiveTime *time.Time - if label.ArchiveTime != nil { - timeValue := label.ArchiveTime.AsTime() + if label.GetArchiveTime() != nil { + timeValue := label.GetArchiveTime().AsTime() archiveTime = &timeValue } return outputLabel{ - Name: label.Name, - Commit: label.CommitId, - CreateTime: label.CreateTime.AsTime(), + Name: label.GetName(), + Commit: label.GetCommitId(), + CreateTime: label.GetCreateTime().AsTime(), ArchiveTime: archiveTime, - moduleFullName: moduleFullName, + entityFullName: moduleFullName, } } -// NewCommitEntity returns a new commit entity to print. -func NewCommitEntity(commit *modulev1.Commit, moduleFullName bufparse.FullName) Entity { +// NewCommitEntity returns a new commit entity to print. It takes a commit as +// an interface to allow for modulev1.Commit and pluginv1beta1.Commit to be passed. +func NewCommitEntity(commit interface { + GetId() string + GetCreateTime() *timestamppb.Timestamp +}, moduleFullName bufparse.FullName) Entity { return outputCommit{ - Commit: commit.Id, - CreateTime: commit.CreateTime.AsTime(), - moduleFullName: moduleFullName, + Commit: commit.GetId(), + CreateTime: commit.GetCreateTime().AsTime(), + entityFullName: moduleFullName, } } @@ -434,22 +444,22 @@ type outputLabel struct { CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"` ArchiveTime *time.Time `json:"archive_time,omitempty" bufprint:"Archive Time,omitempty"` - moduleFullName bufparse.FullName + entityFullName bufparse.FullName } func (l outputLabel) fullName() string { - return fmt.Sprintf("%s:%s", l.moduleFullName.String(), l.Name) + return fmt.Sprintf("%s:%s", l.entityFullName.String(), l.Name) } type outputCommit struct { Commit string `json:"commit,omitempty" bufprint:"Commit"` CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"` - moduleFullName bufparse.FullName + entityFullName bufparse.FullName } func (c outputCommit) fullName() string { - return fmt.Sprintf("%s:%s", c.moduleFullName.String(), c.Commit) + return fmt.Sprintf("%s:%s", c.entityFullName.String(), c.Commit) } type outputModule struct { diff --git a/private/buf/cmd/buf/buf.go b/private/buf/cmd/buf/buf.go index df33dacabf..f05652382b 100644 --- a/private/buf/cmd/buf/buf.go +++ b/private/buf/cmd/buf/buf.go @@ -82,6 +82,10 @@ import ( "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationdelete" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationinfo" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationupdate" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitinfo" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitlist" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitresolve" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincreate" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugindelete" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugininfo" @@ -268,6 +272,16 @@ func NewRootCommand(name string) *appcmd.Command { Use: "plugin", Short: "Manage BSR plugins", SubCommands: []*appcmd.Command{ + { + Use: "commit", + Short: "Manage a plugin's commits", + SubCommands: []*appcmd.Command{ + plugincommitaddlabel.NewCommand("add-label", builder, ""), + plugincommitinfo.NewCommand("info", builder, ""), + plugincommitlist.NewCommand("list", builder, ""), + plugincommitresolve.NewCommand("resolve", builder, ""), + }, + }, plugincreate.NewCommand("create", builder), plugininfo.NewCommand("info", builder), plugindelete.NewCommand("delete", builder), diff --git a/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/plugincommitaddlabel.go b/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/plugincommitaddlabel.go new file mode 100644 index 0000000000..0cbd41eb2b --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/plugincommitaddlabel.go @@ -0,0 +1,149 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugincommitaddlabel + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/buf/bufprint" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/slicesext" + "github.com/bufbuild/buf/private/pkg/uuidutil" + "github.com/spf13/pflag" +) + +const ( + formatFlagName = "format" + labelsFlagName = "label" +) + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, + deprecated string, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " --label