From 3a6e960eb591b7eb1fc77469d096fe26f2d5fa8f Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Wed, 16 Sep 2026 11:29:53 +0300 Subject: [PATCH 01/14] feat(engine): grant MCP tool name authority Co-Authored-By: mecatl --- engine/CHANGELOG.md | 2 + engine/agent/dispatch.go | 11 +- engine/agent/mcp_name_availability_test.go | 69 +++++++++ engine/api/session.txt | 1 + engine/session/grant_tool_authority_test.go | 161 ++++++++++++++++++++ engine/session/principal.go | 38 +++++ engine/session/workspace_enrollment.go | 19 ++- 7 files changed, 293 insertions(+), 8 deletions(-) create mode 100644 engine/agent/mcp_name_availability_test.go create mode 100644 engine/session/grant_tool_authority_test.go diff --git a/engine/CHANGELOG.md b/engine/CHANGELOG.md index 1c480db519..a8bcaf7abf 100644 --- a/engine/CHANGELOG.md +++ b/engine/CHANGELOG.md @@ -13,6 +13,8 @@ The covered surface is the eight core packages (`session`, `governance`, `learni ### Added +- **`session.Session.GrantToolAuthority`** — stable-unions bounded, control-free tool names into an idle or completed session's existing name authority without reopening it or changing unrelated aggregate state. Added (minor). + - **`session.NoProgressNudgeText` / `session.NoProgressExtractiveNudgeText`** — exported the no-progress nudge literals that `engine/agent` authors and `session.IsGenuineUserPrompt` classifies against, so both sides reference one owned copy instead of duplicating the text (mirrors the existing `CompactionSummaryMarker`/`Tier4SummaryMarker` precedent). Added (minor). - **Event-follow capacity classification** — adds diff --git a/engine/agent/dispatch.go b/engine/agent/dispatch.go index 79eaa1c8b6..e0458ea47a 100644 --- a/engine/agent/dispatch.go +++ b/engine/agent/dispatch.go @@ -525,7 +525,7 @@ func (e *Engine) resolvePendingCall(ctx context.Context, r *Run, sess *session.S t, known := e.lookupTool(r, pendingCall.Name) e.openCard(r, turnIdx, pendingCall) if !known { - res := session.NewToolError(pendingCall.ID, fmt.Sprintf("unknown tool %q", pendingCall.Name)) + res := unavailableOrUnknownToolResult(sess, pendingCall) e.emit(r, session.Event{Type: session.EvToolResult, Turn: turnIdx, ToolResult: ptr(res)}) return res, nil, false } @@ -595,6 +595,13 @@ func (e *Engine) resolvePendingCall(ctx context.Context, r *Run, sess *session.S return e.postPreToolUse(ctx, r, sess, env, turnIdx, pre.effective, t, enqueue) } +func unavailableOrUnknownToolResult(sess *session.Session, call session.ToolCall) session.ToolResult { + if authority, bound := sess.BoundAuthority(); strings.HasPrefix(call.Name, "mcp__") && bound && authority.CapabilitySet.AllowsTool(call.Name) { + return session.NewToolError(call.ID, "tool is currently unavailable; do not retry unless the catalog changes") + } + return session.NewToolError(call.ID, fmt.Sprintf("unknown tool %q", call.Name)) +} + // runOne handles a single (mutating or unknown) tool call serially: authorize, // pre-hook, execute, post-hook. It returns the result and a cancelled flag. func (e *Engine) runOne(ctx context.Context, r *Run, sess *session.Session, env tool.Environment, turnIdx int, c session.ToolCall, t tool.Tool, known bool, enqueue time.Time) (session.ToolResult, *dispatchPark, bool) { @@ -606,7 +613,7 @@ func (e *Engine) runOne(ctx context.Context, r *Run, sess *session.Session, env // the gate" invariant). The card carries the unknown name + args so the client // can render it and then mark it failed when the error result arrives. e.openCard(r, turnIdx, c) - res := session.NewToolError(c.ID, fmt.Sprintf("unknown tool %q", c.Name)) + res := unavailableOrUnknownToolResult(sess, c) e.emit(r, session.Event{Type: session.EvToolResult, Turn: turnIdx, ToolResult: ptr(res)}) return res, nil, false } diff --git a/engine/agent/mcp_name_availability_test.go b/engine/agent/mcp_name_availability_test.go new file mode 100644 index 0000000000..3e652d25fa --- /dev/null +++ b/engine/agent/mcp_name_availability_test.go @@ -0,0 +1,69 @@ +package agent_test + +import ( + "context" + "testing" + + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/adapter/noopauthority" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/port" +) + +func TestGrantedMissingToolIsPermanentlyUnavailableWithoutDispatch(t *testing.T) { + const ( + name = "mcp__gone__tool" + want = "tool is currently unavailable; do not retry unless the catalog changes" + ) + var request port.LLMRequest + sentinel := &authorityTool{name: name} + evaluator := &recordingAuthorityEvaluator{decision: port.AuthorityDecision{Allowed: true}} + eng := newEngine(agent.Deps{ + LLM: mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(got port.LLMRequest) { + request = got + })}, mockllm.ToolCallTurn(toolCall("gone", name, `{}`)), mockllm.TextTurn("done")), + Catalog: catalogWith(t), + AuthorityEvaluator: evaluator, + }) + + events := drain(eng.Run(context.Background(), authoritySession(t, name), agent.MemEnv("/ws"), agent.RunRequest{Text: "call it"})) + if got := sentinel.ran.Load(); got != 0 { + t.Fatalf("absent granted tool executions = %d, want 0", got) + } + if _, ok := specByName(request.Tools, name); ok { + t.Fatalf("absent granted tool %q was advertised", name) + } + if got := evaluator.calls(); got != 0 { + t.Fatalf("authority evaluator calls = %d, want 0 because no dispatch gate may run", got) + } + for _, event := range events { + if event.ToolResult != nil && event.ToolResult.CallID == "gone" { + if !event.ToolResult.IsError || event.ToolResult.Content != want { + t.Fatalf("missing granted result = {error:%v content:%q}, want exact permanent unavailable error", event.ToolResult.IsError, event.ToolResult.Content) + } + return + } + } + t.Fatal("missing unavailable tool result") +} + +func TestUngrantedMissingToolRetainsUnknownBehavior(t *testing.T) { + const name = "mcp__never_granted__tool" + eng := newEngine(agent.Deps{ + LLM: mockllm.New(mockllm.ToolCallTurn(toolCall("unknown", name, `{}`)), mockllm.TextTurn("done")), + Catalog: catalogWith(t), + AuthorityEvaluator: noopauthority.New(), + }) + + events := drain(eng.Run(context.Background(), authoritySession(t, "Read"), agent.MemEnv("/ws"), agent.RunRequest{Text: "call it"})) + want := `unknown tool "` + name + `"` + for _, event := range events { + if event.ToolResult != nil && event.ToolResult.CallID == "unknown" { + if !event.ToolResult.IsError || event.ToolResult.Content != want { + t.Fatalf("ungranted missing result = {error:%v content:%q}, want %q", event.ToolResult.IsError, event.ToolResult.Content, want) + } + return + } + } + t.Fatal("missing unknown tool result") +} diff --git a/engine/api/session.txt b/engine/api/session.txt index 9e601890d7..69e758fc96 100644 --- a/engine/api/session.txt +++ b/engine/api/session.txt @@ -20,6 +20,7 @@ method func (*Session).FailedStepRetryPending() (RetryDisposition, StreamProgress, bool) method func (*Session).FailureMetadata() (RetryDisposition, StreamProgress) method func (*Session).FailurePermanence() bool + method func (*Session).GrantToolAuthority(names []string) error method func (*Session).Incarnation() IncarnationID method func (*Session).Interrupt() error method func (*Session).InterruptAuthorization() ([]ToolResult, error) diff --git a/engine/session/grant_tool_authority_test.go b/engine/session/grant_tool_authority_test.go new file mode 100644 index 0000000000..92afb65510 --- /dev/null +++ b/engine/session/grant_tool_authority_test.go @@ -0,0 +1,161 @@ +package session + +import ( + "reflect" + "strings" + "testing" + "time" + + "github.com/stacklok/mecatl/engine/governance" +) + +func grantAuthoritySession(t *testing.T) *Session { + t.Helper() + s := New("grant-authority", ModeDefault, EnvironmentRef{Kind: EnvKindLocal, ID: "workspace", Revision: "r1"}, Limits{MaxTurns: 9, MaxToolCalls: 8}, time.Unix(10, 0).UTC()) + s.Owner = &Principal{Issuer: "issuer", Subject: "owner", Name: "Owner", GrantType: GrantTypeUser} + if err := s.BindAuthority(Authority{ + CapabilitySet: governance.CapabilitySet{ + Tools: []string{"legacy/tool name", "Read"}, + RemainingDelegationDepth: 3, + FileSystem: true, + DirectWrite: true, + }, + Provenance: "configured:test", + DefinitionIdentity: "agent:test", + }); err != nil { + t.Fatalf("BindAuthority: %v", err) + } + s.Conversation.Append(NewUserMessage("preserve history")) + s.Counters = Counters{Turns: 4, ToolCalls: 5} + s.Usage = Usage{InputTokens: 6, OutputTokens: 7} + return s +} + +func TestADR_0345_GrantToolAuthorityPreservesAggregateState(t *testing.T) { + t.Run("duplicate stable union and input cloned", func(t *testing.T) { + s := grantAuthoritySession(t) + before := *s + input := []string{"Read", "mcp__one__first", "mcp__one__first", "mcp__two__工具"} + if err := s.GrantToolAuthority(input); err != nil { + t.Fatalf("GrantToolAuthority: %v", err) + } + input[1] = "mutated" + got, bound := s.BoundAuthority() + if !bound { + t.Fatal("authority became unbound") + } + want := []string{"legacy/tool name", "Read", "mcp__one__first", "mcp__two__工具"} + if !reflect.DeepEqual(got.CapabilitySet.Tools, want) { + t.Fatalf("tools = %q, want stable union %q", got.CapabilitySet.Tools, want) + } + if got.CapabilitySet.RemainingDelegationDepth != 3 || !got.CapabilitySet.FileSystem || !got.CapabilitySet.DirectWrite || got.Provenance != "configured:test" || got.DefinitionIdentity != "agent:test" { + t.Fatalf("unrelated authority changed: %+v", got) + } + afterWithoutAuthority := *s + afterWithoutAuthority.Authority = before.Authority + if !reflect.DeepEqual(afterWithoutAuthority, before) { + t.Fatalf("non-authority aggregate state changed\nbefore: %#v\nafter: %#v", before, afterWithoutAuthority) + } + }) + + t.Run("exact 256 byte boundary", func(t *testing.T) { + s := grantAuthoritySession(t) + exact := strings.Repeat("é", 128) + if err := s.GrantToolAuthority([]string{exact}); err != nil { + t.Fatalf("256-byte UTF-8 name rejected: %v", err) + } + got, _ := s.BoundAuthority() + if !got.CapabilitySet.AllowsTool(exact) { + t.Fatal("256-byte name was not granted") + } + }) + + for _, tc := range []struct { + name string + names []string + }{ + {"empty", []string{"ok", ""}}, + {"invalid UTF-8", []string{"ok", string([]byte{0xff})}}, + {"ASCII control", []string{"ok", "bad\nname"}}, + {"Unicode control", []string{"ok", "bad\u0085name"}}, + {"over 256 bytes", []string{"ok", strings.Repeat("x", 257)}}, + } { + t.Run("invalid batch atomic/"+tc.name, func(t *testing.T) { + s := grantAuthoritySession(t) + before := *s + beforeAuthority := s.Authority.Clone() + if err := s.GrantToolAuthority(tc.names); err == nil { + t.Fatal("GrantToolAuthority accepted invalid batch") + } + if !reflect.DeepEqual(s.Authority, beforeAuthority) { + t.Fatalf("rejected batch mutated authority: %+v", s.Authority) + } + if !reflect.DeepEqual(*s, before) { + t.Fatal("rejected batch mutated aggregate") + } + }) + } + + t.Run("unbound rejected", func(t *testing.T) { + s := New("unbound", ModeDefault, EnvironmentRef{Kind: EnvKindLocal, ID: "workspace", Revision: "r1"}, Limits{}, time.Unix(10, 0).UTC()) + before := *s + if err := s.GrantToolAuthority([]string{"new"}); err == nil { + t.Fatal("GrantToolAuthority accepted an unbound session") + } + if !reflect.DeepEqual(*s, before) { + t.Fatal("unbound rejection mutated aggregate") + } + }) + + t.Run("completed remains completed", func(t *testing.T) { + s := grantAuthoritySession(t) + s.State = StateCompleted + if err := s.GrantToolAuthority([]string{"new"}); err != nil { + t.Fatalf("GrantToolAuthority from completed: %v", err) + } + if s.State != StateCompleted { + t.Fatalf("state = %q, want completed", s.State) + } + }) + + for _, state := range []State{StateRunning, StateAwaiting, StateAuthorizing, StateFailed, StateCancelled} { + t.Run("state rejected/"+string(state), func(t *testing.T) { + s := grantAuthoritySession(t) + s.State = state + before := s.Authority.Clone() + if err := s.GrantToolAuthority([]string{"new"}); err == nil { + t.Fatalf("GrantToolAuthority accepted state %q", state) + } + if s.State != state || !reflect.DeepEqual(s.Authority, before) { + t.Fatal("state rejection mutated aggregate") + } + }) + } + + t.Run("pending control rejected in idle and completed", func(t *testing.T) { + controls := []struct { + name string + set func(*Session) + }{ + {"permission", func(s *Session) { s.pending = &PendingAsk{AskID: "pending"} }}, + {"authorization", func(s *Session) { s.pendingAuthorization = &PendingAuthorization{} }}, + {"workspace enrollment", func(s *Session) { s.pendingWorkspaceEnrollment = &PendingWorkspaceEnrollment{ID: "pending"} }}, + } + for _, control := range controls { + for _, state := range []State{StateIdle, StateCompleted} { + t.Run(control.name+"/"+string(state), func(t *testing.T) { + s := grantAuthoritySession(t) + s.State = state + control.set(s) + before := s.Authority.Clone() + if err := s.GrantToolAuthority([]string{"new"}); err == nil { + t.Fatalf("GrantToolAuthority accepted pending control in %q", state) + } + if s.State != state || !reflect.DeepEqual(s.Authority, before) { + t.Fatal("pending-control rejection mutated aggregate") + } + }) + } + } + }) +} diff --git a/engine/session/principal.go b/engine/session/principal.go index eae70e1b79..55d4a9dcdc 100644 --- a/engine/session/principal.go +++ b/engine/session/principal.go @@ -292,3 +292,41 @@ func (s *Session) BoundAuthority() (Authority, bool) { } return s.Authority.Clone(), true } + +// GrantToolAuthority adds valid tool names to an already-bound authority while +// preserving their existing order and every other aggregate field. +func (s *Session) GrantToolAuthority(names []string) error { + if s.State != StateIdle && s.State != StateCompleted { + return fmt.Errorf("%w: GrantToolAuthority from %q", ErrIllegalTransition, s.State) + } + if s.pending != nil || s.pendingAuthorization != nil || s.pendingWorkspaceEnrollment != nil { + return errors.New("session: cannot grant tool authority while a control is pending") + } + if !s.authorityBound { + return errors.New("session: tool authority is not bound") + } + + seen := make(map[string]struct{}, len(s.Authority.CapabilitySet.Tools)+len(names)) + for _, name := range s.Authority.CapabilitySet.Tools { + seen[name] = struct{}{} + } + additions := make([]string, 0, len(names)) + for _, name := range names { + if _, ok := seen[name]; ok { + continue + } + if !validToolAuthorityName(name) { + return errors.New("session: invalid tool authority name") + } + seen[name] = struct{}{} + additions = append(additions, name) + } + if len(additions) == 0 { + return nil + } + tools := make([]string, 0, len(s.Authority.CapabilitySet.Tools)+len(additions)) + tools = append(tools, s.Authority.CapabilitySet.Tools...) + tools = append(tools, additions...) + s.Authority.CapabilitySet.Tools = tools + return nil +} diff --git a/engine/session/workspace_enrollment.go b/engine/session/workspace_enrollment.go index 453ab58573..252eb32fb7 100644 --- a/engine/session/workspace_enrollment.go +++ b/engine/session/workspace_enrollment.go @@ -79,6 +79,18 @@ func (s *Session) PendingWorkspaceEnrollment() (PendingWorkspaceEnrollment, bool return *s.pendingWorkspaceEnrollment, true } +func validToolAuthorityName(name string) bool { + if name == "" || len(name) > maxWorkspaceEnrollmentToolNameBytes || !utf8.ValidString(name) { + return false + } + for _, r := range name { + if unicode.IsControl(r) { + return false + } + } + return true +} + // ValidWorkspaceEnrollmentToolNames reports whether names is an exact, // duplicate-free enrollment tool set. Names are opaque catalogue identifiers: // the boundary imposes only framing and size safety, not a provider-specific @@ -90,14 +102,9 @@ func ValidWorkspaceEnrollmentToolNames(names []string) bool { seen := make(map[string]struct{}, len(names)) totalBytes := 0 for _, name := range names { - if name == "" || len(name) > maxWorkspaceEnrollmentToolNameBytes || !utf8.ValidString(name) { + if !validToolAuthorityName(name) { return false } - for _, r := range name { - if unicode.IsControl(r) { - return false - } - } if _, duplicate := seen[name]; duplicate { return false } From 33a2e872dd5bf5175ea87e8b10f7e10f81650952 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Wed, 16 Sep 2026 12:44:46 +0300 Subject: [PATCH 02/14] feat(mcp): reconcile ordered MCP sources Co-Authored-By: mecatl --- docs/adr/0027-cloud-native.md | 3 +- docs/design/IMPLEMENTATION-NOTES.md | 20 + internal/adapter/mcp/candidate_budget_test.go | 38 ++ internal/adapter/mcp/mcp.go | 256 ++++++++- internal/adapter/mcp/prompt.go | 30 ++ internal/adapter/mcp/resource.go | 30 ++ internal/adapter/mcp/source/toolhive.go | 27 +- internal/adapter/mcp/source/toolhive_test.go | 28 +- internal/app/build.go | 55 +- internal/app/mcp_reconciler.go | 501 ++++++++++++++++++ internal/app/mcp_reconciler_test.go | 337 ++++++++++++ 11 files changed, 1258 insertions(+), 67 deletions(-) create mode 100644 internal/adapter/mcp/candidate_budget_test.go create mode 100644 internal/app/mcp_reconciler.go create mode 100644 internal/app/mcp_reconciler_test.go diff --git a/docs/adr/0027-cloud-native.md b/docs/adr/0027-cloud-native.md index 057c7176b0..19f8f5c070 100644 --- a/docs/adr/0027-cloud-native.md +++ b/docs/adr/0027-cloud-native.md @@ -799,7 +799,8 @@ durable artifact survives and is reloaded), or **lost** (gone, possibly leaking) | 61 | Provider OIDC issuer and gateway HTTP clients | `internal/cliconfig.NativeEndpointRuntime` | process, one pair per provider runtime | clients have no independent goroutine; their transports die with the runtime/loader | reconstructible from explicit issuer/gateway trust policies and CA bundles; neither trust root is reused for the other | `internal/cliconfig/native_endpoint.go` (`OpenNativeEndpointRuntime`, `nativeTrustClient`) | | 62 | Provider OIDC keyring and encrypted Store handles | `internal/cliconfig.NativeEndpointRuntime` | operation handles; serving Store handles live for the runtime | Login/status/logout defer Store close; `Source` handles close at runtime/loader close | reopened only from explicit `credential_store.oidc.home` and provider identity; no discovery, migration, plaintext, or environment fallback | `internal/cliconfig/native_endpoint.go` (`open`, `Login`, `Status`, `Logout`, `Close`); `internal/adapter/llmendpoint/lifecycle.go` (`NewProtectedStore`) | | 63 | Provider OIDC transaction-lock handles | `llmendpoint.TransactionLocker` | one provider lifecycle operation | `With` releases its owner-only flock after the callback; no lock is retained across gateway requests | reset/reacquired after restart from the hashed provider identity; the durable record remains the source of truth | `internal/adapter/llmendpoint/lifecycle.go` (`TransactionLocker`, `With`) | -| 1 | Global MCP manager (`globalMgr`) | `app.Build` | process | `mcpClose` in Build's `closeAll`; NEVER folded into per-session close (`build.go:980`) | reconstructible (reconnects from config at next Build) | `internal/app/build.go:1868` (`connectMCP`) | +| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, and current complete candidate | `app.Build` through `connectMCP` | process | the Build close fold invokes `mcpSourceReconciler.Close`, which rejects new requests, cancels and joins the worker, then closes the current manager; caller cancellation only stops that caller's wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects a complete candidate, and begins with no source LKG or pending invalidation; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `Close`); `internal/app/build.go` (`connectMCP`) | +| 1 | Global MCP manager (`globalMgr`) | `app.Build` | process | owned as the reconciler's current candidate and closed by its joined Build close; NEVER folded into per-session close | reconstructible (reconnects from ordered sources at next Build) | `internal/app/mcp_reconciler.go` (`mcpReconcileCandidate`); `internal/app/build.go` (`connectMCP`) | | 2 | Per-session client MCP managers and their original `Service.clientMCPSpecs` mount declarations | `sessionEngineFactory` / `Service` | session / process-local map | per-session close func, invoked by `Service.CloseSession` (`service.go:743`) and shutdown. **Two callers now reach this** (issue #821, Scenario 9): the ACP adapter, which calls `CloseSession` on editor disconnect, and the gRPC/HTTP `CreateSession` wire path, whose teardown is the precondition-checked `EndSession` (same teardown) or `Service.Close`. `CloseSession`, failed-create rollback, and `Service.Close` remove the corresponding `clientMCPSpecs` entry; an engine-rebuild failure deliberately retains it because the surviving session can retry/remount the same client tools. The wire caller is a client that may simply go away without ending its session, so a mounted manager can outlive its last use until process shutdown — bounded by `MaxSessionEngines` (which fails a create at the cap rather than growing without limit), not by a reaper. That residual is the same one every per-session engine has, and it is why the field is deployment-gated to a UNIX-socket-only daemon rather than exposed to an anonymous network caller. A create REFUSED for an unreachable server does not add to it: `verifyClientMCPMounted` runs before any id is minted and invokes the same `closeFn` every other rejection in `createPerSessionEngine` does, so the partially-connected manager is torn down on that path rather than left registered against a session that does not exist | **reset/remount by design:** client specs, including secret-shaped headers, are never persisted. A restart drops `clientMCPSpecs` and every client manager; the client explicitly re-mounts via `LoadSessionWithMCP`, `service.go:968`, or creates a new session with `mcp_servers`. Within one Service lifetime, a rebuild reuses the retained original declaration. | `internal/app/build.go:962`; `internal/adapter/server/service.go` (`clientMCPSpecs`, `ClientMCPFromWire`, `WithClientMCP`) | | 3 | Preserved-fork LRU (`LRUForkReaper`) — Parallel ONLY | `app.Build` (shared via `catalogAssets`, built only when Parallel is enabled) | process | LRU eviction runs each entry's cleanup (dir removal) outside the lock; graceful app shutdown calls `Built.Close`, which drains retained entries and eviction cleanups already detached before closure outside the lock | registry lost; the preserved fork DIRS remain on disk un-tracked (a leak on crash) | `engine/agent/forkreaper.go:41,64`; built at `internal/app/build.go:4895`. NOTE: the writable Subagent (`mode:"read-write"`) no longer creates a per-call fork dir — it writes the parent workspace directly (ADR 0077), so it contributes no fork dirs here; the shared `autoMerger` (`forker.SerializingMerger`) is likewise Parallel-only now | | 4 | Project memory store (flock pair: `memory.json` + `memory.lock`) | `app.Build` | process handle, per-directory data | flock held per-operation only; one `*Store` per dir per process. Current entries, revision history, and tombstones share ONE locked atomic document — no split-file transaction | persisted (data/history on disk; legacy entries lazily materialize on first mutation; handle rebuilt at next Build) | `internal/app/build.go`; `internal/adapter/memory/store.go` (`Store`, `withExclusiveLock`, `materializeLegacy`) | diff --git a/docs/design/IMPLEMENTATION-NOTES.md b/docs/design/IMPLEMENTATION-NOTES.md index 484f45ba91..08e4484e75 100644 --- a/docs/design/IMPLEMENTATION-NOTES.md +++ b/docs/design/IMPLEMENTATION-NOTES.md @@ -5987,6 +5987,26 @@ without affinity or a durable-broker decision. Guards include `internal/adapter/ `internal/adapter/mcpbroker/workspace_catalogue_test.go`, and `internal/adapter/mcpbroker/toolhive_process_test.go`. +**Ordered direct MCP source reconciliation (ADR 0345, Task 02):** +`internal/app/mcp_reconciler.go` (`mcpSourceReconciler`) is the one Build-owned, +serialized/coalesced path for initial resolution, manual requests, current-server +list-change notifications, and ToolHive-only bounded jittered polling. It consults +the existing static-before-ToolHive source order once per cycle, retains each +failed source's last-known-good snapshot, and treats a successful empty snapshot +as withdrawal. Stable, non-dirty observations stop before candidate connection. +A dirty current-runtime notification rebuilds a complete candidate and therefore +re-lists tools, resources, and prompts together; callbacks from displaced +candidate generations are ignored. `internal/adapter/mcp/mcp.go` +(`NewCompleteManager`) connects and lists all desired servers all-or-nothing, +using one candidate-wide page/byte/cardinality budget and no OAuth presenter. +Candidate equality covers source/server configuration and bounded tool, +resource, and prompt metadata. Build shutdown rejects new waits, cancels and +joins the worker, then closes its current candidate. Caller cancellation only +abandons that caller's wait. The current `connectMCP` publication bridge accepts +the initial candidate and safely closes/discards later changed candidates while +retaining the manager borrowed by existing catalogs; immutable runtime +publication, revision pins, and retirement replace that bridge in Task 03. + **Server-global MCP on every session (bug #3 fix, `sessionEngineFactory`):** the per-session catalog mounts the SERVER-GLOBAL MCP tools (`cfg.MCPServers` + ToolHive — the same tools the build-time `buildCatalog`→`connectMCP`+`assembleCatalog` path mounts on the main engine), NOT just core + client diff --git a/internal/adapter/mcp/candidate_budget_test.go b/internal/adapter/mcp/candidate_budget_test.go new file mode 100644 index 0000000000..654e6244bb --- /dev/null +++ b/internal/adapter/mcp/candidate_budget_test.go @@ -0,0 +1,38 @@ +package mcp + +import ( + "strings" + "testing" +) + +func TestCandidateListBudgetBoundsInputBeforePublication(t *testing.T) { + budget := NewCandidateListBudget(2, 2, 4) + if err := budget.consumePage(2); err != nil { + t.Fatalf("entry boundary: %v", err) + } + if err := budget.consumePage(0); err != nil { + t.Fatalf("page boundary: %v", err) + } + if err := budget.consumePage(0); err == nil { + t.Fatal("page over-bound accepted") + } + + buf := make([]byte, 8) + n, err := budget.readResponse(strings.NewReader("12345"), buf) + if err == nil || n != 0 || !strings.Contains(err.Error(), "bytes exceed") { + t.Fatalf("byte over-bound read = (%d, %v)", n, err) + } + _, pages, bytes := budget.Stats() + if pages != 2 || bytes != 0 { + t.Fatalf("failed input changed counters: pages=%d bytes=%d", pages, bytes) + } + + budget.Seal() + n, err = budget.readResponse(strings.NewReader("12345"), buf) + if err != nil { + t.Fatalf("sealed runtime read: %v", err) + } + if n != 5 { + t.Fatalf("sealed runtime read bytes = %d, want 5", n) + } +} diff --git a/internal/adapter/mcp/mcp.go b/internal/adapter/mcp/mcp.go index 9064963826..846c7281bf 100644 --- a/internal/adapter/mcp/mcp.go +++ b/internal/adapter/mcp/mcp.go @@ -30,6 +30,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net" "net/http" "net/url" @@ -63,6 +64,91 @@ const ( clientVersion = "v0" ) +// CandidateListBudget bounds aggregate list ingestion across every server in one +// all-or-nothing reconciliation candidate. A single shared value is attached to +// every candidate ServerConfig so pages, bytes, and entries cannot multiply by +// server count. +type CandidateListBudget struct { + mu sync.Mutex + maxEntries int + maxPages int + maxBytes int + entries int + pages int + bytes int + sealed bool +} + +// NewCandidateListBudget creates one candidate-wide list budget. +func NewCandidateListBudget(maxEntries, maxPages, maxBytes int) *CandidateListBudget { + return &CandidateListBudget{maxEntries: maxEntries, maxPages: maxPages, maxBytes: maxBytes} +} + +func (b *CandidateListBudget) consumePage(entries int) error { + if b == nil { + return nil + } + b.mu.Lock() + defer b.mu.Unlock() + if b.entries+entries > b.maxEntries { + return fmt.Errorf("mcp: active list entries exceed limit %d", b.maxEntries) + } + if b.pages+1 > b.maxPages { + return fmt.Errorf("mcp: candidate list pages exceed limit %d", b.maxPages) + } + b.entries += entries + b.pages++ + return nil +} + +func (b *CandidateListBudget) readResponse(body io.Reader, p []byte) (int, error) { + b.mu.Lock() + if b.sealed { + b.mu.Unlock() + return body.Read(p) + } + remaining := b.maxBytes - b.bytes + b.mu.Unlock() + if remaining <= 0 { + return 0, fmt.Errorf("mcp: candidate response bytes exceed limit %d", b.maxBytes) + } + if len(p) > remaining+1 { + p = p[:remaining+1] + } + n, err := body.Read(p) + b.mu.Lock() + defer b.mu.Unlock() + if b.sealed { + return n, err + } + if b.bytes+n > b.maxBytes { + return 0, fmt.Errorf("mcp: candidate response bytes exceed limit %d", b.maxBytes) + } + b.bytes += n + return n, err +} + +// Seal ends construction-time response accounting. The retained runtime may +// then serve ordinary calls without spending its one-time candidate budget. +func (b *CandidateListBudget) Seal() { + if b == nil { + return + } + b.mu.Lock() + b.sealed = true + b.mu.Unlock() +} + +// Stats returns the successfully consumed aggregate counts. +func (b *CandidateListBudget) Stats() (entries, pages, bytes int) { + if b == nil { + return 0, 0, 0 + } + b.mu.Lock() + defer b.mu.Unlock() + return b.entries, b.pages, b.bytes +} + // ServerConfig describes a single remote MCP server to connect to over the // Streamable HTTP transport. type ServerConfig struct { @@ -93,6 +179,13 @@ type ServerConfig struct { // operator-configured servers, so the operator path keeps Go's default // behaviour byte-for-byte. See newMCPHTTPClient for why the two differ. NoRedirects bool + // ListChanged is an optional non-blocking invalidation callback for the + // Build-owned direct-source reconciler. Notification handlers invoke it after + // marking adapter-local state dirty; it must not perform network work. + ListChanged func() + // CandidateBudget is set only for complete reconciliation candidates. It is + // shared by every server in that candidate and bounds aggregate list input. + CandidateBudget *CandidateListBudget } // ValidateClientURL validates a CLIENT-PROVIDED Streamable HTTP MCP endpoint @@ -543,6 +636,41 @@ func prepareOAuthServerConfig(ctx context.Context, cfg ServerConfig) (ServerConf return cfg, controller, err } +type candidateBudgetRoundTripper struct { + base http.RoundTripper + budget *CandidateListBudget +} + +func (t candidateBudgetRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + res, err := t.base.RoundTrip(req) + if err != nil || res == nil || res.Body == nil { + return res, err + } + res.Body = &candidateBudgetBody{ReadCloser: res.Body, budget: t.budget} + return res, nil +} + +type candidateBudgetBody struct { + io.ReadCloser + budget *CandidateListBudget +} + +func (b *candidateBudgetBody) Read(p []byte) (int, error) { + return b.budget.readResponse(b.ReadCloser, p) +} + +func withCandidateBudget(client *http.Client, budget *CandidateListBudget) *http.Client { + if budget == nil { + return client + } + base := client.Transport + if base == nil { + base = http.DefaultTransport + } + client.Transport = candidateBudgetRoundTripper{base: base, budget: budget} + return client +} + func newMCPHTTPClient(cfg ServerConfig, oauth *OAuthController) *http.Client { client := &http.Client{} if cfg.HTTPClient != nil { @@ -584,7 +712,7 @@ func newMCPHTTPClient(cfg ServerConfig, oauth *OAuthController) *http.Client { client.Transport = &bearerRoundTripper{base: client.Transport, origin: origin, source: cfg.TokenSource} } if len(cfg.Headers) == 0 { - return client + return withCandidateBudget(client, cfg.CandidateBudget) } base := client.Transport if base == nil { @@ -599,7 +727,7 @@ func newMCPHTTPClient(cfg ServerConfig, oauth *OAuthController) *http.Client { origin = requestOrigin(parsed) } client.Transport = &headerRoundTripper{base: base, headers: headers, origin: origin} - return client + return withCandidateBudget(client, cfg.CandidateBudget) } // Connect establishes a Streamable HTTP session to the configured MCP server, @@ -622,11 +750,19 @@ func Connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Ser // The alternative — asking each consumer to call RedactError — was tried and // demonstrably does not hold: of three NewManager callers, one logged the raw // error and the raw URL, and the audit that was supposed to find it missed it. - srv, err := connect(ctx, cfg, diag) + srv, err := connect(ctx, cfg, diag, false) + return srv, RedactErrorValue(err) +} + +// ConnectComplete is the reconciliation candidate variant of Connect. It +// requires every capability advertised by the server to list successfully, so a +// candidate can never publish a partial tool/resource/prompt snapshot. +func ConnectComplete(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Server, error) { + srv, err := connect(ctx, cfg, diag, true) return srv, RedactErrorValue(err) } -func connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Server, error) { +func connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics, requireComplete bool) (*Server, error) { // Wrap the sink so no log line from this package — nor from the *Server it // builds, which inherits this diag — can carry a credential-bearing URL. See // redactingDiagnostics for why this is a sink decoration rather than a fix at @@ -677,7 +813,12 @@ func connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Ser } srv.session = sess - tools, err := listTools(connectCtx, cfg.Name, srv, sess) + var tools []tool.Tool + if requireComplete { + tools, err = listToolsBounded(connectCtx, cfg.Name, srv, sess, cfg.CandidateBudget) + } else { + tools, err = listTools(connectCtx, cfg.Name, srv, sess) + } if err != nil { _ = sess.Close() _ = oauthController.Close() @@ -694,7 +835,19 @@ func connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Ser // tools are already usable. caps := serverCapabilities(sess) if caps != nil && caps.Resources != nil { - if res, rerr := srv.listResources(connectCtx); rerr != nil { + var res []Resource + var rerr error + if requireComplete { + res, rerr = srv.listResourcesBounded(connectCtx, sess, cfg.CandidateBudget) + } else { + res, rerr = srv.listResources(connectCtx) + } + if rerr != nil { + if requireComplete { + _ = sess.Close() + _ = oauthController.Close() + return nil, fmt.Errorf("mcp: list resources on server %q: %w", cfg.Name, rerr) + } diag.Log(connectCtx, port.LevelWarn, "mcp: listing resources failed; continuing without them", "server", cfg.Name, "err", rerr) } else { @@ -702,7 +855,19 @@ func connect(ctx context.Context, cfg ServerConfig, diag port.Diagnostics) (*Ser } } if caps != nil && caps.Prompts != nil { - if pr, perr := srv.listPrompts(connectCtx); perr != nil { + var pr []Prompt + var perr error + if requireComplete { + pr, perr = srv.listPromptsBounded(connectCtx, sess, cfg.CandidateBudget) + } else { + pr, perr = srv.listPrompts(connectCtx) + } + if perr != nil { + if requireComplete { + _ = sess.Close() + _ = oauthController.Close() + return nil, fmt.Errorf("mcp: list prompts on server %q: %w", cfg.Name, perr) + } diag.Log(connectCtx, port.LevelWarn, "mcp: listing prompts failed; continuing without them", "server", cfg.Name, "err", perr) } else { @@ -798,6 +963,39 @@ func listTools(ctx context.Context, serverName string, srv *Server, sess *mcpsdk return tools, nil } +func listToolsBounded(ctx context.Context, serverName string, srv *Server, sess *mcpsdk.ClientSession, budget *CandidateListBudget) ([]tool.Tool, error) { + var out []tool.Tool + cursor := "" + seen := make(map[string]struct{}) + for { + page, err := sess.ListTools(ctx, &mcpsdk.ListToolsParams{Cursor: cursor}) + if err != nil { + return nil, err + } + if page == nil { + return nil, errors.New("mcp: nil tools list page") + } + if err := budget.consumePage(len(page.Tools)); err != nil { + return nil, err + } + for _, remote := range page.Tools { + wrapped, err := newRemoteTool(serverName, srv, remote) + if err != nil { + return nil, err + } + out = append(out, wrapped) + } + if page.NextCursor == "" { + return out, nil + } + if _, duplicate := seen[page.NextCursor]; duplicate { + return nil, errors.New("mcp: tools list cursor cycle") + } + seen[page.NextCursor] = struct{}{} + cursor = page.NextCursor + } +} + // HasOAuthCredential reports whether this connected OAuth server restored or // durably stored a credential. It exposes readiness only and never reads or // returns token data. @@ -893,6 +1091,9 @@ func (s *Server) handleListChanged(ctx context.Context, list string) { s.promptsGen++ } s.mu.Unlock() + if s.cfg.ListChanged != nil { + s.cfg.ListChanged() + } if !already { s.diag.Log(ctx, port.LevelWarn, "mcp server list changed", "server", s.name, "list", list) } @@ -1170,6 +1371,47 @@ func NewManager(ctx context.Context, configs []ServerConfig, onError func(cfg Se return m, nil } +// NewCompleteManager constructs an all-or-nothing reconciliation candidate. +// Unlike NewManager's startup-compatible fail-soft behavior, one failed server +// closes every successfully-created peer and rejects the complete candidate. +func NewCompleteManager(ctx context.Context, configs []ServerConfig, diag port.Diagnostics) (*Manager, error) { + diag = redactDiagnostics(diag) + m := &Manager{} + if len(configs) == 0 { + return m, nil + } + type result struct { + srv *Server + err error + } + results := make([]result, len(configs)) + sem := make(chan struct{}, maxConnectConcurrency) + var wg sync.WaitGroup + for i, cfg := range configs { + wg.Add(1) + go func(i int, cfg ServerConfig) { + defer wg.Done() + sem <- struct{}{} + defer func() { <-sem }() + results[i].srv, results[i].err = ConnectComplete(ctx, cfg, diag) + }(i, cfg) + } + wg.Wait() + var candidateErr error + for i, result := range results { + if result.err != nil { + candidateErr = errors.Join(candidateErr, fmt.Errorf("mcp: candidate server %q: %w", configs[i].Name, result.err)) + continue + } + m.servers = append(m.servers, result.srv) + } + if candidateErr != nil { + _ = m.Close() + return nil, RedactErrorValue(candidateErr) + } + return m, nil +} + // safeCallbackConfig returns cfg with its two credential-bearing fields made safe // for an error callback to log: the URL redacted, the headers dropped. Every other // field is preserved verbatim. diff --git a/internal/adapter/mcp/prompt.go b/internal/adapter/mcp/prompt.go index ef00ba44e8..95455b763c 100644 --- a/internal/adapter/mcp/prompt.go +++ b/internal/adapter/mcp/prompt.go @@ -2,6 +2,7 @@ package mcp import ( "context" + "errors" "fmt" "strings" @@ -122,6 +123,35 @@ func (s *Server) listPrompts(ctx context.Context) ([]Prompt, error) { return out, nil } +func (s *Server) listPromptsBounded(ctx context.Context, sess *mcpsdk.ClientSession, budget *CandidateListBudget) ([]Prompt, error) { + var out []Prompt + cursor := "" + seen := make(map[string]struct{}) + for { + page, err := sess.ListPrompts(ctx, &mcpsdk.ListPromptsParams{Cursor: cursor}) + if err != nil { + return nil, err + } + if page == nil { + return nil, errors.New("mcp: nil prompts list page") + } + if err := budget.consumePage(len(page.Prompts)); err != nil { + return nil, err + } + for _, prompt := range page.Prompts { + out = append(out, promptFromSDK(s.name, prompt)) + } + if page.NextCursor == "" { + return out, nil + } + if _, duplicate := seen[page.NextCursor]; duplicate { + return nil, errors.New("mcp: prompts list cursor cycle") + } + seen[page.NextCursor] = struct{}{} + cursor = page.NextCursor + } +} + // getPrompt expands a named prompt with the given arguments and returns the // translated result. The GetPrompt call rides through withSession so a dropped // session is re-established transparently (one bounded reconnect). diff --git a/internal/adapter/mcp/resource.go b/internal/adapter/mcp/resource.go index dfb23a85da..8e70930504 100644 --- a/internal/adapter/mcp/resource.go +++ b/internal/adapter/mcp/resource.go @@ -2,6 +2,7 @@ package mcp import ( "context" + "errors" "fmt" mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" @@ -112,6 +113,35 @@ func (s *Server) listResources(ctx context.Context) ([]Resource, error) { return out, nil } +func (s *Server) listResourcesBounded(ctx context.Context, sess *mcpsdk.ClientSession, budget *CandidateListBudget) ([]Resource, error) { + var out []Resource + cursor := "" + seen := make(map[string]struct{}) + for { + page, err := sess.ListResources(ctx, &mcpsdk.ListResourcesParams{Cursor: cursor}) + if err != nil { + return nil, err + } + if page == nil { + return nil, errors.New("mcp: nil resources list page") + } + if err := budget.consumePage(len(page.Resources)); err != nil { + return nil, err + } + for _, resource := range page.Resources { + out = append(out, resourceFromSDK(s.name, resource)) + } + if page.NextCursor == "" { + return out, nil + } + if _, duplicate := seen[page.NextCursor]; duplicate { + return nil, errors.New("mcp: resources list cursor cycle") + } + seen[page.NextCursor] = struct{}{} + cursor = page.NextCursor + } +} + // readResource fetches a single resource by URI and returns its (translated) // content chunks. The caller decides how to render them (flattenResourceContents // for the model-facing tool). The ReadResource call rides through withSession so diff --git a/internal/adapter/mcp/source/toolhive.go b/internal/adapter/mcp/source/toolhive.go index 58be281d98..dc28213ea6 100644 --- a/internal/adapter/mcp/source/toolhive.go +++ b/internal/adapter/mcp/source/toolhive.go @@ -47,10 +47,10 @@ type workloadLister interface { // ToolHiveSource discovers MCP servers from the running ToolHive workloads in a // group, reading each workload's already-populated HTTP proxy URL. Construction of -// the underlying ToolHive manager is LAZY (first Servers call) and ERROR-GUARDED: -// if no container runtime is reachable the source degrades to zero servers plus a -// single diagnostic, NOT a fatal error, so a developer without Podman/Docker can -// still run the harness. +// the underlying ToolHive manager is lazy (first Servers call). Runtime/listing +// infrastructure failures are returned as consultation errors so reconciliation +// can retain the source's last-known-good snapshot; a successful empty list is +// therefore distinguishable and authoritative. type ToolHiveSource struct { // group is the ToolHive group to filter workloads to. Empty means the // effective "default" group. @@ -95,11 +95,10 @@ func (s ToolHiveSource) Name() string { // Servers lists the running ToolHive workloads in the configured group and maps // each streamable-http workload to an mcp.ServerConfig. // -// Fail-soft contract: +// Consultation contract: // - If the ToolHive manager cannot be constructed or the list call fails (no -// container runtime), return (nil, [one diagnostic], nil) — a degraded but -// non-fatal state. The harness keeps running with whatever static servers it -// has. +// container runtime), return an error. The ordered reconciler retains LKG; +// startup remains fail-soft because composition treats this as stale. // - A workload whose name contains "__" is skipped (it would corrupt the // mcp____ namespacing). // - A workload whose *effective proxy transport* is not streamable-http is @@ -110,12 +109,7 @@ func (s ToolHiveSource) Name() string { func (s ToolHiveSource) Servers(ctx context.Context) ([]mcp.ServerConfig, []SkipError, error) { lister, err := s.newLister(ctx) if err != nil { - // No container runtime (or other construction fault): degrade to zero - // servers + a diagnostic. This is the common developer-laptop path. - return nil, []SkipError{{ - Server: "toolhive", - Reason: fmt.Sprintf("container runtime unavailable: %v", err), - }}, nil + return nil, nil, fmt.Errorf("ToolHive container runtime unavailable: %w", err) } // listAll=false: running workloads only. The runtime returns an error (not an @@ -123,10 +117,7 @@ func (s ToolHiveSource) Servers(ctx context.Context) ([]mcp.ServerConfig, []Skip // fault: degrade, don't abort. list, err := lister.ListWorkloads(ctx, false) if err != nil { - return nil, []SkipError{{ - Server: "toolhive", - Reason: fmt.Sprintf("listing ToolHive workloads failed: %v", err), - }}, nil + return nil, nil, fmt.Errorf("listing ToolHive workloads: %w", err) } // FilterByGroup is a pure in-memory filter over the already-listed workloads: diff --git a/internal/adapter/mcp/source/toolhive_test.go b/internal/adapter/mcp/source/toolhive_test.go index d8e9a1b5bb..f737d99ea1 100644 --- a/internal/adapter/mcp/source/toolhive_test.go +++ b/internal/adapter/mcp/source/toolhive_test.go @@ -219,32 +219,24 @@ func TestToolHiveEmptyGroupDefaults(t *testing.T) { } } -func TestToolHiveNoRuntimeDegrades(t *testing.T) { - // Constructor error (no container runtime) -> (nil, one diagnostic, nil). +func TestToolHiveNoRuntimeIsConsultationFailure(t *testing.T) { got, skips, err := sourceWith("default", nil, errors.New("no socket")).Servers(context.Background()) - if err != nil { - t.Fatalf("no-runtime must NOT be a fatal error, got %v", err) - } - if got != nil { - t.Errorf("no-runtime should yield zero servers, got %v", got) + if err == nil || !strings.Contains(err.Error(), "runtime unavailable") { + t.Fatalf("no-runtime error = %v, want consultation failure", err) } - if len(skips) != 1 || skips[0].Server != "toolhive" || !strings.Contains(skips[0].Reason, "runtime unavailable") { - t.Fatalf("expected one runtime-unavailable diagnostic, got %v", skips) + if got != nil || skips != nil { + t.Fatalf("failed consultation must not masquerade as authoritative empty: got=%v skips=%v", got, skips) } } -func TestToolHiveListErrorDegrades(t *testing.T) { - // Runtime present but list call fails -> degrade, not fatal. +func TestToolHiveListErrorIsConsultationFailure(t *testing.T) { f := &fakeLister{err: errors.New("daemon down")} got, skips, err := sourceWith("default", f, nil).Servers(context.Background()) - if err != nil { - t.Fatalf("list error must NOT be fatal, got %v", err) - } - if got != nil { - t.Errorf("list error should yield zero servers, got %v", got) + if err == nil || !strings.Contains(err.Error(), "listing ToolHive workloads") { + t.Fatalf("list error = %v, want consultation failure", err) } - if len(skips) != 1 || !strings.Contains(skips[0].Reason, "listing ToolHive workloads failed") { - t.Fatalf("expected one list-failed diagnostic, got %v", skips) + if got != nil || skips != nil { + t.Fatalf("failed consultation must not masquerade as authoritative empty: got=%v skips=%v", got, skips) } } diff --git a/internal/app/build.go b/internal/app/build.go index 006315ca9d..358a8ce5b1 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -5762,19 +5762,41 @@ func mcpSourceProber(cfg Config) func(ctx context.Context) []mcpsource.SourceInf // the mcp.Provider used for resources/prompts. func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, []mcpsource.SourceInfo, func()) { opts := mcpResolveOptions(cfg) - sources := mcpsource.ResolveSources(opts) - - configs, inventory, skips := mcpsource.Resolve(ctx, sources) - for _, s := range skips { - cfg.diag().Log(ctx, port.LevelWarn, "MCP server skipped", "name", s.Server, "reason", s.Reason) - } - if len(configs) == 0 { - cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", - "toolhive", cfg.ToolHiveEnabled, "static", len(cfg.MCPServers)) + if len(opts.StaticServers) == 0 && !opts.ToolHiveEnabled { + _, inventory, _ := mcpsource.Resolve(ctx, mcpsource.ResolveSources(opts)) + cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", "toolhive", false, "static", 0) return nil, nil, inventory, func() {} } + reconciler := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: mcpsource.ResolveSources(opts), + toolHive: opts.ToolHiveEnabled, + build: buildMCPReconcileCandidate(cfg), + // Task 03 replaces this bridge with immutable runtime publication and + // retirement. Until then, changed candidates are safely discarded rather + // than closing the manager already borrowed by assembled catalogs. + publish: func(old, _ *mcpReconcileCandidate) bool { return old == nil }, + }) + result, err := reconciler.Reconcile(ctx) + for _, diagnostic := range result.diagnostics { + cfg.diag().Log(ctx, port.LevelWarn, "MCP source reconciliation", "reason", diagnostic) + } + if err != nil || result.candidate == nil || len(result.candidate.configs) == 0 { + if err != nil { + logMCPReconcileConnectError(ctx, cfg, cfg.MCPServers, err) + cfg.diag().Log(ctx, port.LevelWarn, "MCP manager construction failed; continuing without MCP tools", "reason", "unavailable") + } else { + cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", + "toolhive", cfg.ToolHiveEnabled, "static", len(cfg.MCPServers)) + } + return nil, nil, result.inventory, reconciler.Close + } + mgr := result.candidate.manager + cfg.diag().Log(ctx, port.LevelInfo, "MCP servers connected", "servers", len(result.candidate.configs), "tools", len(mgr.Tools())) + return mgr, mgr, result.inventory, reconciler.Close +} - onError := func(sc mcp.ServerConfig, err error) { +func logMCPReconcileConnectError(ctx context.Context, cfg Config, configs []mcp.ServerConfig, err error) { + for _, sc := range configs { switch mcp.OAuthDCRRecoveryCategoryOf(err) { case mcp.OAuthDCRRecoveryResetRequired: cfg.diag().Log(ctx, port.LevelWarn, "MCP OAuth DCR valid ready registration identity differs from current profile, principal, canonical resource, or exact issuer", "name", sc.Name, "remedy", "run "+mcpLoginRemedy(sc)+" --reset-dcr-registration") @@ -5791,19 +5813,6 @@ func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, [] cfg.diag().Log(ctx, port.LevelWarn, "MCP OAuth environment credential unavailable", "name", sc.Name, "remedy", mcpLoginRemedy(sc)) return } - cfg.diag().Log(ctx, port.LevelWarn, "MCP server unreachable; skipping", "name", sc.Name, "reason", "unavailable") - } - mgr, err := mcp.NewManager(ctx, configs, onError, cfg.diag()) - if err != nil { - cfg.diag().Log(ctx, port.LevelWarn, "MCP manager construction failed; continuing without MCP tools", "reason", "unavailable") - return nil, nil, inventory, func() {} - } - cfg.diag().Log(ctx, port.LevelInfo, "MCP servers connected", "servers", len(configs), "tools", len(mgr.Tools())) - - return mgr, mgr, inventory, func() { - if err := mgr.Close(); err != nil { - cfg.diag().Log(ctx, port.LevelWarn, "MCP manager close", "err", err) - } } } diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go new file mode 100644 index 0000000000..bf9294a06d --- /dev/null +++ b/internal/app/mcp_reconciler.go @@ -0,0 +1,501 @@ +package app + +import ( + "context" + "crypto/rand" + "encoding/binary" + "errors" + "fmt" + "reflect" + "sort" + "strings" + "sync" + "sync/atomic" + "time" + "unicode/utf8" + + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/mcp" + mcpsource "github.com/stacklok/mecatl/internal/adapter/mcp/source" +) + +const ( + maxMCPReconcileSources = 8 + maxMCPReconcileServers = 128 + maxMCPActiveListEntries = 10_000 + maxMCPCandidatePages = 256 + maxMCPCandidateBytes = 16 << 20 + maxMCPUnionGrantNames = 1_024 + maxMCPHistoricalGrantedNames = 16_384 + maxMCPRetainedRuntimes = 4 + maxMCPDiagnosticBytes = 512 + maxMCPReconcileCycleDuration = 45 * time.Second + minMCPPollInterval = 25 * time.Second + maxMCPPollInterval = 35 * time.Second +) + +var errMCPReconcilerClosed = errors.New("MCP source reconciler is closed") + +type mcpToolMeta struct { + Name string + Description string + Schema string + ReadOnly bool +} + +type mcpReconcileCandidate struct { + manager *mcp.Manager + configs []mcp.ServerConfig + inventory []mcpsource.SourceInfo + tools []mcpToolMeta + resources []mcp.Resource + prompts []mcp.Prompt + generation uint64 + pages int + bytes int +} + +func (c *mcpReconcileCandidate) close() { + if c != nil && c.manager != nil { + _ = c.manager.Close() + } +} + +type mcpReconcileResult struct { + candidate *mcpReconcileCandidate + inventory []mcpsource.SourceInfo + diagnostics []string + stale bool + changed bool +} + +type mcpCandidateBuilder func(context.Context, []mcp.ServerConfig, func()) (*mcpReconcileCandidate, error) + +type mcpReconcilerOptions struct { + sources []mcpsource.Source + toolHive bool + build mcpCandidateBuilder + publish func(old, candidate *mcpReconcileCandidate) bool + after func(time.Duration) <-chan time.Time +} + +type mcpSourceSnapshot struct { + configs []mcp.ServerConfig + info mcpsource.SourceInfo +} + +type mcpReconcileReply struct { + result mcpReconcileResult + err error +} + +type mcpSourceReconciler struct { + ctx context.Context + cancel context.CancelFunc + once sync.Once + wg sync.WaitGroup + + sources []mcpsource.Source + toolHive bool + build mcpCandidateBuilder + publish func(old, candidate *mcpReconcileCandidate) bool + after func(time.Duration) <-chan time.Time + trigger chan struct{} + + mu sync.Mutex + waiters []chan mcpReconcileReply + lkg map[string]mcpSourceSnapshot + current *mcpReconcileCandidate + closed bool + + cyclesDone atomic.Int64 + nextGen atomic.Uint64 + candidateDirty atomic.Bool +} + +func newMCPSourceReconciler(opts mcpReconcilerOptions) *mcpSourceReconciler { + ctx, cancel := context.WithCancel(context.Background()) + if opts.after == nil { + opts.after = time.After + } + r := &mcpSourceReconciler{ + ctx: ctx, cancel: cancel, sources: append([]mcpsource.Source(nil), opts.sources...), + toolHive: opts.toolHive, build: opts.build, publish: opts.publish, after: opts.after, + trigger: make(chan struct{}, 1), lkg: make(map[string]mcpSourceSnapshot), + } + r.wg.Add(1) + go r.loop() + return r +} + +func (r *mcpSourceReconciler) polling() bool { return r.toolHive } +func (r *mcpSourceReconciler) cycles() int64 { return r.cyclesDone.Load() } + +func (r *mcpSourceReconciler) Reconcile(ctx context.Context) (mcpReconcileResult, error) { + reply := make(chan mcpReconcileReply, 1) + r.mu.Lock() + if r.closed { + r.mu.Unlock() + return mcpReconcileResult{}, errMCPReconcilerClosed + } + r.waiters = append(r.waiters, reply) + r.mu.Unlock() + r.invalidate() + select { + case got := <-reply: + return got.result, got.err + case <-ctx.Done(): + return mcpReconcileResult{}, ctx.Err() + } +} + +func (r *mcpSourceReconciler) invalidate() { + select { + case r.trigger <- struct{}{}: + default: + } +} + +func (r *mcpSourceReconciler) loop() { + defer r.wg.Done() + var poll <-chan time.Time + if r.toolHive { + poll = r.after(mcpPollDelay()) + } + for { + select { + case <-r.ctx.Done(): + replyMCPWaiters(r.takeWaiters(), mcpReconcileResult{stale: true}, r.ctx.Err()) + return + case <-poll: + r.invalidate() + poll = r.after(mcpPollDelay()) + case <-r.trigger: + waiters := r.takeWaiters() + result, err := r.cycle() + r.cyclesDone.Add(1) + replyMCPWaiters(waiters, result, err) + } + } +} + +func mcpPollDelay() time.Duration { + span := maxMCPPollInterval - minMCPPollInterval + if span <= 0 { + return minMCPPollInterval + } + var seed [4]byte + if _, err := rand.Read(seed[:]); err != nil { + return minMCPPollInterval + span/2 + } + jitterMillis := int64(binary.LittleEndian.Uint32(seed[:4])) % span.Milliseconds() + return minMCPPollInterval + time.Duration(jitterMillis)*time.Millisecond +} + +func (r *mcpSourceReconciler) takeWaiters() []chan mcpReconcileReply { + r.mu.Lock() + defer r.mu.Unlock() + waiters := r.waiters + r.waiters = nil + return waiters +} + +func replyMCPWaiters(waiters []chan mcpReconcileReply, result mcpReconcileResult, err error) { + for _, waiter := range waiters { + waiter <- mcpReconcileReply{result: result, err: err} + } +} + +func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { + cycleCtx, cancel := context.WithTimeout(r.ctx, maxMCPReconcileCycleDuration) + defer cancel() + configs, inventory, diagnostics, stale, err := r.resolve(cycleCtx) + result := mcpReconcileResult{inventory: inventory, diagnostics: diagnostics, stale: stale} + if err != nil { + r.mu.Lock() + result.candidate = r.current + r.mu.Unlock() + return result, err + } + + r.mu.Lock() + current := r.current + unchanged := current != nil && reflect.DeepEqual(current.configs, configs) + r.mu.Unlock() + candidateDirty := r.candidateDirty.Swap(false) + if unchanged && !stale && !candidateDirty { + result.candidate = current + return result, nil + } + if r.build == nil { + return result, errors.New("MCP source reconciler has no candidate builder") + } + + generation := r.nextGen.Add(1) + dirty := func() { + r.mu.Lock() + isCurrent := r.current != nil && r.current.generation == generation + r.mu.Unlock() + if isCurrent { + r.candidateDirty.Store(true) + r.invalidate() + } + } + candidate, err := r.build(cycleCtx, configs, dirty) + if err != nil { + result.stale = true + result.diagnostics = appendBoundedDiagnostic(result.diagnostics, err.Error()) + r.mu.Lock() + result.candidate = r.current + r.mu.Unlock() + return result, err + } + if candidate == nil { + return result, errors.New("MCP candidate builder returned nil") + } + candidate.generation = generation + candidate.configs = cloneMCPConfigs(configs) + candidate.inventory = cloneMCPInventory(inventory) + if err := validateMCPCandidate(candidate); err != nil { + candidate.close() + result.stale = true + result.diagnostics = appendBoundedDiagnostic(result.diagnostics, err.Error()) + return result, err + } + + r.mu.Lock() + old := r.current + if equalMCPCandidate(old, candidate) { + r.mu.Unlock() + candidate.close() + result.candidate = old + return result, nil + } + if r.publish != nil && !r.publish(old, candidate) { + r.mu.Unlock() + candidate.close() + result.candidate = old + result.stale = true + result.diagnostics = appendBoundedDiagnostic(result.diagnostics, "MCP runtime publication is pending integration") + return result, nil + } + r.current = candidate + r.mu.Unlock() + if old != nil { + old.close() + } + result.candidate = candidate + result.changed = old != nil + return result, nil +} + +func (r *mcpSourceReconciler) resolve(ctx context.Context) ([]mcp.ServerConfig, []mcpsource.SourceInfo, []string, bool, error) { + if len(r.sources) > maxMCPReconcileSources { + return nil, nil, nil, true, fmt.Errorf("MCP source count exceeds limit %d", maxMCPReconcileSources) + } + var inventory []mcpsource.SourceInfo + var diagnostics []string + var all []struct { + config mcp.ServerConfig + source string + } + stale := false + for _, src := range r.sources { + cfgs, skips, err := src.Servers(ctx) + info := sourceInfo(src) + for _, skip := range skips { + msg := skip.Error() + info.Diagnostics = appendBoundedDiagnostic(info.Diagnostics, msg) + diagnostics = appendBoundedDiagnostic(diagnostics, msg) + } + if err != nil { + stale = true + msg := "source consultation failed: " + err.Error() + info.Diagnostics = appendBoundedDiagnostic(info.Diagnostics, msg) + diagnostics = appendBoundedDiagnostic(diagnostics, msg) + if prior, ok := r.lkg[src.Name()]; ok { + cfgs = cloneMCPConfigs(prior.configs) + info.Servers = append([]mcpsource.ServerInfo(nil), prior.info.Servers...) + } + } else { + cfgs = cloneMCPConfigs(cfgs) + info.Servers = serverInfos(cfgs, info.Group) + r.lkg[src.Name()] = mcpSourceSnapshot{configs: cloneMCPConfigs(cfgs), info: info} + } + inventory = append(inventory, info) + for _, cfg := range cfgs { + all = append(all, struct { + config mcp.ServerConfig + source string + }{cfg, src.Name()}) + } + } + if len(all) > maxMCPReconcileServers { + return nil, inventory, diagnostics, true, fmt.Errorf("MCP server count exceeds limit %d", maxMCPReconcileServers) + } + winner := make(map[string]string, len(all)) + merged := make([]mcp.ServerConfig, 0, len(all)) + for _, item := range all { + if prior, exists := winner[item.config.Name]; exists { + diagnostics = appendBoundedDiagnostic(diagnostics, fmt.Sprintf("server %q shadowed by higher-precedence source %q", item.config.Name, prior)) + continue + } + winner[item.config.Name] = item.source + merged = append(merged, item.config) + } + sort.Slice(merged, func(i, j int) bool { return merged[i].Name < merged[j].Name }) + return merged, inventory, diagnostics, stale, nil +} + +func (r *mcpSourceReconciler) Close() { + r.once.Do(func() { + r.mu.Lock() + r.closed = true + r.mu.Unlock() + r.cancel() + r.wg.Wait() + r.mu.Lock() + current := r.current + r.current = nil + r.mu.Unlock() + current.close() + }) +} + +func sourceInfo(src mcpsource.Source) mcpsource.SourceInfo { + info := mcpsource.SourceInfo{Name: src.Name(), Enabled: true} + switch { + case src.Name() == "static": + info.Kind = "static" + case strings.HasPrefix(src.Name(), "toolhive("): + info.Kind = "toolhive" + info.Group = strings.TrimSuffix(strings.TrimPrefix(src.Name(), "toolhive("), ")") + } + return info +} + +func serverInfos(configs []mcp.ServerConfig, group string) []mcpsource.ServerInfo { + out := make([]mcpsource.ServerInfo, 0, len(configs)) + for _, cfg := range configs { + out = append(out, mcpsource.ServerInfo{Name: cfg.Name, URL: cfg.URL, Transport: "streamable-http", Group: group}) + } + return out +} + +func cloneMCPConfigs(in []mcp.ServerConfig) []mcp.ServerConfig { + out := make([]mcp.ServerConfig, len(in)) + for i, cfg := range in { + out[i] = cfg + if cfg.Headers != nil { + out[i].Headers = make(map[string]string, len(cfg.Headers)) + for k, v := range cfg.Headers { + out[i].Headers[k] = v + } + } + if cfg.OAuth != nil { + oauth := *cfg.OAuth + oauth.Presenter = nil // serving reconciliation never launches consent + out[i].OAuth = &oauth + } + } + return out +} + +func cloneMCPInventory(in []mcpsource.SourceInfo) []mcpsource.SourceInfo { + out := make([]mcpsource.SourceInfo, len(in)) + for i, info := range in { + out[i] = info + out[i].Servers = append([]mcpsource.ServerInfo(nil), info.Servers...) + out[i].Diagnostics = append([]string(nil), info.Diagnostics...) + } + return out +} + +func appendBoundedDiagnostic(dst []string, raw string) []string { + safe := mcp.RedactText(strings.Join(strings.Fields(raw), " ")) + if len(safe) > maxMCPDiagnosticBytes { + safe = safe[:maxMCPDiagnosticBytes] + for !utf8.ValidString(safe) { + safe = safe[:len(safe)-1] + } + } + return append(dst, safe) +} + +func validateMCPCandidate(c *mcpReconcileCandidate) error { + entries := len(c.tools) + len(c.resources) + len(c.prompts) + if entries > maxMCPActiveListEntries { + return fmt.Errorf("MCP active list entries exceed limit %d", maxMCPActiveListEntries) + } + if c.pages > maxMCPCandidatePages { + return fmt.Errorf("MCP candidate pages exceed limit %d", maxMCPCandidatePages) + } + if c.bytes > maxMCPCandidateBytes { + return fmt.Errorf("MCP candidate bytes exceed limit %d", maxMCPCandidateBytes) + } + return nil +} + +func equalMCPCandidate(a, b *mcpReconcileCandidate) bool { + if a == nil || b == nil { + return a == b + } + return reflect.DeepEqual(a.configs, b.configs) && reflect.DeepEqual(a.tools, b.tools) && reflect.DeepEqual(a.resources, b.resources) && reflect.DeepEqual(a.prompts, b.prompts) && reflect.DeepEqual(a.inventory, b.inventory) +} + +func toolMetadata(tools []tool.Tool) []mcpToolMeta { + out := make([]mcpToolMeta, 0, len(tools)) + for _, candidate := range tools { + spec := candidate.Spec() + out = append(out, mcpToolMeta{Name: spec.Name, Description: spec.Description, Schema: string(spec.Schema), ReadOnly: candidate.ReadOnly()}) + } + sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name }) + return out +} + +func validateMCPGrantBounds(existing, additions []string) error { + if len(additions) > maxMCPUnionGrantNames { + return fmt.Errorf("MCP refresh additions exceed limit %d", maxMCPUnionGrantNames) + } + seen := make(map[string]struct{}, len(existing)+len(additions)) + for _, name := range existing { + seen[name] = struct{}{} + } + for _, name := range additions { + seen[name] = struct{}{} + } + if len(seen) > maxMCPHistoricalGrantedNames { + return fmt.Errorf("historical MCP grants exceed limit %d", maxMCPHistoricalGrantedNames) + } + return nil +} + +func buildMCPReconcileCandidate(diagCfg Config) mcpCandidateBuilder { + return func(ctx context.Context, configs []mcp.ServerConfig, changed func()) (*mcpReconcileCandidate, error) { + bounded := cloneMCPConfigs(configs) + budget := mcp.NewCandidateListBudget(maxMCPActiveListEntries, maxMCPCandidatePages, maxMCPCandidateBytes) + defer budget.Seal() + for i := range bounded { + bounded[i].ListChanged = changed + bounded[i].CandidateBudget = budget + } + mgr, err := mcp.NewCompleteManager(ctx, bounded, diagCfg.diag()) + if err != nil { + return nil, err + } + candidate := &mcpReconcileCandidate{manager: mgr, configs: cloneMCPConfigs(configs)} + candidate.tools = toolMetadata(mgr.Tools()) + candidate.resources, err = mgr.ListResources(ctx, "") + if err != nil { + candidate.close() + return nil, err + } + candidate.prompts, err = mgr.ListPrompts(ctx, "") + if err != nil { + candidate.close() + return nil, err + } + _, candidate.pages, candidate.bytes = budget.Stats() + return candidate, nil + } +} diff --git a/internal/app/mcp_reconciler_test.go b/internal/app/mcp_reconciler_test.go new file mode 100644 index 0000000000..a3735ecc60 --- /dev/null +++ b/internal/app/mcp_reconciler_test.go @@ -0,0 +1,337 @@ +package app + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/http/httptest" + "sync" + "sync/atomic" + "testing" + "time" + + mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" + + "github.com/stacklok/mecatl/internal/adapter/mcp" + mcpsource "github.com/stacklok/mecatl/internal/adapter/mcp/source" +) + +type reconciliationSource struct { + name string + mu sync.Mutex + cfgs []mcp.ServerConfig + err error +} + +func (s *reconciliationSource) Name() string { return s.name } +func (s *reconciliationSource) Servers(context.Context) ([]mcp.ServerConfig, []mcpsource.SkipError, error) { + s.mu.Lock() + defer s.mu.Unlock() + return append([]mcp.ServerConfig(nil), s.cfgs...), nil, s.err +} +func (s *reconciliationSource) set(cfgs []mcp.ServerConfig, err error) { + s.mu.Lock() + s.cfgs, s.err = cfgs, err + s.mu.Unlock() +} + +func candidateFromConfigs(configs []mcp.ServerConfig, generation uint64) *mcpReconcileCandidate { + return &mcpReconcileCandidate{configs: cloneMCPConfigs(configs), generation: generation} +} + +func TestMCPSourceReconciliation_Scenario1_OrderedSourcesLKGAndEmpty(t *testing.T) { + static := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "same", URL: "http://static/mcp"}}} + toolhive := &reconciliationSource{name: "toolhive(default)", cfgs: []mcp.ServerConfig{{Name: "same", URL: "http://toolhive/mcp"}, {Name: "dynamic", URL: "http://dynamic/mcp"}}} + var generation atomic.Uint64 + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{static, toolhive}, + build: func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, generation.Add(1)), nil + }, + }) + t.Cleanup(r.Close) + + first, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatalf("initial reconcile: %v", err) + } + if got := configURL(first.candidate.configs, "same"); got != "http://static/mcp" { + t.Fatalf("configured/static source lost precedence: %q", got) + } + if len(first.inventory) != 2 || len(first.inventory[1].Servers) != 2 { + t.Fatalf("pre-shadow source rows not retained: %+v", first.inventory) + } + + toolhive.set(nil, errors.New("runtime unavailable: https://secret.example/mcp?token=do-not-log")) + failed, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatalf("failed-source reconcile should retain LKG: %v", err) + } + if !failed.stale || configURL(failed.candidate.configs, "dynamic") == "" { + t.Fatalf("source failure did not retain LKG/stale: %+v", failed) + } + for _, d := range failed.diagnostics { + if len(d) > maxMCPDiagnosticBytes || containsSecret(d) { + t.Fatalf("diagnostic is unbounded or secret-bearing: %q", d) + } + } + + toolhive.set([]mcp.ServerConfig{}, nil) + empty, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatalf("authoritative-empty reconcile: %v", err) + } + if empty.stale || configURL(empty.candidate.configs, "dynamic") != "" { + t.Fatalf("successful empty did not withdraw ToolHive LKG: %+v", empty) + } +} + +func TestMCPSourceReconciliation_Scenario1_ProductionTriggerMatrix(t *testing.T) { + t.Run("polling-and-manual-coalescing", func(t *testing.T) { + static := &reconciliationSource{name: "static"} + var builds atomic.Int64 + started := make(chan struct{}, 1) + release := make(chan struct{}) + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{static}, + build: func(ctx context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + builds.Add(1) + select { + case started <- struct{}{}: + default: + } + select { + case <-release: + case <-ctx.Done(): + return nil, ctx.Err() + } + return candidateFromConfigs(configs, uint64(builds.Load())), nil + }, + }) + if r.polling() { + t.Fatal("polling enabled without ToolHive") + } + ctx, cancel := context.WithCancel(context.Background()) + done := make(chan error, 1) + go func() { _, err := r.Reconcile(ctx); done <- err }() + <-started + cancel() + if err := <-done; !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled waiter error = %v", err) + } + other := make(chan error, 1) + go func() { _, err := r.Reconcile(context.Background()); other <- err }() + close(release) + if err := <-other; err != nil { + t.Fatalf("coalesced waiter: %v", err) + } + if got := builds.Load(); got > 2 { + t.Fatalf("manual work not serialized/coalesced: %d builds", got) + } + r.Close() + }) + + t.Run("toolhive-poll-and-stable-no-reconnect", func(t *testing.T) { + th := &reconciliationSource{name: "toolhive(default)", cfgs: []mcp.ServerConfig{{Name: "a", URL: "http://a/mcp"}}} + ticks := make(chan time.Time, 4) + var builds atomic.Int64 + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{th}, toolHive: true, + after: func(d time.Duration) <-chan time.Time { + if d < minMCPPollInterval || d > maxMCPPollInterval { + t.Errorf("poll interval outside jitter bounds: %v", d) + } + return ticks + }, + build: func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, uint64(builds.Add(1))), nil + }, + }) + t.Cleanup(r.Close) + if !r.polling() { + t.Fatal("ToolHive polling is disabled") + } + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatal(err) + } + ticks <- time.Now() + eventuallyReconcile(t, func() bool { return r.cycles() >= 2 }) + if got := builds.Load(); got != 1 { + t.Fatalf("unchanged poll reconnected candidate: builds=%d", got) + } + }) + + t.Run("dirty-all-lists-and-stale-notification", func(t *testing.T) { + var builds atomic.Int64 + var notify func() + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "live", URL: "http://live/mcp"}}}}, + build: func(_ context.Context, configs []mcp.ServerConfig, changed func()) (*mcpReconcileCandidate, error) { + notify = changed + g := uint64(builds.Add(1)) + return &mcpReconcileCandidate{configs: cloneMCPConfigs(configs), generation: g, tools: []mcpToolMeta{{Name: "tool"}}, resources: []mcp.Resource{{URI: "r", Description: string(rune('0' + g))}}, prompts: []mcp.Prompt{{Name: "p", Description: string(rune('0' + g))}}}, nil + }, + }) + t.Cleanup(r.Close) + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatal(err) + } + oldNotify := notify + oldNotify() + eventuallyReconcile(t, func() bool { return builds.Load() == 2 }) + oldNotify() + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatal(err) + } + if got := builds.Load(); got != 2 { + t.Fatalf("stale runtime notification triggered build: %d", got) + } + }) + + t.Run("real-notification-refreshes-complete-snapshot", func(t *testing.T) { + remote := mcpsdk.NewServer(&mcpsdk.Implementation{Name: "live", Version: "v1"}, nil) + mcpsdk.AddTool(remote, &mcpsdk.Tool{Name: "initial"}, func(context.Context, *mcpsdk.CallToolRequest, struct{}) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{}, nil, nil + }) + httpServer := httptest.NewServer(mcpsdk.NewStreamableHTTPHandler(func(*http.Request) *mcpsdk.Server { return remote }, nil)) + src := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "live", URL: httpServer.URL}}} + r := newMCPSourceReconciler(mcpReconcilerOptions{sources: []mcpsource.Source{src}, build: buildMCPReconcileCandidate(Config{})}) + t.Cleanup(httpServer.Close) + t.Cleanup(r.Close) + first, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatalf("initial reconcile: %v", err) + } + firstGeneration := first.candidate.generation + + remote.AddResource(&mcpsdk.Resource{URI: "test://late", Name: "late-resource"}, func(_ context.Context, req *mcpsdk.ReadResourceRequest) (*mcpsdk.ReadResourceResult, error) { + return &mcpsdk.ReadResourceResult{Contents: []*mcpsdk.ResourceContents{{URI: req.Params.URI, Text: "late"}}}, nil + }) + remote.AddPrompt(&mcpsdk.Prompt{Name: "late-prompt"}, func(context.Context, *mcpsdk.GetPromptRequest) (*mcpsdk.GetPromptResult, error) { + return &mcpsdk.GetPromptResult{}, nil + }) + mcpsdk.AddTool(remote, &mcpsdk.Tool{Name: "late-tool"}, func(context.Context, *mcpsdk.CallToolRequest, struct{}) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{}, nil, nil + }) + + eventuallyReconcile(t, func() bool { + r.mu.Lock() + defer r.mu.Unlock() + return r.current != nil && r.current.generation != firstGeneration && len(r.current.tools) == 2 && len(r.current.resources) == 1 && len(r.current.prompts) == 1 + }) + }) +} + +func TestADR_0345_ReconciliationBoundsConsentAndShutdown(t *testing.T) { + if maxMCPReconcileSources <= 0 || maxMCPReconcileServers <= 0 || maxMCPActiveListEntries <= 0 || maxMCPCandidatePages <= 0 || maxMCPCandidateBytes <= 0 || maxMCPUnionGrantNames <= 0 || maxMCPHistoricalGrantedNames <= 0 || maxMCPRetainedRuntimes <= 0 || maxMCPReconcileCycleDuration <= 0 { + t.Fatal("every reconciliation dimension must have an independent finite bound") + } + tooMany := make([]mcp.ServerConfig, maxMCPReconcileServers+1) + for i := range tooMany { + tooMany[i] = mcp.ServerConfig{Name: "server"} + } + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "static", cfgs: tooMany}}, + build: func(context.Context, []mcp.ServerConfig, func()) (*mcpReconcileCandidate, error) { + t.Fatal("candidate built beyond server bound") + return nil, nil + }, + }) + result, err := r.Reconcile(context.Background()) + if err == nil || !result.stale { + t.Fatalf("bound failure = (%+v, %v), want stale error", result, err) + } + r.Close() + + for _, tc := range []struct { + name string + candidate *mcpReconcileCandidate + }{ + {"active-list", &mcpReconcileCandidate{tools: make([]mcpToolMeta, maxMCPActiveListEntries+1)}}, + {"page-count", &mcpReconcileCandidate{pages: maxMCPCandidatePages + 1}}, + {"byte-count", &mcpReconcileCandidate{bytes: maxMCPCandidateBytes + 1}}, + } { + t.Run(tc.name+"-bound", func(t *testing.T) { + if err := validateMCPCandidate(tc.candidate); err == nil { + t.Fatal("over-bound candidate accepted") + } + }) + } + if err := validateMCPCandidate(&mcpReconcileCandidate{tools: make([]mcpToolMeta, maxMCPActiveListEntries), pages: maxMCPCandidatePages, bytes: maxMCPCandidateBytes}); err != nil { + t.Fatalf("candidate boundary rejected: %v", err) + } + if err := validateMCPGrantBounds(nil, make([]string, maxMCPUnionGrantNames)); err != nil { + t.Fatalf("union boundary rejected: %v", err) + } + if err := validateMCPGrantBounds(nil, make([]string, maxMCPUnionGrantNames+1)); err == nil { + t.Fatal("union over-bound accepted") + } + existing := make([]string, maxMCPHistoricalGrantedNames) + for i := range existing { + existing[i] = fmt.Sprintf("mcp__s__%d", i) + } + if err := validateMCPGrantBounds(existing, nil); err != nil { + t.Fatalf("historical boundary rejected: %v", err) + } + if err := validateMCPGrantBounds(existing, []string{"mcp__s__overflow"}); err == nil { + t.Fatal("historical over-bound accepted") + } + + presenter := mcp.OAuthPresenterFunc(nil) + cloned := cloneMCPConfigs([]mcp.ServerConfig{{OAuth: &mcp.OAuthOptions{Presenter: presenter}}}) + if cloned[0].OAuth == nil || cloned[0].OAuth.Presenter != nil { + t.Fatal("serving reconciliation retained an OAuth consent presenter") + } + + blocked := make(chan struct{}) + joined := make(chan struct{}) + r = newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "toolhive(default)"}}, toolHive: true, + build: func(ctx context.Context, _ []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + close(blocked) + <-ctx.Done() + close(joined) + return nil, ctx.Err() + }, + }) + go func() { _, _ = r.Reconcile(context.Background()) }() + <-blocked + r.Close() + select { + case <-joined: + case <-time.After(time.Second): + t.Fatal("shutdown did not join reconciliation") + } +} + +func configURL(configs []mcp.ServerConfig, name string) string { + for _, c := range configs { + if c.Name == name { + return c.URL + } + } + return "" +} +func containsSecret(s string) bool { + return len(s) >= len("do-not-log") && stringContains(s, "do-not-log") +} +func stringContains(s, sub string) bool { + for i := 0; i+len(sub) <= len(s); i++ { + if s[i:i+len(sub)] == sub { + return true + } + } + return false +} +func eventuallyReconcile(t *testing.T, f func() bool) { + t.Helper() + deadline := time.Now().Add(time.Second) + for time.Now().Before(deadline) { + if f() { + return + } + time.Sleep(time.Millisecond) + } + t.Fatal("timed out waiting for reconciliation") +} From 77b5c4501b6e1601181d1532d920015bf2ab1fc6 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Wed, 16 Sep 2026 14:29:22 +0300 Subject: [PATCH 03/14] feat(mcp): publish immutable direct runtimes Co-Authored-By: mecatl --- docs/adr/0027-cloud-native.md | 4 +- docs/design/IMPLEMENTATION-NOTES.md | 23 +- internal/adapter/server/service.go | 60 ++- internal/adapter/server/team.go | 10 + internal/app/build.go | 91 +++- internal/app/catalog.go | 6 +- internal/app/mcp_reconciler.go | 31 +- internal/app/mcp_runtime.go | 279 ++++++++++ internal/app/mcp_runtime_publication_test.go | 508 +++++++++++++++++++ internal/app/root_authority.go | 20 + internal/app/session_debug_test.go | 10 +- 11 files changed, 990 insertions(+), 52 deletions(-) create mode 100644 internal/app/mcp_runtime.go create mode 100644 internal/app/mcp_runtime_publication_test.go diff --git a/docs/adr/0027-cloud-native.md b/docs/adr/0027-cloud-native.md index 19f8f5c070..4fe3e69c64 100644 --- a/docs/adr/0027-cloud-native.md +++ b/docs/adr/0027-cloud-native.md @@ -799,8 +799,8 @@ durable artifact survives and is reloaded), or **lost** (gone, possibly leaking) | 61 | Provider OIDC issuer and gateway HTTP clients | `internal/cliconfig.NativeEndpointRuntime` | process, one pair per provider runtime | clients have no independent goroutine; their transports die with the runtime/loader | reconstructible from explicit issuer/gateway trust policies and CA bundles; neither trust root is reused for the other | `internal/cliconfig/native_endpoint.go` (`OpenNativeEndpointRuntime`, `nativeTrustClient`) | | 62 | Provider OIDC keyring and encrypted Store handles | `internal/cliconfig.NativeEndpointRuntime` | operation handles; serving Store handles live for the runtime | Login/status/logout defer Store close; `Source` handles close at runtime/loader close | reopened only from explicit `credential_store.oidc.home` and provider identity; no discovery, migration, plaintext, or environment fallback | `internal/cliconfig/native_endpoint.go` (`open`, `Login`, `Status`, `Logout`, `Close`); `internal/adapter/llmendpoint/lifecycle.go` (`NewProtectedStore`) | | 63 | Provider OIDC transaction-lock handles | `llmendpoint.TransactionLocker` | one provider lifecycle operation | `With` releases its owner-only flock after the callback; no lock is retained across gateway requests | reset/reacquired after restart from the hashed provider identity; the durable record remains the source of truth | `internal/adapter/llmendpoint/lifecycle.go` (`TransactionLocker`, `With`) | -| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, and current complete candidate | `app.Build` through `connectMCP` | process | the Build close fold invokes `mcpSourceReconciler.Close`, which rejects new requests, cancels and joins the worker, then closes the current manager; caller cancellation only stops that caller's wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects a complete candidate, and begins with no source LKG or pending invalidation; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `Close`); `internal/app/build.go` (`connectMCP`) | -| 1 | Global MCP manager (`globalMgr`) | `app.Build` | process | owned as the reconciler's current candidate and closed by its joined Build close; NEVER folded into per-session close | reconstructible (reconnects from ordered sources at next Build) | `internal/app/mcp_reconciler.go` (`mcpReconcileCandidate`); `internal/app/build.go` (`connectMCP`) | +| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, immutable current and bounded retiring runtimes, one deferred-successor bit, revision-tagged engine caches, and run/operation pins | `app.Build` through `connectMCP`; `server.Service` owns root-run pin lifetime | process publication state plus one pin per active root run or resource/prompt operation | the Build close fold first drains `Service`, then invokes `mcpSourceReconciler.Close` and `mcpRuntimeSet.close`; publication never mutates a live manager, a displaced runtime closes only after its pins drain, and a full retirement set discards the candidate without force-close and schedules one retry after drain. Cached-engine close never closes a direct manager. Caller cancellation only stops that caller's reconciliation wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects one complete runtime, and begins with no source LKG, retired runtime, pin, cache revision, or pending invalidation; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `mcpReconcileCandidate`, `Close`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`, `pin`, `publish`, `release`); `internal/adapter/server/service.go` (`beginRunAdmission`, `engineAndEnvironmentFor`, `SessionEngineResult.RuntimeRevision`); `internal/app/build.go` (`connectMCP`) | +| 1 | Direct global MCP managers (one per immutable current/retiring runtime) | `app.Build` / `mcpRuntimeSet` | process, bounded current plus retired set | a candidate owns its manager from complete construction; unchanged/failed/unpublishable candidates close immediately, retired managers close after operation pins drain, and joined Build close closes the remainder. They are NEVER folded into per-session engine close | reconstructible (reconnects a complete desired set from ordered sources at next Build) | `internal/app/mcp_reconciler.go` (`mcpReconcileCandidate`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`); `internal/app/build.go` (`connectMCP`) | | 2 | Per-session client MCP managers and their original `Service.clientMCPSpecs` mount declarations | `sessionEngineFactory` / `Service` | session / process-local map | per-session close func, invoked by `Service.CloseSession` (`service.go:743`) and shutdown. **Two callers now reach this** (issue #821, Scenario 9): the ACP adapter, which calls `CloseSession` on editor disconnect, and the gRPC/HTTP `CreateSession` wire path, whose teardown is the precondition-checked `EndSession` (same teardown) or `Service.Close`. `CloseSession`, failed-create rollback, and `Service.Close` remove the corresponding `clientMCPSpecs` entry; an engine-rebuild failure deliberately retains it because the surviving session can retry/remount the same client tools. The wire caller is a client that may simply go away without ending its session, so a mounted manager can outlive its last use until process shutdown — bounded by `MaxSessionEngines` (which fails a create at the cap rather than growing without limit), not by a reaper. That residual is the same one every per-session engine has, and it is why the field is deployment-gated to a UNIX-socket-only daemon rather than exposed to an anonymous network caller. A create REFUSED for an unreachable server does not add to it: `verifyClientMCPMounted` runs before any id is minted and invokes the same `closeFn` every other rejection in `createPerSessionEngine` does, so the partially-connected manager is torn down on that path rather than left registered against a session that does not exist | **reset/remount by design:** client specs, including secret-shaped headers, are never persisted. A restart drops `clientMCPSpecs` and every client manager; the client explicitly re-mounts via `LoadSessionWithMCP`, `service.go:968`, or creates a new session with `mcp_servers`. Within one Service lifetime, a rebuild reuses the retained original declaration. | `internal/app/build.go:962`; `internal/adapter/server/service.go` (`clientMCPSpecs`, `ClientMCPFromWire`, `WithClientMCP`) | | 3 | Preserved-fork LRU (`LRUForkReaper`) — Parallel ONLY | `app.Build` (shared via `catalogAssets`, built only when Parallel is enabled) | process | LRU eviction runs each entry's cleanup (dir removal) outside the lock; graceful app shutdown calls `Built.Close`, which drains retained entries and eviction cleanups already detached before closure outside the lock | registry lost; the preserved fork DIRS remain on disk un-tracked (a leak on crash) | `engine/agent/forkreaper.go:41,64`; built at `internal/app/build.go:4895`. NOTE: the writable Subagent (`mode:"read-write"`) no longer creates a per-call fork dir — it writes the parent workspace directly (ADR 0077), so it contributes no fork dirs here; the shared `autoMerger` (`forker.SerializingMerger`) is likewise Parallel-only now | | 4 | Project memory store (flock pair: `memory.json` + `memory.lock`) | `app.Build` | process handle, per-directory data | flock held per-operation only; one `*Store` per dir per process. Current entries, revision history, and tombstones share ONE locked atomic document — no split-file transaction | persisted (data/history on disk; legacy entries lazily materialize on first mutation; handle rebuilt at next Build) | `internal/app/build.go`; `internal/adapter/memory/store.go` (`Store`, `withExclusiveLock`, `materializeLegacy`) | diff --git a/docs/design/IMPLEMENTATION-NOTES.md b/docs/design/IMPLEMENTATION-NOTES.md index 08e4484e75..45e79095a3 100644 --- a/docs/design/IMPLEMENTATION-NOTES.md +++ b/docs/design/IMPLEMENTATION-NOTES.md @@ -5987,7 +5987,7 @@ without affinity or a durable-broker decision. Guards include `internal/adapter/ `internal/adapter/mcpbroker/workspace_catalogue_test.go`, and `internal/adapter/mcpbroker/toolhive_process_test.go`. -**Ordered direct MCP source reconciliation (ADR 0345, Task 02):** +**Ordered direct MCP source reconciliation and runtime publication (ADR 0345):** `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`) is the one Build-owned, serialized/coalesced path for initial resolution, manual requests, current-server list-change notifications, and ToolHive-only bounded jittered polling. It consults @@ -6000,12 +6000,21 @@ candidate generations are ignored. `internal/adapter/mcp/mcp.go` (`NewCompleteManager`) connects and lists all desired servers all-or-nothing, using one candidate-wide page/byte/cardinality budget and no OAuth presenter. Candidate equality covers source/server configuration and bounded tool, -resource, and prompt metadata. Build shutdown rejects new waits, cancels and -joins the worker, then closes its current candidate. Caller cancellation only -abandons that caller's wait. The current `connectMCP` publication bridge accepts -the initial candidate and safely closes/discards later changed candidates while -retaining the manager borrowed by existing catalogs; immutable runtime -publication, revision pins, and retirement replace that bridge in Task 03. +resource, and prompt metadata. `internal/app/mcp_runtime.go` (`mcpRuntimeSet`) +atomically publishes the complete candidate as one manager/provider/catalog +contribution. Root runs pin it in `server.Service.beginRunAdmission`; the pin +context reaches prompt expansion and every Subagent/Parallel/Team/named/reference +factory built by the one `assembleCatalog` path. Out-of-run resource and prompt +provider calls take one call-scoped pin. Shared and cached default, selector, +no-FS, client-MCP, mode, specialist, and debug engines carry only a revision tag; +`server.Service.engineAndEnvironmentFor` rebuilds a mismatch before use, so idle +engine caches never lease a manager and their close functions never own one. +Displaced runtimes close after pins drain. A full bounded retirement set closes +and discards the unpublishable candidate without force-closing live work, marks +the cycle stale, and remembers one retry that fires when a retirement drains. +Build shutdown first drains Service operations, then rejects new reconciler waits, +cancels and joins the worker, and closes all remaining runtime managers. Caller +cancellation only abandons that caller's reconciliation wait. **Server-global MCP on every session (bug #3 fix, `sessionEngineFactory`):** the per-session catalog mounts the SERVER-GLOBAL MCP tools (`cfg.MCPServers` + ToolHive — the diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index c8e2e6b4af..3fac46a923 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -145,6 +145,11 @@ type SessionEngineResult struct { // (the wire-only option) turns the check on, so the ACP path and every // selector-only factory are unaffected. MountedClientMCP []string + // RuntimeRevision is the immutable direct-MCP runtime revision used to build + // this engine. Zero keeps compatibility for compositions without live MCP + // publication. Engines do not hold runtime pins; run admission compares this + // tag with the operation pin and rebuilds before use. + RuntimeRevision uint64 // Close tears down the session's MCP manager. Never nil (a no-op when no specs). Close func() error } @@ -566,6 +571,17 @@ type Config struct { // regression-guard seam: composition wires it ONLY when a plan slot is active. ModeNeedsEngine func(mode session.PermissionMode) bool + // OperationPin pins one immutable direct-MCP runtime for a root run. The + // returned context carries the generation into composition factories and child + // engines; release is called only when the run registry settles. Nil disables + // runtime publication integration. + OperationPin func(context.Context) (context.Context, func(), error) + // OperationRevision reads the revision carried by OperationPin. Shared and + // cached engines are rebuilt before use when their tag differs. + OperationRevision func(context.Context) uint64 + // SharedEngineRevision tags Engine's build-time direct-MCP generation. + SharedEngineRevision uint64 + // MemberEngine builds a team member's Engine from the shared team and the // member spec (see engine/agent.MemberEngine). It is the seam that wires // the agent-team RPCs: when nil, those RPCs return ErrTeamsDisabled. The @@ -1227,8 +1243,11 @@ type sessionEngine struct { // shared buildAndRegisterSessionEngine path (the run-entry seam, between turns). The // empty value means "no mode pin" (a pre-Phase-3 factory) and never triggers a // rebuild — byte-identical to the old behaviour. - builtForMode session.PermissionMode - close func() error + // runtimeRevision tags the immutable direct-MCP generation used to build the + // catalog. It is not a lease; the root run owns the operation pin. + runtimeRevision uint64 + builtForMode session.PermissionMode + close func() error } // runState couples an in-flight *agent.Run with the live *session.Session the @@ -1265,7 +1284,10 @@ type runState struct { // runContextStop releases the lease-linked launch context after the promoted // run has settled. It must outlive the run-entry call itself. runContextStop context.CancelFunc - awaiting atomic.Bool + // operationRelease drains the immutable direct-MCP runtime pin acquired at + // run admission. It is independent from engine cache lifetime. + operationRelease func() + awaiting atomic.Bool // titleRevision is the last title metadata revision successfully persisted and // published for this run. It starts from the admitted durable snapshot so // prompt-ingress changes publish only after their save succeeds. @@ -4270,6 +4292,7 @@ func (s *Service) LoadSessionWithMCP(ctx context.Context, id session.SessionID, modelID: res.ModelID, reasoningEffort: res.ReasoningEffort, builtForMode: res.BuiltForMode, + runtimeRevision: res.RuntimeRevision, close: res.Close, } if profile == ProfileNoFS && (s.placementBinder == nil || !sess.EnvironmentRef.Valid()) { @@ -4994,8 +5017,12 @@ func (s *Service) engineAndEnvironmentFor(ctx context.Context, sess *session.Ses return nil, tool.Environment{}, err } } + desiredRuntimeRevision := s.cfg.SharedEngineRevision + if s.cfg.OperationRevision != nil { + desiredRuntimeRevision = s.cfg.OperationRevision(ctx) + } switch { - case hasEngine && se.builtForMode != "" && se.builtForMode != sess.Mode: + case hasEngine && (se.runtimeRevision != desiredRuntimeRevision || se.builtForMode != "" && se.builtForMode != sess.Mode): // CASE 1 (ADR 0030 Layer 3): the registered per-session engine was built for a // DIFFERENT mode than the session now holds — a plan↔execute switch re-resolved // the model. Rebuild through the shared factory path, REPLACING the prior engine. @@ -5023,7 +5050,8 @@ func (s *Service) engineAndEnvironmentFor(ctx context.Context, sess *session.Ses s.mu.Lock() envOverride, hasEnvOverride = s.sessionEnvironments[id] s.mu.Unlock() - case !hasEngine && !s.needsRehydration(sess) && s.cfg.ModeNeedsEngine != nil && s.cfg.SessionEngine != nil && s.cfg.ModeNeedsEngine(sess.Mode): + case !hasEngine && !s.needsRehydration(sess) && s.cfg.SessionEngine != nil && + (desiredRuntimeRevision != s.cfg.SharedEngineRevision || s.cfg.ModeNeedsEngine != nil && s.cfg.ModeNeedsEngine(sess.Mode)): // CASE 2 (ADR 0030 Layer 3): a DEFAULT-FS session that would otherwise ride the // shared engine, but its mode (plan) resolves a DIFFERENT model — promote it to a // per-session factory engine. A default-FS session has the empty selector + a real @@ -5259,6 +5287,7 @@ func (s *Service) buildAndRegisterSessionEngineWithBrokerTools(ctx context.Conte modelID: res.ModelID, reasoningEffort: res.ReasoningEffort, builtForMode: res.BuiltForMode, + runtimeRevision: res.RuntimeRevision, close: res.Close, } s.mu.Lock() @@ -7323,17 +7352,30 @@ func (s *Service) cleanupRunAdmission(id session.SessionID, st *runState, promot // path so concurrent approvals wait for its resumeMu transaction to promote. // The caller holds runEntryMu for id. func (s *Service) beginRunAdmission(parent context.Context, id session.SessionID, sess *session.Session, resumeAdmission bool) (*runState, context.Context, error) { + operationRelease := func() {} + if s.cfg.OperationPin != nil { + var err error + parent, operationRelease, err = s.cfg.OperationPin(parent) + if err != nil { + return nil, nil, err + } + if operationRelease == nil { + operationRelease = func() {} + } + } ctx, cancel := context.WithCancel(parent) - st := &runState{sess: sess, admissionCancel: cancel, settled: make(chan struct{}), resumeAdmission: resumeAdmission, titleRevision: sess.TitleRevision} + st := &runState{sess: sess, admissionCancel: cancel, operationRelease: operationRelease, settled: make(chan struct{}), resumeAdmission: resumeAdmission, titleRevision: sess.TitleRevision} s.mu.Lock() if s.draining.Load() { s.mu.Unlock() cancel() + operationRelease() return nil, nil, fmt.Errorf("%w: %q", ErrUnavailable, id) } if _, exists := s.runs[id]; exists { s.mu.Unlock() cancel() + operationRelease() return nil, nil, fmt.Errorf("%w: session %q already has an active run", ErrFailedPrecondition, id) } s.runs[id] = st @@ -7344,11 +7386,14 @@ func (s *Service) beginRunAdmission(parent context.Context, id session.SessionID func (s *Service) removeRunState(id session.SessionID, st *runState) { removeCapability := false var stopRunContext context.CancelFunc + var releaseOperation func() s.mu.Lock() if s.runs[id] == st { delete(s.runs, id) stopRunContext = st.runContextStop st.runContextStop = nil + releaseOperation = st.operationRelease + st.operationRelease = nil st.settledOnce.Do(func() { close(st.settled) }) removeCapability = st.removeCapabilityOnSettle if h := s.heldLeases[id]; h != nil && !h.valid { @@ -7360,6 +7405,9 @@ func (s *Service) removeRunState(id session.SessionID, st *runState) { if stopRunContext != nil { stopRunContext() } + if releaseOperation != nil { + releaseOperation() + } if removeCapability { s.cfg.MutationCapability.Remove(id) } diff --git a/internal/adapter/server/team.go b/internal/adapter/server/team.go index 639c537519..b9cc9499c8 100644 --- a/internal/adapter/server/team.go +++ b/internal/adapter/server/team.go @@ -487,6 +487,16 @@ func (s *Service) CancelTeammate(ctx context.Context, teamID, member string) err // by Drain itself (that is the bounded GracefulStop's job). The gate starts // false — byte-identical default when Drain has not been called. func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.TeamEvent)) (agent.TeamOutcome, error) { + if s.cfg.OperationPin != nil { + pinned, release, err := s.cfg.OperationPin(ctx) + if err != nil { + return agent.TeamOutcome{}, err + } + if release != nil { + defer release() + } + ctx = pinned + } // Drain gate (ADR 0048, mecak8s): refuse new team runs on a draining // replica before claiming the team — mirrors acquireLease's check. if s.draining.Load() { diff --git a/internal/app/build.go b/internal/app/build.go index 358a8ce5b1..09a6ac2f2e 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -2176,7 +2176,20 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { } return entry.baseURL }, - Engine: engine, + Engine: engine, + OperationPin: func(ctx context.Context) (context.Context, func(), error) { + if assets.mcpRuntimes == nil { + return ctx, func() {}, nil + } + return assets.mcpRuntimes.pin(ctx) + }, + OperationRevision: mcpRuntimeRevision, + SharedEngineRevision: func() uint64 { + if assets.mcpRuntimes == nil { + return 0 + } + return assets.mcpRuntimes.currentRevision() + }(), Store: store, OwnershipEnforced: cfg.OwnershipEnforced, SessionLoadFailureMetric: cfg.SessionLoadFailureMetricsEmitter, @@ -2197,7 +2210,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { PlacementScope: placementScope, SessionReadLedger: sessionReadLedger, RootAuthority: func(kind session.SessionKind) session.Authority { - return mintRootAuthority(assets.rootCatalog, mcpResourceCapabilities(assets.globalMgr), kind) + return mintRuntimeRootAuthority(assets.rootCatalog, assets.mcpRuntimes, kind) }, SharedEngineRoot: cfg.Workspace, // the launch root; a session on a DIFFERENT root routes through the per-session factory (issue #102, docs/adr/0032) // ADR 0237 applied to outbound MCP: the same deployment-policy discipline — @@ -2535,7 +2548,7 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // in buildEngine so it shares the main engine's exact collaborators. SessionEngine: sessFactory, SessionEngineWithTools: assets.sessionFactoryWithTools, - DebugSessionEngine: debugSessionEngineFactory(cfg, reg, provider, store, eventLog, policy, assets.globalMgr), + DebugSessionEngine: debugSessionEngineFactory(cfg, reg, provider, store, eventLog, policy, assets.globalMgr, assets.mcpRuntimes), DebugMCP: assets.globalMgr != nil && len(assets.globalMgr.Tools()) > 0, // ModeNeedsEngine (ADR 0030 Layer 3): tells the Service whether a session's // PermissionMode would resolve a model DIFFERING from the shared engine's model @@ -2895,8 +2908,21 @@ func selectedProviderModel(reg *providerRegistry, providerID, model string) stri // selected, already-connected server-global MCP servers. // //nolint:gocyclo // The dedicated factory keeps target, provider, catalog, and policy validation together. -func debugSessionEngineFactory(cfg Config, reg *providerRegistry, fallback port.LLMProvider, store port.SessionStore, eventLog port.EventLog, basePolicy port.PermissionPolicy, globalMgr *mcp.Manager) server.DebugSessionEngineFactory { +func debugSessionEngineFactory(cfg Config, reg *providerRegistry, fallback port.LLMProvider, store port.SessionStore, eventLog port.EventLog, basePolicy port.PermissionPolicy, globalMgr *mcp.Manager, runtimes *mcpRuntimeSet) server.DebugSessionEngineFactory { return func(ctx context.Context, sel server.ProviderSelector, profile server.SessionProfile, mode session.PermissionMode, target session.SessionID, expectedFingerprint string, expectedOwner *session.Principal, selectedServers, toolCeiling []string) (server.SessionEngineResult, error) { + runtimeRevision := uint64(0) + manager := globalMgr + if runtimes != nil { + pinned, release, err := runtimes.pin(ctx) + if err != nil { + return server.SessionEngineResult{}, err + } + defer release() + ctx = pinned + candidate := mcpRuntimeCandidate(ctx) + manager = candidate.manager + runtimeRevision = candidate.generation + } if profile != server.ProfileNoFS || target == "" || expectedFingerprint == "" { return server.SessionEngineResult{}, fmt.Errorf("%w: debug sessions require no-fs and a bound target incarnation", server.ErrInvalidArgument) } @@ -2925,7 +2951,14 @@ func debugSessionEngineFactory(cfg Config, reg *providerRegistry, fallback port. cat := tool.NewCatalog() cat.MustRegister(sessiondebug.NewBound(target, expectedFingerprint, expectedOwner, cfg.OwnershipEnforced, store, eventLog)) - mounted, err := globalMgr.SelectedTools(selectedServers, toolCeiling) + var mounted []tool.Tool + if manager == nil { + if len(selectedServers) != 0 || len(toolCeiling) != 0 { + return server.SessionEngineResult{}, fmt.Errorf("%w: selected debug MCP tools are unavailable", server.ErrInvalidArgument) + } + } else { + mounted, err = manager.SelectedTools(selectedServers, toolCeiling) + } if err != nil { return server.SessionEngineResult{}, fmt.Errorf("%w: selected debug MCP: %v", server.ErrInvalidArgument, err) } @@ -2953,7 +2986,7 @@ func debugSessionEngineFactory(cfg Config, reg *providerRegistry, fallback port. } return server.SessionEngineResult{ Engine: agent.NewEngine(deps), Capabilities: modelCapability(reg, providerID, model), - ProviderID: providerID, ModelID: model, BuiltForMode: mode, DebugMCPTools: mountedNames, Close: func() error { return nil }, + ProviderID: providerID, ModelID: model, BuiltForMode: mode, RuntimeRevision: runtimeRevision, DebugMCPTools: mountedNames, Close: func() error { return nil }, }, nil } } @@ -3010,7 +3043,9 @@ func sessionEngineFactoryWithTools( assets catalogAssets, guardrailWaiver *modelhook.WaiverHolder, ) server.SessionEngineWithToolsFactory { - return func(ctx context.Context, sel server.ProviderSelector, specs []mcp.ServerConfig, profile server.SessionProfile, workspace string, mode session.PermissionMode, sessionTools []tool.Tool) (server.SessionEngineResult, error) { + build := func(ctx context.Context, sel server.ProviderSelector, specs []mcp.ServerConfig, profile server.SessionProfile, workspace string, mode session.PermissionMode, sessionTools []tool.Tool) (server.SessionEngineResult, error) { + runtimeAssets := mcpCatalogAssets(ctx, assets) + runtimeRevision := mcpRuntimeRevision(ctx) // Pin the CHILD permission resolver to THIS session's base root (issue // #32): a per-session engine's subagents/members/branches must resolve // project permission rules from the SESSION's pre-fork root — the @@ -3191,9 +3226,9 @@ func sessionEngineFactoryWithTools( // Caller-scoped lazy hydration: rebuild this authenticated session's global // and admitted project generations from durable state before binding the // Skill tool. A failed authoritative read clears only these partitions. - skillPartitions := hydrateLearnedSkillPartitions(ctx, cfg, assets, workspace) + skillPartitions := hydrateLearnedSkillPartitions(ctx, cfg, runtimeAssets, workspace) - cat, closeFn := assembleCatalog(ctx, cfg, reg, store, hooks, &assets, catalogSession{ + cat, closeFn := assembleCatalog(ctx, cfg, reg, store, hooks, &runtimeAssets, catalogSession{ provider: resolvedProvider, providerID: resolvedProviderID, model: resolvedModel, @@ -3214,18 +3249,18 @@ func sessionEngineFactoryWithTools( learningCfg.Workspace = workspace learningCfg.LearningMode, learningCfg.LearningSensitivity, learningCfg.SkillActivationPolicy = learningPolicyForWorkspace(cfg, workspace) learningCfg.Model = resolvedModel - learningCfg.attemptRepository = assets.attemptRepository - learningCfg.automaticAdmissionLedger = assets.automaticAdmissionLedger + learningCfg.attemptRepository = runtimeAssets.attemptRepository + learningCfg.automaticAdmissionLedger = runtimeAssets.automaticAdmissionLedger learningCfg.learningSourceStore = store deps := engineDepsForProvider(cfg, resolvedProvider, resolvedModel, windowFn, store, policy, hooks, mcpProvider, instructions) - attachOperatorProfile(&deps, assets.userModelStore) + attachOperatorProfile(&deps, runtimeAssets.userModelStore) deps.LearningMode = learningCfg.LearningMode - deps.LearningObserver = bindMaterializationLifecycle(buildReflectionObserver(learningCfg, resolvedProvider, learningCfg.Model, assets.userModelStore, assets.memStore, assets.reflectionRepository, assets.reflectionCoordinator, assets.learningAdmission, buildProcedureProcessor(learningCfg, assets)), assets.reflectionLifecycle) + deps.LearningObserver = bindMaterializationLifecycle(buildReflectionObserver(learningCfg, resolvedProvider, learningCfg.Model, runtimeAssets.userModelStore, runtimeAssets.memStore, runtimeAssets.reflectionRepository, runtimeAssets.reflectionCoordinator, runtimeAssets.learningAdmission, buildProcedureProcessor(learningCfg, runtimeAssets)), runtimeAssets.reflectionLifecycle) deps.Catalog = cat // Fire-result delivery drain (ADR 0075): the per-session engine's Step 2a // drain reads the SAME durable queue as the main engine. nil (no // schedule-capable store) is the byte-identical no-delivery path. - deps.DeliveryQueue = assets.deliveryQueue + deps.DeliveryQueue = runtimeAssets.deliveryQueue // MODEL-VISIBLE plan-approval contract (issue #206): the gate only fires // when the model CALLS PresentPlan, and nothing else tells it to — an // uninstructed model treats an inline "acceptable" as approval and keeps @@ -3241,7 +3276,7 @@ func sessionEngineFactoryWithTools( // (the StablePrefix layer). A session whose store backs no ScheduleStore // has no tool, so the note is withheld (the model is never told about a // tool it cannot call). - deps.PromptConfig = applySchedulePosture(deps.PromptConfig, scheduleManagerPresent(assets)) + deps.PromptConfig = applySchedulePosture(deps.PromptConfig, scheduleManagerPresent(runtimeAssets)) deps.PromptConfig = applyAgentModelDiscoveryPosture(deps.PromptConfig, deps.Catalog) deps.PromptConfig = applyTemporaryStoragePosture(deps.PromptConfig, shellAvailable(cfg)) deps.PromptConfig = applyDiagnosticsPosture(deps.PromptConfig) @@ -3309,7 +3344,8 @@ func sessionEngineFactoryWithTools( // Echo the mode this engine resolved its model for (ADR 0030 Layer 3), so the // Service stamps sessionEngine.builtForMode from this one source and detects a // later mode→model staleness — the SAME single-source discipline as the ids. - BuiltForMode: mode, + BuiltForMode: mode, + RuntimeRevision: runtimeRevision, // The client MCP servers that actually connected (nil when none were // requested). The factory REPORTS; the Service decides whether a partial // mount is acceptable, because its two callers disagree — see the @@ -3318,6 +3354,7 @@ func sessionEngineFactoryWithTools( Close: closeFn, }, nil } + return pinMCPRuntimeFactory(assets, build) } // catalogContextWindow returns the embedded models.dev catalog's total context @@ -5398,7 +5435,7 @@ func buildCatalog(ctx context.Context, cfg Config, reg *providerRegistry, provid // buildSubagentTool can (a) pull a REFERENCED main server's tools out of this manager // and (b) connect their own INLINE servers. mainMgr is nil when no main servers are // configured (reference entries then resolve to a clear "unknown server" diagnostic). - mainMgr, mcpProvider, mcpInventory, mcpClose := connectMCP(ctx, cfg) + mainMgr, mcpProvider, mcpInventory, mcpRuntimes, mcpClose := connectMCP(ctx, cfg) // Per-project memory store: opt-in via MemoryStoreURL (a remote gRPC driver; // Phase B) or MemoryDir (the flocked reference adapter, opened ONCE here — @@ -5621,6 +5658,7 @@ func buildCatalog(ctx context.Context, cfg Config, reg *providerRegistry, provid assets := catalogAssets{ globalMgr: mainMgr, + mcpRuntimes: mcpRuntimes, agentReg: agentReg, memStore: memStore, userModelStore: userModelStore, @@ -5760,26 +5798,29 @@ func mcpSourceProber(cfg Config) func(ctx context.Context) []mcpsource.SourceInf // the concrete *mcp.Manager (nil when no servers connect) so the per-agent-def // wiring can pull a REFERENCED main server's tools out of it; the same value is // the mcp.Provider used for resources/prompts. -func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, []mcpsource.SourceInfo, func()) { +func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, []mcpsource.SourceInfo, *mcpRuntimeSet, func()) { opts := mcpResolveOptions(cfg) if len(opts.StaticServers) == 0 && !opts.ToolHiveEnabled { _, inventory, _ := mcpsource.Resolve(ctx, mcpsource.ResolveSources(opts)) cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", "toolhive", false, "static", 0) - return nil, nil, inventory, func() {} + return nil, nil, inventory, nil, func() {} } + runtimes := newMCPRuntimeSet(nil) reconciler := newMCPSourceReconciler(mcpReconcilerOptions{ sources: mcpsource.ResolveSources(opts), toolHive: opts.ToolHiveEnabled, build: buildMCPReconcileCandidate(cfg), - // Task 03 replaces this bridge with immutable runtime publication and - // retirement. Until then, changed candidates are safely discarded rather - // than closing the manager already borrowed by assembled catalogs. - publish: func(old, _ *mcpReconcileCandidate) bool { return old == nil }, + publish: runtimes.publish, }) + runtimes.setRetry(reconciler.invalidate) result, err := reconciler.Reconcile(ctx) for _, diagnostic := range result.diagnostics { cfg.diag().Log(ctx, port.LevelWarn, "MCP source reconciliation", "reason", diagnostic) } + closeRuntime := sync.OnceFunc(func() { + reconciler.Close() + runtimes.close() + }) if err != nil || result.candidate == nil || len(result.candidate.configs) == 0 { if err != nil { logMCPReconcileConnectError(ctx, cfg, cfg.MCPServers, err) @@ -5788,11 +5829,11 @@ func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, [] cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", "toolhive", cfg.ToolHiveEnabled, "static", len(cfg.MCPServers)) } - return nil, nil, result.inventory, reconciler.Close + return nil, runtimes, result.inventory, runtimes, closeRuntime } mgr := result.candidate.manager cfg.diag().Log(ctx, port.LevelInfo, "MCP servers connected", "servers", len(result.candidate.configs), "tools", len(mgr.Tools())) - return mgr, mgr, result.inventory, reconciler.Close + return mgr, runtimes, result.inventory, runtimes, closeRuntime } func logMCPReconcileConnectError(ctx context.Context, cfg Config, configs []mcp.ServerConfig, err error) { diff --git a/internal/app/catalog.go b/internal/app/catalog.go index 4bf22eeed7..5876628ca9 100644 --- a/internal/app/catalog.go +++ b/internal/app/catalog.go @@ -72,7 +72,11 @@ import ( // tool, so ForkPreservedCap stays a PROCESS bound (a per-session reaper would // multiply the cap by the number of sessions). type catalogAssets struct { - globalMgr *mcp.Manager + globalMgr *mcp.Manager + // mcpRuntimes owns the revisioned direct MCP manager/provider publication. + // Catalog copies select the operation-pinned manager before assembly; cached + // engines retain only the returned revision tag. + mcpRuntimes *mcpRuntimeSet agentReg *agents.Registry memStore tool.MemoryStore userModelStore tool.MemoryStore diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go index bf9294a06d..451e1a4c66 100644 --- a/internal/app/mcp_reconciler.go +++ b/internal/app/mcp_reconciler.go @@ -53,12 +53,24 @@ type mcpReconcileCandidate struct { generation uint64 pages int bytes int + closeOnce sync.Once + closed atomic.Bool } func (c *mcpReconcileCandidate) close() { - if c != nil && c.manager != nil { - _ = c.manager.Close() + if c == nil { + return } + c.closeOnce.Do(func() { + c.closed.Store(true) + if c.manager != nil { + _ = c.manager.Close() + } + }) +} + +func (c *mcpReconcileCandidate) isClosed() bool { + return c != nil && c.closed.Load() } type mcpReconcileResult struct { @@ -265,13 +277,20 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { r.mu.Lock() old := r.current + r.mu.Unlock() if equalMCPCandidate(old, candidate) { - r.mu.Unlock() candidate.close() result.candidate = old return result, nil } + r.mu.Lock() + r.current = candidate + r.mu.Unlock() if r.publish != nil && !r.publish(old, candidate) { + r.mu.Lock() + if r.current == candidate { + r.current = old + } r.mu.Unlock() candidate.close() result.candidate = old @@ -279,9 +298,9 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { result.diagnostics = appendBoundedDiagnostic(result.diagnostics, "MCP runtime publication is pending integration") return result, nil } - r.current = candidate - r.mu.Unlock() - if old != nil { + // A publication hook owns displaced-runtime retirement. Without one, preserve + // the reconciler's original immediate-close behavior for unit embeddings. + if old != nil && r.publish == nil { old.close() } result.candidate = candidate diff --git a/internal/app/mcp_runtime.go b/internal/app/mcp_runtime.go new file mode 100644 index 0000000000..a620b9b97c --- /dev/null +++ b/internal/app/mcp_runtime.go @@ -0,0 +1,279 @@ +package app + +import ( + "context" + "encoding/json" + "errors" + "sync" + + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/mcp" + serveradapter "github.com/stacklok/mecatl/internal/adapter/server" +) + +var errMCPRuntimeUnavailable = errors.New("mcp runtime is unavailable") + +type mcpRuntimeContextKey struct{} + +type mcpRuntimePin struct { + candidate *mcpReconcileCandidate +} + +// mcpRuntimeSet owns the immutable current direct MCP runtime and the bounded +// retirement set. Engines only retain a revision tag; operation contexts retain +// the pin that keeps a displaced manager alive. +type mcpRuntimeSet struct { + mu sync.Mutex + current *mcpReconcileCandidate + empty *mcpReconcileCandidate + pins map[*mcpReconcileCandidate]int + retired []*mcpReconcileCandidate + deferred bool + retry func() + closed bool +} + +func newMCPRuntimeSet(retry func()) *mcpRuntimeSet { + return &mcpRuntimeSet{empty: &mcpReconcileCandidate{}, pins: make(map[*mcpReconcileCandidate]int), retry: retry} +} + +func (s *mcpRuntimeSet) setRetry(retry func()) { + s.mu.Lock() + s.retry = retry + s.mu.Unlock() +} + +func (s *mcpRuntimeSet) publish(old, candidate *mcpReconcileCandidate) bool { + if candidate == nil { + return false + } + s.mu.Lock() + if s.closed || s.current != old { + s.mu.Unlock() + candidate.close() + return false + } + if old != nil && s.pins[old] > 0 && len(s.retired) >= maxMCPRetainedRuntimes { + s.deferred = true + s.mu.Unlock() + candidate.close() + return false + } + s.current = candidate + if old != nil { + if s.pins[old] == 0 { + s.mu.Unlock() + old.close() + return true + } + s.retired = append(s.retired, old) + } + s.mu.Unlock() + return true +} + +func (s *mcpRuntimeSet) pin(ctx context.Context) (context.Context, func(), error) { + if inherited, ok := ctx.Value(mcpRuntimeContextKey{}).(*mcpRuntimePin); ok && inherited != nil && inherited.candidate != nil { + return ctx, func() {}, nil + } + s.mu.Lock() + if s.closed { + s.mu.Unlock() + return nil, nil, errMCPRuntimeUnavailable + } + candidate := s.current + if candidate == nil { + candidate = s.empty + } + s.pins[candidate]++ + s.mu.Unlock() + var once sync.Once + release := func() { once.Do(func() { s.release(candidate) }) } + return context.WithValue(ctx, mcpRuntimeContextKey{}, &mcpRuntimePin{candidate: candidate}), release, nil +} + +func (s *mcpRuntimeSet) release(candidate *mcpReconcileCandidate) { + var closeCandidate *mcpReconcileCandidate + var retry func() + s.mu.Lock() + if n := s.pins[candidate]; n > 1 { + s.pins[candidate] = n - 1 + } else { + delete(s.pins, candidate) + for i, retired := range s.retired { + if retired == candidate { + closeCandidate = retired + s.retired = append(s.retired[:i], s.retired[i+1:]...) + break + } + } + if closeCandidate != nil && s.deferred && !s.closed { + s.deferred = false + retry = s.retry + } + } + s.mu.Unlock() + closeCandidate.close() + if retry != nil { + retry() + } +} + +func (s *mcpRuntimeSet) currentRevision() uint64 { + s.mu.Lock() + defer s.mu.Unlock() + if s.current == nil { + return 0 + } + return s.current.generation +} + +func (s *mcpRuntimeSet) currentToolNames() []string { + s.mu.Lock() + defer s.mu.Unlock() + if s.current == nil { + return nil + } + out := make([]string, 0, len(s.current.tools)) + for _, meta := range s.current.tools { + out = append(out, meta.Name) + } + return out +} + +func (s *mcpRuntimeSet) currentResourceServers() []string { + s.mu.Lock() + defer s.mu.Unlock() + if s.current == nil { + return nil + } + seen := make(map[string]struct{}) + out := make([]string, 0) + for _, resource := range s.current.resources { + if _, ok := seen[resource.Server]; ok { + continue + } + seen[resource.Server] = struct{}{} + out = append(out, resource.Server) + } + return out +} + +func (s *mcpRuntimeSet) close() { + s.mu.Lock() + if s.closed { + s.mu.Unlock() + return + } + s.closed = true + current := s.current + retired := append([]*mcpReconcileCandidate(nil), s.retired...) + s.current = nil + s.retired = nil + s.mu.Unlock() + current.close() + for _, candidate := range retired { + candidate.close() + } +} + +func mcpRuntimeCandidate(ctx context.Context) *mcpReconcileCandidate { + pin, _ := ctx.Value(mcpRuntimeContextKey{}).(*mcpRuntimePin) + if pin == nil { + return nil + } + return pin.candidate +} + +func mcpRuntimeRevision(ctx context.Context) uint64 { + candidate := mcpRuntimeCandidate(ctx) + if candidate == nil { + return 0 + } + return candidate.generation +} + +func pinCatalogAssets(ctx context.Context, assets catalogAssets) (context.Context, catalogAssets, uint64, func(), error) { + if assets.mcpRuntimes == nil { + return ctx, assets, 0, func() {}, nil + } + pinned, release, err := assets.mcpRuntimes.pin(ctx) + if err != nil { + return nil, catalogAssets{}, 0, nil, err + } + candidate := mcpRuntimeCandidate(pinned) + assets.globalMgr = candidate.manager + return pinned, assets, candidate.generation, release, nil +} + +func mcpCatalogAssets(ctx context.Context, assets catalogAssets) catalogAssets { + if candidate := mcpRuntimeCandidate(ctx); candidate != nil { + assets.globalMgr = candidate.manager + } + return assets +} + +func pinMCPRuntimeFactory(assets catalogAssets, build serveradapter.SessionEngineWithToolsFactory) serveradapter.SessionEngineWithToolsFactory { + return func(ctx context.Context, sel serveradapter.ProviderSelector, specs []mcp.ServerConfig, profile serveradapter.SessionProfile, workspace string, mode session.PermissionMode, sessionTools []tool.Tool) (serveradapter.SessionEngineResult, error) { + pinned, _, _, release, err := pinCatalogAssets(ctx, assets) + if err != nil { + return serveradapter.SessionEngineResult{}, err + } + defer release() + return build(pinned, sel, specs, profile, workspace, mode, sessionTools) + } +} + +func (s *mcpRuntimeSet) withManager(ctx context.Context, use func(context.Context, *mcp.Manager) error) error { + pinned, release, err := s.pin(ctx) + if err != nil { + return err + } + defer release() + candidate := mcpRuntimeCandidate(pinned) + if candidate == nil || candidate.manager == nil { + return errMCPRuntimeUnavailable + } + return use(pinned, candidate.manager) +} + +func (s *mcpRuntimeSet) ListResources(ctx context.Context, server string) (out []mcp.Resource, err error) { + err = s.withManager(ctx, func(ctx context.Context, manager *mcp.Manager) error { + out, err = manager.ListResources(ctx, server) + return err + }) + return out, err +} + +func (s *mcpRuntimeSet) ReadResource(ctx context.Context, server, uri string) (out mcp.ResourceContents, err error) { + err = s.withManager(ctx, func(ctx context.Context, manager *mcp.Manager) error { + out, err = manager.ReadResource(ctx, server, uri) + return err + }) + return out, err +} + +func (s *mcpRuntimeSet) ListPrompts(ctx context.Context, server string) (out []mcp.Prompt, err error) { + err = s.withManager(ctx, func(ctx context.Context, manager *mcp.Manager) error { + out, err = manager.ListPrompts(ctx, server) + return err + }) + return out, err +} + +func (s *mcpRuntimeSet) GetPrompt(ctx context.Context, server, name string, args map[string]string) (out mcp.PromptResult, err error) { + err = s.withManager(ctx, func(ctx context.Context, manager *mcp.Manager) error { + out, err = manager.GetPrompt(ctx, server, name, args) + return err + }) + return out, err +} + +func (s *mcpRuntimeSet) CallTool(ctx context.Context, server, name string, args json.RawMessage) (out mcp.CallResult, err error) { + err = s.withManager(ctx, func(ctx context.Context, manager *mcp.Manager) error { + out, err = manager.CallTool(ctx, server, name, args) + return err + }) + return out, err +} diff --git a/internal/app/mcp_runtime_publication_test.go b/internal/app/mcp_runtime_publication_test.go new file mode 100644 index 0000000000..ab60552b54 --- /dev/null +++ b/internal/app/mcp_runtime_publication_test.go @@ -0,0 +1,508 @@ +package app + +import ( + "context" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/stacklok/mecatl/engine/adapter/memstore" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/adapter/nofs" + "github.com/stacklok/mecatl/engine/adapter/permpolicy" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/governance" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/prompt" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/agents" + "github.com/stacklok/mecatl/internal/adapter/hookexec" + "github.com/stacklok/mecatl/internal/adapter/mcp" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +func runtimeTestCandidate(revision uint64, names ...string) *mcpReconcileCandidate { + tools := make([]mcpToolMeta, 0, len(names)) + for _, name := range names { + tools = append(tools, mcpToolMeta{Name: name, Schema: `{}`}) + } + return &mcpReconcileCandidate{generation: revision, tools: tools} +} + +func TestMCPSourceReconciliation_Scenario2_AllOrNothingPublication(t *testing.T) { + var retries atomic.Int32 + runtimes := newMCPRuntimeSet(func() { retries.Add(1) }) + first := runtimeTestCandidate(1, "mcp__one__read") + if !runtimes.publish(nil, first) { + t.Fatal("initial complete runtime was not published") + } + ctx, pin, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + if got := mcpRuntimeRevision(ctx); got != 1 { + t.Fatalf("pinned revision = %d, want 1", got) + } + second := runtimeTestCandidate(2, "mcp__two__read") + if !runtimes.publish(first, second) { + t.Fatal("complete successor was not published") + } + if got := runtimes.currentRevision(); got != 2 { + t.Fatalf("current revision = %d, want 2", got) + } + if first.isClosed() { + t.Fatal("pinned retired runtime closed before drain") + } + pin() + if !first.isClosed() { + t.Fatal("retired runtime did not close after drain") + } + if retries.Load() != 0 { + t.Fatalf("unexpected deferred retries = %d", retries.Load()) + } + equalLeft := runtimeTestCandidate(10, "mcp__same__tool") + equalLeft.resources = []mcp.Resource{{Server: "same", URI: "mcp://same"}} + equalLeft.prompts = []mcp.Prompt{{Server: "same", Name: "prompt"}} + equalRight := runtimeTestCandidate(11, "mcp__same__tool") + equalRight.resources = append([]mcp.Resource(nil), equalLeft.resources...) + equalRight.prompts = append([]mcp.Prompt(nil), equalLeft.prompts...) + if !equalMCPCandidate(equalLeft, equalRight) { + t.Fatal("equivalent complete runtime metadata was treated as changed") + } + equalRight.resources[0].URI = "mcp://changed" + if equalMCPCandidate(equalLeft, equalRight) { + t.Fatal("resource-only change did not require publication") + } + equalRight.resources[0] = equalLeft.resources[0] + equalRight.prompts[0].Description = "changed" + if equalMCPCandidate(equalLeft, equalRight) { + t.Fatal("prompt-only change did not require publication") + } + runtimes.close() +} + +func TestMCPSourceReconciliation_Scenario2_ProductionEngineRevisionMatrix(t *testing.T) { + provider := mockllm.New() + reg := regForTest(provider, providerOpenAI, "test-model") + store := memstore.New() + policy := permpolicy.NewPolicy(defaultRules(), nil) + runtimes := newMCPRuntimeSet(nil) + first := runtimeTestCandidate(1) + if !runtimes.publish(nil, first) { + t.Fatal("publish first runtime") + } + assets := catalogAssets{mcpRuntimes: runtimes} + factory := sessionEngineFactory(Config{Model: "test-model"}, reg, provider, store, policy, hookexec.New(nil), runtimes, prompt.RootAssembler{}, assets, nil) + + ctx, release, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + rows := []struct { + name string + profile server.SessionProfile + mode session.PermissionMode + sel server.ProviderSelector + specs []mcp.ServerConfig + }{ + {name: "default", profile: server.ProfileDefault}, + {name: "selector", profile: server.ProfileDefault, sel: server.ProviderSelector{ProviderID: providerOpenAI, ModelID: "test-model"}}, + {name: "no-fs", profile: server.ProfileNoFS}, + {name: "client-mcp", profile: server.ProfileDefault, specs: []mcp.ServerConfig{{Name: "client", URL: newMCPTestServer(t)}}}, + {name: "mode", profile: server.ProfileDefault, mode: session.ModePlan}, + } + for _, row := range rows { + t.Run(row.name, func(t *testing.T) { + result, buildErr := factory(ctx, row.sel, row.specs, row.profile, "", row.mode) + if buildErr != nil { + t.Fatal(buildErr) + } + defer result.Close() + if result.RuntimeRevision != 1 { + t.Fatalf("runtime revision = %d, want 1", result.RuntimeRevision) + } + }) + } + target := session.New("debug-target", session.ModeDefault, session.EnvironmentRef{Kind: session.EnvKindLocal, ID: "/target", Revision: "r1"}, session.Limits{}, time.Unix(0, 0)) + if err := store.Save(ctx, target); err != nil { + t.Fatal(err) + } + debugFactory := debugSessionEngineFactory(Config{Model: "test-model"}, reg, provider, store, nil, policy, nil, runtimes) + debugResult, err := debugFactory(ctx, server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, nil, nil) + if err != nil { + t.Fatal(err) + } + if debugResult.RuntimeRevision != 1 { + t.Fatalf("debug runtime revision = %d, want 1", debugResult.RuntimeRevision) + } + if _, err := debugFactory(ctx, server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, []string{"missing"}, []string{"mcp__missing__tool"}); err == nil { + t.Fatal("debug factory accepted selected names absent from the pinned runtime") + } + release() + runtimes.close() +} + +func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T) { + var successorRetries atomic.Int32 + runtimes := newMCPRuntimeSet(func() { successorRetries.Add(1) }) + current := runtimeTestCandidate(1) + if !runtimes.publish(nil, current) { + t.Fatal("publish initial runtime") + } + pins := make([]func(), 0, maxMCPRetainedRuntimes) + for i := 0; i < maxMCPRetainedRuntimes; i++ { + _, release, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + pins = append(pins, release) + next := runtimeTestCandidate(uint64(i + 2)) + if !runtimes.publish(current, next) { + t.Fatalf("publication %d unexpectedly deferred", i+2) + } + current = next + } + _, currentPin, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + pins = append(pins, currentPin) + blocked := runtimeTestCandidate(uint64(maxMCPRetainedRuntimes + 2)) + if runtimes.publish(current, blocked) { + t.Fatal("publication succeeded with full retirement set") + } + if !blocked.isClosed() { + t.Fatal("unpublishable candidate was not closed") + } + pins[0]() + if successorRetries.Load() != 1 { + t.Fatalf("deferred successor retries after first drain = %d, want 1", successorRetries.Load()) + } + for _, release := range pins[1:] { + release() + } + if successorRetries.Load() != 1 { + t.Fatalf("deferred successor was retried more than once: %d", successorRetries.Load()) + } + runtimes.close() + + // Exercise the real Service run-entry and production session factory. The + // cached shared engine is revision 1; a revision-2 root pin must rebuild it + // before use, and that pin must outlive event drain until FinishRun. + provider := mockllm.New(mockllm.TextTurn("done")) + reg := regForTest(provider, providerOpenAI, "test-model") + store := memstore.New() + policy := permpolicy.NewPolicy(defaultRules(), nil) + runRuntimes := newMCPRuntimeSet(nil) + rev1 := runtimeTestCandidate(1) + if !runRuntimes.publish(nil, rev1) { + t.Fatal("publish service revision 1") + } + assets := catalogAssets{mcpRuntimes: runRuntimes} + productionFactory := sessionEngineFactory(Config{Model: "test-model"}, reg, provider, store, policy, hookexec.New(nil), runRuntimes, prompt.RootAssembler{}, assets, nil) + initial := agent.NewEngine(agent.Deps{LLM: provider, Catalog: tool.NewCatalog(), Model: "test-model"}) + var builtRevision atomic.Uint64 + factory := func(ctx context.Context, sel server.ProviderSelector, specs []mcp.ServerConfig, profile server.SessionProfile, workspace string, mode session.PermissionMode) (server.SessionEngineResult, error) { + result, buildErr := productionFactory(ctx, sel, specs, profile, workspace, mode) + if buildErr == nil { + builtRevision.Store(result.RuntimeRevision) + } + return result, buildErr + } + svc, err := newTestServerService(server.Config{ + Engine: initial, Store: store, SessionEngine: factory, + SharedEngineRevision: 1, OperationPin: runRuntimes.pin, OperationRevision: mcpRuntimeRevision, + }) + if err != nil { + t.Fatal(err) + } + defer svc.Close() + sess, err := svc.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatal(err) + } + rev2 := runtimeTestCandidate(2) + if !runRuntimes.publish(rev1, rev2) { + t.Fatal("publish service revision 2") + } + run, err := svc.StartRunContent(context.Background(), sess.ID, "go", nil) + if err != nil { + t.Fatal(err) + } + for range run.Events() { + } + if got := builtRevision.Load(); got != 2 { + t.Fatalf("production run rebuilt revision = %d, want 2", got) + } + rev3 := runtimeTestCandidate(3) + if !runRuntimes.publish(rev2, rev3) { + t.Fatal("publish service revision 3") + } + if rev2.isClosed() { + t.Fatal("root runtime pin drained before FinishRun") + } + svc.FinishRun(sess.ID, run) + if !rev2.isClosed() { + t.Fatal("root runtime pin did not drain at FinishRun") + } + runRuntimes.close() +} + +func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *testing.T) { + const ( + name = "mcp__svc__echo" + unavailable = "tool is currently unavailable; do not retry unless the catalog changes" + ) + ctx := context.Background() + firstManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "first")) + runtimes := newMCPRuntimeSet(nil) + first := &mcpReconcileCandidate{manager: firstManager, generation: 1, tools: toolMetadata(firstManager.Tools())} + if !runtimes.publish(nil, first) { + t.Fatal("publish initial runtime") + } + emptyManager, err := mcp.NewCompleteManager(ctx, nil, nil) + if err != nil { + t.Fatal(err) + } + empty := &mcpReconcileCandidate{manager: emptyManager, generation: 2} + if !runtimes.publish(first, empty) { + t.Fatal("publish successful empty removal") + } + + var requests []port.LLMRequest + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + requests = append(requests, req) + })}, + mockllm.ToolCallTurn(session.NewToolCall("removed", name, []byte(`{"text":"removed"}`))), + mockllm.TextTurn("removed observed"), + mockllm.ToolCallTurn(session.NewToolCall("unknown", "mcp__svc__never-granted", []byte(`{}`))), + mockllm.TextTurn("unknown observed"), + mockllm.ToolCallTurn(session.NewToolCall("reappeared", name, []byte(`{"text":"again"}`))), + mockllm.TextTurn("reappeared observed"), + ) + reg := regForTest(provider, providerOpenAI, "test-model") + store := memstore.New() + policy := permpolicy.NewPolicy([]governance.Rule{{Scope: governance.ScopeCLI, Tool: "*", Effect: governance.Allow}}, nil) + authorityEvaluator, _, err := selectAuthorityEvaluator("local", "") + if err != nil { + t.Fatal(err) + } + assets := catalogAssets{mcpRuntimes: runtimes} + factory := sessionEngineFactory(Config{Model: "test-model", authorityEvaluator: authorityEvaluator}, reg, provider, store, policy, hookexec.New(nil), runtimes, prompt.RootAssembler{}, assets, nil) + sess := session.New("availability", session.ModeDefault, session.EnvironmentRef{Kind: session.EnvKindNoFS, ID: "none", Revision: "in-tree-v1"}, session.Limits{}, time.Unix(0, 0)) + if err := sess.BindAuthority(session.Authority{ + CapabilitySet: governanceCapability(name), + Provenance: "test", DefinitionIdentity: "test", + }); err != nil { + t.Fatal(err) + } + env := testEnvironment(nofs.New(), nil) + runOnce := func(wantRevision uint64) string { + t.Helper() + pinned, release, pinErr := runtimes.pin(ctx) + if pinErr != nil { + t.Fatal(pinErr) + } + defer release() + result, buildErr := factory(pinned, server.ProviderSelector{}, nil, server.ProfileNoFS, "", session.ModeDefault) + if buildErr != nil { + t.Fatal(buildErr) + } + defer result.Close() + if result.RuntimeRevision != wantRevision { + t.Fatalf("engine revision = %d, want %d", result.RuntimeRevision, wantRevision) + } + var content string + var observed []session.EventType + run := result.Engine.Run(pinned, sess, env, agent.RunRequest{Text: "exercise current MCP availability"}) + for ev := range run.Events() { + observed = append(observed, ev.Type) + if ev.Type == session.EvPermissionAsk { + run.Approve(ev.Ask.AskID, session.VerdictAllowOnce) + } + if ev.Type == session.EvToolResult && ev.ToolResult != nil { + content = ev.ToolResult.Content + } + } + if content == "" { + t.Logf("events=%v state=%s history=%+v", observed, sess.State, sess.Conversation.Messages) + } + return content + } + + if got := runOnce(2); got != unavailable { + t.Fatalf("removed granted call result = %q, want %q", got, unavailable) + } + if len(requests) == 0 || requestHasTool(requests[0], name) { + t.Fatal("removed granted name remained in model tool specs") + } + if err := sess.Reopen(); err != nil { + t.Fatal(err) + } + if got := runOnce(2); got == unavailable || !strings.Contains(got, "unknown tool") { + t.Fatalf("ungranted absent call result = %q, want ordinary unknown-tool error", got) + } + + if err := sess.Reopen(); err != nil { + t.Fatal(err) + } + secondManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "second")) + second := &mcpReconcileCandidate{manager: secondManager, generation: 3, tools: toolMetadata(secondManager.Tools())} + if !runtimes.publish(empty, second) { + t.Fatal("publish exact-name reappearance") + } + beforeReappearance := len(requests) + if got := runOnce(3); !strings.Contains(got, "second") { + t.Fatalf("reappeared same-name call result = %q, want new endpoint result", got) + } + reappearedAdvertised := false + for _, req := range requests[beforeReappearance:] { + reappearedAdvertised = reappearedAdvertised || requestHasTool(req, name) + } + if !reappearedAdvertised { + t.Fatal("reappeared exact name was not restored to model specs") + } + if got := sess.Authority.CapabilitySet.Tools; len(got) != 1 || got[0] != name { + t.Fatalf("same-name endpoint drift changed durable grant: %v", got) + } + runtimes.close() +} + +func requestHasTool(req port.LLMRequest, name string) bool { + for _, spec := range req.Tools { + if spec.Name == name { + return true + } + } + return false +} + +func TestMCPSourceReconciliation_Scenario3_DelegationAndResumeNameSemantics(t *testing.T) { + const ( + name = "mcp__svc__echo" + childID = "subagent-parent-p1" + unavailable = "tool is currently unavailable; do not retry unless the catalog changes" + ) + ctx := context.Background() + manager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "pinned-old")) + runtimes := newMCPRuntimeSet(nil) + old := &mcpReconcileCandidate{manager: manager, generation: 1, tools: toolMetadata(manager.Tools())} + if !runtimes.publish(nil, old) { + t.Fatal("publish old runtime") + } + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("p1", "Subagent", []byte(`{"prompt":"use the referenced service","agent":"ref-task"}`))), + mockllm.ToolCallTurn(session.NewToolCall("child-old", name, []byte(`{"text":"old"}`))), + mockllm.TextTurn("old child done"), + mockllm.TextTurn("parent old done"), + mockllm.ToolCallTurn(session.NewToolCall("p2", "Subagent", []byte(`{"resume":"`+childID+`","prompt":"retry the same service"}`))), + mockllm.ToolCallTurn(session.NewToolCall("child-resume", name, []byte(`{"text":"resume"}`))), + mockllm.TextTurn("resumed child done"), + mockllm.TextTurn("parent resume done"), + ) + reg := regForTest(provider, providerOpenAI, "test-model") + store := memstore.New() + policy := permpolicy.NewPolicy(defaultRules(), nil) + authorityEvaluator, _, err := selectAuthorityEvaluator("local", "") + if err != nil { + t.Fatal(err) + } + defs := agents.NewRegistry([]agents.AgentDef{{ + Name: "ref-task", Description: "reference test", Tools: []string{"Read"}, + MCPServers: []agents.AgentMCPServer{{Name: "svc"}}, + }}) + cfg := Config{Model: "test-model", authorityEvaluator: authorityEvaluator} + assets := catalogAssets{mcpRuntimes: runtimes, agentReg: defs} + factory := sessionEngineFactory(cfg, reg, provider, store, policy, hookexec.New(nil), runtimes, prompt.RootAssembler{}, assets, nil) + parent := session.New("parent", session.ModeDefault, session.EnvironmentRef{Kind: session.EnvKindLocal, ID: "/ws", Revision: "in-tree-v1"}, session.Limits{MaxTurns: 8}, time.Unix(0, 0)) + if err := parent.BindAuthority(session.Authority{ + CapabilitySet: governance.CapabilitySet{Tools: []string{"Subagent", name}, RemainingDelegationDepth: 1, FileSystem: true}, + Provenance: "test", DefinitionIdentity: "test", + }); err != nil { + t.Fatal(err) + } + drive := func(pinned context.Context, result server.SessionEngineResult) { + t.Helper() + run := result.Engine.Run(pinned, parent, memEnvironment("/ws"), agent.RunRequest{Text: "delegate"}) + for ev := range run.Events() { + if ev.Type == session.EvPermissionAsk { + run.Approve(ev.Ask.AskID, session.VerdictAllowOnce) + } + } + } + + oldCtx, oldRelease, err := runtimes.pin(ctx) + if err != nil { + t.Fatal(err) + } + oldEngine, err := factory(oldCtx, server.ProviderSelector{}, nil, server.ProfileDefault, "/ws", session.ModeDefault) + if err != nil { + t.Fatal(err) + } + emptyManager, err := mcp.NewCompleteManager(ctx, nil, nil) + if err != nil { + t.Fatal(err) + } + removed := &mcpReconcileCandidate{manager: emptyManager, generation: 2} + if !runtimes.publish(old, removed) { + t.Fatal("publish removal while parent is pinned") + } + drive(oldCtx, oldEngine) + child, err := store.Load(ctx, childID) + if err != nil { + t.Fatal(err) + } + if got := latestToolResult(child, "child-old"); !strings.Contains(got, "pinned-old") { + t.Fatalf("pre-publication child did not inherit old runtime: %q", got) + } + if old.isClosed() { + t.Fatal("parent-pinned runtime closed before delegated child completed") + } + oldRelease() + if !old.isClosed() { + t.Fatal("old runtime did not retire after parent and child drained") + } + _ = oldEngine.Close() + + if err := parent.Reopen(); err != nil { + t.Fatal(err) + } + newCtx, newRelease, err := runtimes.pin(ctx) + if err != nil { + t.Fatal(err) + } + newEngine, err := factory(newCtx, server.ProviderSelector{}, nil, server.ProfileDefault, "/ws", session.ModeDefault) + if err != nil { + t.Fatal(err) + } + defer newEngine.Close() + drive(newCtx, newEngine) + resumed, err := store.Load(ctx, childID) + if err != nil { + t.Fatal(err) + } + if got := latestToolResult(resumed, "child-resume"); got != unavailable { + t.Fatalf("resumed granted child call = %q, want %q", got, unavailable) + } + if got := mcpRuntimeRevision(newCtx); got != 2 { + t.Fatalf("post-publication resume revision = %d, want 2", got) + } + newRelease() + runtimes.close() +} + +func latestToolResult(sess *session.Session, callID string) string { + for i := len(sess.Conversation.Messages) - 1; i >= 0; i-- { + result := sess.Conversation.Messages[i].ToolResult + if result != nil && result.CallID == session.ToolCallID(callID) { + return result.Content + } + } + return "" +} + +func governanceCapability(names ...string) governance.CapabilitySet { + return governance.CapabilitySet{Tools: append([]string(nil), names...)} +} diff --git a/internal/app/root_authority.go b/internal/app/root_authority.go index d60a9df6a3..829bc08c9b 100644 --- a/internal/app/root_authority.go +++ b/internal/app/root_authority.go @@ -147,3 +147,23 @@ func mintRootAuthority(catalog *tool.Catalog, resources []string, kind session.S DefinitionIdentity: rootAuthorityDefinition, } } + +func mintRuntimeRootAuthority(catalog *tool.Catalog, runtimes *mcpRuntimeSet, kind session.SessionKind) session.Authority { + if runtimes == nil || kind == session.SessionKindDebug { + return mintRootAuthority(catalog, nil, kind) + } + authority := mintRootAuthority(catalog, nil, kind) + names := authority.CapabilitySet.Tools[:0] + for _, name := range authority.CapabilitySet.Tools { + if strings.HasPrefix(name, "mcp__") || strings.HasPrefix(name, "mcp_resource__") { + continue + } + names = append(names, name) + } + names = append(names, runtimes.currentToolNames()...) + for _, server := range runtimes.currentResourceServers() { + names = append(names, governance.MCPResourceCapability(server)) + } + authority.CapabilitySet.Tools = names + return authority +} diff --git a/internal/app/session_debug_test.go b/internal/app/session_debug_test.go index dee7d5afb4..e02a97fa41 100644 --- a/internal/app/session_debug_test.go +++ b/internal/app/session_debug_test.go @@ -69,7 +69,7 @@ func TestDebugSessionMCPPublishJourneyRequiresFreshApproval(t *testing.T) { ) cfg := Config{Model: "mock-model"} reg := regForTest(provider, providerOpenAI, cfg.Model) - factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, manager) + factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, manager, nil) res, err := factory(ctx, server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, []string{"github"}, nil) if err != nil { t.Fatal(err) @@ -137,7 +137,7 @@ func TestDebugSessionSelectedGlobalMCPIsExactAndBorrowed(t *testing.T) { provider := mockllm.New(mockllm.TextTurn("done")) cfg := Config{Model: "mock-model"} reg := regForTest(provider, providerOpenAI, cfg.Model) - factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, manager) + factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, manager, nil) res, err := factory(ctx, server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, []string{"github"}, nil) if err != nil { t.Fatal(err) @@ -178,7 +178,7 @@ func TestDebugSessionFactoryExactCatalogAndStablePrefix(t *testing.T) { })}, mockllm.TextTurn("debug done"), mockllm.TextTurn("normal done")) cfg := Config{Model: "mock-model"} reg := regForTest(provider, providerOpenAI, cfg.Model) - factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, nil) + factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, nil, nil) res, err := factory(context.Background(), server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, nil, nil) if err != nil { t.Fatalf("debug factory: %v", err) @@ -238,7 +238,7 @@ func TestDebugSessionFactoryPreservesBaseInspectPolicy(t *testing.T) { ) cfg := Config{Model: "mock-model"} base := permpolicy.NewPolicy([]governance.Rule{{Scope: governance.ScopeUser, Tool: sessiondebug.ToolName, Effect: tc.effect}}, nil) - factory := debugSessionEngineFactory(cfg, regForTest(provider, providerOpenAI, cfg.Model), provider, store, nil, base, nil) + factory := debugSessionEngineFactory(cfg, regForTest(provider, providerOpenAI, cfg.Model), provider, store, nil, base, nil, nil) res, err := factory(ctx, server.ProviderSelector{}, server.ProfileNoFS, session.ModeDefault, target.ID, session.DebugTargetFingerprint(target), target.Owner, nil, nil) if err != nil { t.Fatal(err) @@ -274,7 +274,7 @@ func TestDebugSessionRestartRehydratesBoundEngine(t *testing.T) { ) cfg := Config{Model: "mock-model"} reg := regForTest(provider, providerOpenAI, cfg.Model) - factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, nil) + factory := debugSessionEngineFactory(cfg, reg, provider, store, nil, nil, nil, nil) shared := agent.NewEngine(agent.Deps{LLM: provider, Catalog: tool.NewCatalog(), Model: cfg.Model}) newService := func() *server.Service { svc, err := newTestServerService(server.Config{ From fb17667325106c49a93e849b0924758b9a5f0dfd Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Wed, 16 Sep 2026 21:14:50 +0200 Subject: [PATCH 04/14] fix(mcp): retain runtime pins through direct teams Co-Authored-By: mecatl --- docs/adr/0027-cloud-native.md | 2 +- docs/design/IMPLEMENTATION-NOTES.md | 8 +- internal/adapter/server/service.go | 27 ++++ internal/adapter/server/team.go | 80 ++++++++++-- internal/app/build.go | 11 ++ internal/app/mcp_runtime.go | 38 ++++-- internal/app/mcp_runtime_publication_test.go | 128 +++++++++++++++++++ 7 files changed, 269 insertions(+), 25 deletions(-) diff --git a/docs/adr/0027-cloud-native.md b/docs/adr/0027-cloud-native.md index 4fe3e69c64..06129fcdd9 100644 --- a/docs/adr/0027-cloud-native.md +++ b/docs/adr/0027-cloud-native.md @@ -799,7 +799,7 @@ durable artifact survives and is reloaded), or **lost** (gone, possibly leaking) | 61 | Provider OIDC issuer and gateway HTTP clients | `internal/cliconfig.NativeEndpointRuntime` | process, one pair per provider runtime | clients have no independent goroutine; their transports die with the runtime/loader | reconstructible from explicit issuer/gateway trust policies and CA bundles; neither trust root is reused for the other | `internal/cliconfig/native_endpoint.go` (`OpenNativeEndpointRuntime`, `nativeTrustClient`) | | 62 | Provider OIDC keyring and encrypted Store handles | `internal/cliconfig.NativeEndpointRuntime` | operation handles; serving Store handles live for the runtime | Login/status/logout defer Store close; `Source` handles close at runtime/loader close | reopened only from explicit `credential_store.oidc.home` and provider identity; no discovery, migration, plaintext, or environment fallback | `internal/cliconfig/native_endpoint.go` (`open`, `Login`, `Status`, `Logout`, `Close`); `internal/adapter/llmendpoint/lifecycle.go` (`NewProtectedStore`) | | 63 | Provider OIDC transaction-lock handles | `llmendpoint.TransactionLocker` | one provider lifecycle operation | `With` releases its owner-only flock after the callback; no lock is retained across gateway requests | reset/reacquired after restart from the hashed provider identity; the durable record remains the source of truth | `internal/adapter/llmendpoint/lifecycle.go` (`TransactionLocker`, `With`) | -| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, immutable current and bounded retiring runtimes, one deferred-successor bit, revision-tagged engine caches, and run/operation pins | `app.Build` through `connectMCP`; `server.Service` owns root-run pin lifetime | process publication state plus one pin per active root run or resource/prompt operation | the Build close fold first drains `Service`, then invokes `mcpSourceReconciler.Close` and `mcpRuntimeSet.close`; publication never mutates a live manager, a displaced runtime closes only after its pins drain, and a full retirement set discards the candidate without force-close and schedules one retry after drain. Cached-engine close never closes a direct manager. Caller cancellation only stops that caller's reconciliation wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects one complete runtime, and begins with no source LKG, retired runtime, pin, cache revision, or pending invalidation; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `mcpReconcileCandidate`, `Close`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`, `pin`, `publish`, `release`); `internal/adapter/server/service.go` (`beginRunAdmission`, `engineAndEnvironmentFor`, `SessionEngineResult.RuntimeRevision`); `internal/app/build.go` (`connectMCP`) | +| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, immutable current and bounded retiring runtimes, one deferred-successor bit, revision-tagged engine caches, and run/operation pins | `app.Build` through `connectMCP`; `server.Service` owns root-run and direct-Team pin lifetime | process publication state plus one pin per active root run or resource/prompt operation; a direct Team retains its creation pin until `RunTeam`, explicit cleanup, or Service shutdown because member engines are built during creation | the Build close fold first drains `Service`, including created-but-not-run Teams, then invokes `mcpSourceReconciler.Close` and `mcpRuntimeSet.close`; publication never mutates a live manager, a displaced runtime closes only after its pins drain, and a full retirement set discards the candidate without force-close and schedules one retry after drain. Cached-engine close never closes a direct manager. Caller cancellation only stops that caller's reconciliation wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects one complete runtime, and begins with no source LKG, retired runtime, pin, cache revision, or pending invalidation; direct Teams are process-local and are not restored, so their retained pins disappear with them; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `mcpReconcileCandidate`, `Close`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`, `pin`, `publish`, `release`); `internal/adapter/server/service.go` (`beginRunAdmission`, `engineAndEnvironmentFor`, `SessionEngineResult.RuntimeRevision`); `internal/adapter/server/team.go` (`createTeamInEnvironment`, `RunTeam`, `CleanupTeam`); `internal/app/build.go` (`connectMCP`) | | 1 | Direct global MCP managers (one per immutable current/retiring runtime) | `app.Build` / `mcpRuntimeSet` | process, bounded current plus retired set | a candidate owns its manager from complete construction; unchanged/failed/unpublishable candidates close immediately, retired managers close after operation pins drain, and joined Build close closes the remainder. They are NEVER folded into per-session engine close | reconstructible (reconnects a complete desired set from ordered sources at next Build) | `internal/app/mcp_reconciler.go` (`mcpReconcileCandidate`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`); `internal/app/build.go` (`connectMCP`) | | 2 | Per-session client MCP managers and their original `Service.clientMCPSpecs` mount declarations | `sessionEngineFactory` / `Service` | session / process-local map | per-session close func, invoked by `Service.CloseSession` (`service.go:743`) and shutdown. **Two callers now reach this** (issue #821, Scenario 9): the ACP adapter, which calls `CloseSession` on editor disconnect, and the gRPC/HTTP `CreateSession` wire path, whose teardown is the precondition-checked `EndSession` (same teardown) or `Service.Close`. `CloseSession`, failed-create rollback, and `Service.Close` remove the corresponding `clientMCPSpecs` entry; an engine-rebuild failure deliberately retains it because the surviving session can retry/remount the same client tools. The wire caller is a client that may simply go away without ending its session, so a mounted manager can outlive its last use until process shutdown — bounded by `MaxSessionEngines` (which fails a create at the cap rather than growing without limit), not by a reaper. That residual is the same one every per-session engine has, and it is why the field is deployment-gated to a UNIX-socket-only daemon rather than exposed to an anonymous network caller. A create REFUSED for an unreachable server does not add to it: `verifyClientMCPMounted` runs before any id is minted and invokes the same `closeFn` every other rejection in `createPerSessionEngine` does, so the partially-connected manager is torn down on that path rather than left registered against a session that does not exist | **reset/remount by design:** client specs, including secret-shaped headers, are never persisted. A restart drops `clientMCPSpecs` and every client manager; the client explicitly re-mounts via `LoadSessionWithMCP`, `service.go:968`, or creates a new session with `mcp_servers`. Within one Service lifetime, a rebuild reuses the retained original declaration. | `internal/app/build.go:962`; `internal/adapter/server/service.go` (`clientMCPSpecs`, `ClientMCPFromWire`, `WithClientMCP`) | | 3 | Preserved-fork LRU (`LRUForkReaper`) — Parallel ONLY | `app.Build` (shared via `catalogAssets`, built only when Parallel is enabled) | process | LRU eviction runs each entry's cleanup (dir removal) outside the lock; graceful app shutdown calls `Built.Close`, which drains retained entries and eviction cleanups already detached before closure outside the lock | registry lost; the preserved fork DIRS remain on disk un-tracked (a leak on crash) | `engine/agent/forkreaper.go:41,64`; built at `internal/app/build.go:4895`. NOTE: the writable Subagent (`mode:"read-write"`) no longer creates a per-call fork dir — it writes the parent workspace directly (ADR 0077), so it contributes no fork dirs here; the shared `autoMerger` (`forker.SerializingMerger`) is likewise Parallel-only now | diff --git a/docs/design/IMPLEMENTATION-NOTES.md b/docs/design/IMPLEMENTATION-NOTES.md index 45e79095a3..4bc791425a 100644 --- a/docs/design/IMPLEMENTATION-NOTES.md +++ b/docs/design/IMPLEMENTATION-NOTES.md @@ -6004,9 +6004,11 @@ resource, and prompt metadata. `internal/app/mcp_runtime.go` (`mcpRuntimeSet`) atomically publishes the complete candidate as one manager/provider/catalog contribution. Root runs pin it in `server.Service.beginRunAdmission`; the pin context reaches prompt expansion and every Subagent/Parallel/Team/named/reference -factory built by the one `assembleCatalog` path. Out-of-run resource and prompt -provider calls take one call-scoped pin. Shared and cached default, selector, -no-FS, client-MCP, mode, specialist, and debug engines carry only a revision tag; +factory built by the one `assembleCatalog` path. Direct `RunTeam` members are +built during team creation, so that path retains its creation pin until the run, +explicit cleanup, or Service shutdown and derives its member factory from the +same pinned manager. Out-of-run resource and prompt provider calls take one +call-scoped pin. Shared and cached default, selector, no-FS, client-MCP, mode, specialist, and debug engines carry only a revision tag; `server.Service.engineAndEnvironmentFor` rebuilds a mismatch before use, so idle engine caches never lease a manager and their close functions never own one. Displaced runtimes close after pins drain. A full bounded retirement set closes diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index 3fac46a923..9a209b4f41 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -589,6 +589,9 @@ type Config struct { // catalog (read-only base + MemberTools, plus mutating tools only for a // Mutating member) and the provider/model. MemberEngine MemberEngineFactory + // MemberEngineForOperation resolves the direct RunTeam member factory from the + // same operation-pinned context retained by the team. Nil uses MemberEngine. + MemberEngineForOperation func(context.Context) MemberEngineFactory // TeamGoalUntrusted, when true, re-fences the gRPC/HTTP CreateTeam goal as // UNTRUSTED data in member and synthesis prompts (threaded to // agent.WithUntrustedGoal). DEFAULT false: the goal is the team's TRUSTED @@ -3050,7 +3053,31 @@ func (s *Service) Close() { for id := range s.heldLeases { leasedIDs = append(leasedIDs, id) } + teamOperationReleases := make([]func(), 0, len(s.teams)) + for _, ts := range s.teams { + // A running direct Team owns its operation pin until Supervisor.Run + // returns. Releasing it here would let Build close the manager under live + // member calls; the RunTeam defer performs the release after drain. + if ts.phase != teamRunning && ts.operationRelease != nil { + teamOperationReleases = append(teamOperationReleases, ts.operationRelease) + ts.operationRelease = nil + ts.operationCtx = nil + } + } + runOperationReleases := make([]func(), 0, len(s.runs)) + for _, rs := range s.runs { + if rs.operationRelease != nil { + runOperationReleases = append(runOperationReleases, rs.operationRelease) + rs.operationRelease = nil + } + } s.mu.Unlock() + for _, release := range teamOperationReleases { + release() + } + for _, release := range runOperationReleases { + release() + } // Close every per-session engine in a goroutine with a BOUNDED timeout so a // stuck engine close (e.g. a wedged MCP transport) cannot stall shutdown diff --git a/internal/adapter/server/team.go b/internal/adapter/server/team.go index b9cc9499c8..d5a507571f 100644 --- a/internal/adapter/server/team.go +++ b/internal/adapter/server/team.go @@ -94,6 +94,11 @@ type teamState struct { owner *session.Principal phase teamPhase + // operationCtx carries the immutable direct-runtime pin selected before any + // member factory runs. operationRelease drains it after RunTeam or cleanup. + operationCtx context.Context + operationRelease func() + // run serialises a SpawnTeammate (AddMember writes the supervisor's member maps) // against a RunTeam start (sup.Run reads them). See the type doc above. run sync.Mutex @@ -154,11 +159,37 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ if s.cfg.MemberEngine == nil { return "", nil, ErrTeamsDisabled } + operationCtx := context.WithoutCancel(ctx) + operationRelease := func() {} + if s.cfg.OperationPin != nil { + var err error + operationCtx, operationRelease, err = s.cfg.OperationPin(operationCtx) + if err != nil { + return "", nil, err + } + if operationRelease == nil { + operationRelease = func() {} + } + } + pinTransferred := false + defer func() { + if !pinTransferred { + operationRelease() + } + }() + ctx = operationCtx + memberEngine := s.cfg.MemberEngine + if s.cfg.MemberEngineForOperation != nil { + memberEngine = s.cfg.MemberEngineForOperation(ctx) + if memberEngine == nil { + return "", nil, ErrTeamsDisabled + } + } workspace := base.Workspace().Root() t := team.New(name) factory := func(spec agent.MemberSpec, routedModel string) agent.MemberBuild { - return s.cfg.MemberEngine(t, spec, routedModel) + return memberEngine(t, spec, routedModel) } // Compute the team id FIRST (it needs only NewID, no dependency on the supervisor) @@ -264,9 +295,13 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ s.mu.Lock() // The slot was claimed above, so no capacity refusal can occur here — the cap // is enforced before any lease or durable write. - s.teams[id] = &teamState{team: t, sup: sup, base: workspace, owner: session.PrincipalFromContext(ctx).Clone()} + s.teams[id] = &teamState{ + team: t, sup: sup, base: workspace, owner: session.PrincipalFromContext(ctx).Clone(), + operationCtx: ctx, operationRelease: operationRelease, + } s.teamsReserving-- registered = true + pinTransferred = true s.mu.Unlock() return id, t.Members(), nil } @@ -487,16 +522,6 @@ func (s *Service) CancelTeammate(ctx context.Context, teamID, member string) err // by Drain itself (that is the bounded GracefulStop's job). The gate starts // false — byte-identical default when Drain has not been called. func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.TeamEvent)) (agent.TeamOutcome, error) { - if s.cfg.OperationPin != nil { - pinned, release, err := s.cfg.OperationPin(ctx) - if err != nil { - return agent.TeamOutcome{}, err - } - if release != nil { - defer release() - } - ctx = pinned - } // Drain gate (ADR 0048, mecak8s): refuse new team runs on a draining // replica before claiming the team — mirrors acquireLease's check. if s.draining.Load() { @@ -506,6 +531,24 @@ func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.Te if err != nil { return agent.TeamOutcome{}, err } + if ts.operationCtx != nil { + runCtx, cancel := context.WithCancel(ts.operationCtx) + stop := context.AfterFunc(ctx, cancel) + defer func() { + stop() + cancel() + }() + ctx = runCtx + } else if s.cfg.OperationPin != nil { + pinned, release, pinErr := s.cfg.OperationPin(ctx) + if pinErr != nil { + return agent.TeamOutcome{}, pinErr + } + if release != nil { + defer release() + } + ctx = pinned + } // Atomically claim the team for this run. A second concurrent RunTeam (or one // after a completed run) is rejected — the Supervisor's member state is not safe // to drive twice. The transition is guarded by Service.mu so that of two callers @@ -545,9 +588,16 @@ func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.Te } defer func() { + var release func() s.mu.Lock() ts.phase = teamDone + release = ts.operationRelease + ts.operationRelease = nil + ts.operationCtx = nil s.mu.Unlock() + if release != nil { + release() + } }() return ts.sup.Run(ctx, sink), nil } @@ -580,7 +630,13 @@ func (s *Service) CleanupTeam(ctx context.Context, teamID string) error { return fmt.Errorf("%w: %q", ErrTeamRunning, teamID) } delete(s.teams, teamID) + releaseOperation := ts.operationRelease + ts.operationRelease = nil + ts.operationCtx = nil s.mu.Unlock() + if releaseOperation != nil { + releaseOperation() + } // Release every member lease this team acquired. Without this the lease and its // renewer goroutine outlive the team and are only reclaimed at process exit, so a diff --git a/internal/app/build.go b/internal/app/build.go index 09a6ac2f2e..6ebe8a31ee 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -7770,6 +7770,17 @@ func applyTeamConfig(svcCfg *server.Config, cfg Config, reg *providerRegistry, p // no-FS team exists only inside a no-fs session's in-catalog Team tool. factory, fk, roFk, sharedBaseWorkspace, teamHooks := buildTeamWiring(context.Background(), cfg, reg, provider, reg.Default(), cfg.Model, mainMgr, agentReg, skillIdx, a, false) svcCfg.MemberEngine = factory + if a.mcpRuntimes != nil { + svcCfg.MemberEngineForOperation = func(ctx context.Context) server.MemberEngineFactory { + runtimeAssets := mcpCatalogAssets(ctx, a) + candidate := mcpRuntimeCandidate(ctx) + if candidate == nil { + return nil + } + operationFactory, _, _, _, _ := buildTeamWiring(ctx, cfg, reg, provider, reg.Default(), cfg.Model, candidate.manager, agentReg, skillIdx, runtimeAssets, false) + return operationFactory + } + } svcCfg.Forker = fk svcCfg.ReadOnlyForker = roFk svcCfg.SharedBaseWorkspace = sharedBaseWorkspace diff --git a/internal/app/mcp_runtime.go b/internal/app/mcp_runtime.go index a620b9b97c..4f70cf9646 100644 --- a/internal/app/mcp_runtime.go +++ b/internal/app/mcp_runtime.go @@ -24,18 +24,24 @@ type mcpRuntimePin struct { // retirement set. Engines only retain a revision tag; operation contexts retain // the pin that keeps a displaced manager alive. type mcpRuntimeSet struct { - mu sync.Mutex - current *mcpReconcileCandidate - empty *mcpReconcileCandidate - pins map[*mcpReconcileCandidate]int - retired []*mcpReconcileCandidate - deferred bool - retry func() - closed bool + mu sync.Mutex + current *mcpReconcileCandidate + empty *mcpReconcileCandidate + pins map[*mcpReconcileCandidate]int + retired []*mcpReconcileCandidate + deferred bool + retry func() + closed bool + drained chan struct{} + drain sync.Once + closeDone chan struct{} } func newMCPRuntimeSet(retry func()) *mcpRuntimeSet { - return &mcpRuntimeSet{empty: &mcpReconcileCandidate{}, pins: make(map[*mcpReconcileCandidate]int), retry: retry} + return &mcpRuntimeSet{ + empty: &mcpReconcileCandidate{}, pins: make(map[*mcpReconcileCandidate]int), + retry: retry, drained: make(chan struct{}), closeDone: make(chan struct{}), + } } func (s *mcpRuntimeSet) setRetry(retry func()) { @@ -113,6 +119,9 @@ func (s *mcpRuntimeSet) release(candidate *mcpReconcileCandidate) { retry = s.retry } } + if s.closed && len(s.pins) == 0 { + s.drain.Do(func() { close(s.drained) }) + } s.mu.Unlock() closeCandidate.close() if retry != nil { @@ -163,10 +172,20 @@ func (s *mcpRuntimeSet) currentResourceServers() []string { func (s *mcpRuntimeSet) close() { s.mu.Lock() if s.closed { + closeDone := s.closeDone s.mu.Unlock() + <-closeDone return } s.closed = true + if len(s.pins) == 0 { + s.drain.Do(func() { close(s.drained) }) + } + drained := s.drained + s.mu.Unlock() + + <-drained + s.mu.Lock() current := s.current retired := append([]*mcpReconcileCandidate(nil), s.retired...) s.current = nil @@ -176,6 +195,7 @@ func (s *mcpRuntimeSet) close() { for _, candidate := range retired { candidate.close() } + close(s.closeDone) } func mcpRuntimeCandidate(ctx context.Context) *mcpReconcileCandidate { diff --git a/internal/app/mcp_runtime_publication_test.go b/internal/app/mcp_runtime_publication_test.go index ab60552b54..e908929adc 100644 --- a/internal/app/mcp_runtime_publication_test.go +++ b/internal/app/mcp_runtime_publication_test.go @@ -80,6 +80,38 @@ func TestMCPSourceReconciliation_Scenario2_AllOrNothingPublication(t *testing.T) if equalMCPCandidate(equalLeft, equalRight) { t.Fatal("prompt-only change did not require publication") } + + shutdown := newMCPRuntimeSet(nil) + shutdownCandidate := runtimeTestCandidate(1, "mcp__shutdown__tool") + if !shutdown.publish(nil, shutdownCandidate) { + t.Fatal("publish shutdown runtime") + } + _, releaseShutdownPin, err := shutdown.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + closeDone := make(chan struct{}) + go func() { + shutdown.close() + close(closeDone) + }() + select { + case <-closeDone: + t.Fatal("runtime shutdown completed before its operation pin drained") + case <-time.After(20 * time.Millisecond): + } + if shutdownCandidate.isClosed() { + t.Fatal("runtime shutdown closed a manager before operation drain") + } + releaseShutdownPin() + select { + case <-closeDone: + case <-time.After(time.Second): + t.Fatal("runtime shutdown did not complete after operation drain") + } + if !shutdownCandidate.isClosed() { + t.Fatal("runtime shutdown did not close the drained manager") + } runtimes.close() } @@ -248,6 +280,102 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T t.Fatal("root runtime pin did not drain at FinishRun") } runRuntimes.close() + + // Direct RunTeam builds member engines before RunTeam starts, so team creation + // retains the operation pin. A publication between CreateTeam and RunTeam must + // not swap a referenced specialist onto the new manager. + const teamTool = "mcp__svc__echo" + teamRuntimes := newMCPRuntimeSet(nil) + teamOldManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "team-old:")) + teamOld := &mcpReconcileCandidate{manager: teamOldManager, generation: 1, tools: toolMetadata(teamOldManager.Tools())} + if !teamRuntimes.publish(nil, teamOld) { + t.Fatal("publish direct-team revision 1") + } + teamProvider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("team-call", teamTool, []byte(`{"text":"work"}`))), + mockllm.TextTurn("member done"), + mockllm.TextTurn("team report"), + mockllm.ToolCallTurn(session.NewToolCall("team-call-new", teamTool, []byte(`{"text":"work"}`))), + mockllm.TextTurn("new member done"), + mockllm.TextTurn("new team report"), + ) + teamReg := regForTest(teamProvider, providerOpenAI, "test-model") + teamCfg := teamCfg(t) + teamCfg.EnableTeams = true + teamCfg.Model = "test-model" + teamCfg.authorityEvaluator, _, err = selectAuthorityEvaluator("local", "") + if err != nil { + t.Fatal(err) + } + teamDefs := agents.NewRegistry([]agents.AgentDef{{ + Name: "team-ref", Description: "uses the pinned referenced service", Origin: tool.AgentOriginExplicit, + MCPServers: []agents.AgentMCPServer{{Name: "svc"}}, + }}) + teamAssets := catalogAssets{mcpRuntimes: teamRuntimes, agentReg: teamDefs} + var teamServerCfg server.Config + applyTeamConfig(&teamServerCfg, teamCfg, teamReg, teamProvider, teamOldManager, teamDefs, nil, teamAssets) + teamStore := memstore.New() + rootNames := []string{teamTool} + for name := range agent.MemberToolNames() { + rootNames = append(rootNames, name) + } + teamServerCfg.Engine = initial + teamServerCfg.Store = teamStore + teamServerCfg.SharedEngineRoot = teamCfg.Workspace + teamServerCfg.OperationPin = teamRuntimes.pin + teamServerCfg.OperationRevision = mcpRuntimeRevision + teamServerCfg.RootAuthority = func(session.SessionKind) session.Authority { + return session.Authority{ + CapabilitySet: governance.CapabilitySet{Tools: rootNames, FileSystem: true}, + Provenance: "test", DefinitionIdentity: "test", + } + } + teamSvc, err := newTestServerService(teamServerCfg) + if err != nil { + t.Fatal(err) + } + defer teamSvc.Close() + teamID, _, err := teamSvc.CreateTeamOnDefaultPlacement(context.Background(), "pinned", "use the service", 0, []agent.MemberSpec{{ + Name: "lead", Lead: true, AgentType: "team-ref", InitialPrompt: "call the service once", + }}) + if err != nil { + t.Fatal(err) + } + teamNewManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "team-new:")) + teamNew := &mcpReconcileCandidate{manager: teamNewManager, generation: 2, tools: toolMetadata(teamNewManager.Tools())} + if !teamRuntimes.publish(teamOld, teamNew) { + t.Fatal("publish direct-team revision 2") + } + if _, err := teamSvc.RunTeam(context.Background(), teamID, func(agent.TeamEvent) {}); err != nil { + t.Fatal(err) + } + member, err := teamStore.Load(context.Background(), agent.MemberSessionID(teamID, "lead")) + if err != nil { + t.Fatal(err) + } + if got := latestToolResult(member, "team-call"); !strings.Contains(got, "team-old:work") { + t.Fatalf("direct RunTeam member did not retain its creation pin: %q", got) + } + if !teamOld.isClosed() { + t.Fatal("direct RunTeam runtime did not retire after team completion") + } + newTeamID, _, err := teamSvc.CreateTeamOnDefaultPlacement(context.Background(), "current", "use the current service", 0, []agent.MemberSpec{{ + Name: "lead", Lead: true, AgentType: "team-ref", InitialPrompt: "call the service once", + }}) + if err != nil { + t.Fatal(err) + } + if _, err := teamSvc.RunTeam(context.Background(), newTeamID, func(agent.TeamEvent) {}); err != nil { + t.Fatal(err) + } + newMember, err := teamStore.Load(context.Background(), agent.MemberSessionID(newTeamID, "lead")) + if err != nil { + t.Fatal(err) + } + if got := latestToolResult(newMember, "team-call-new"); !strings.Contains(got, "team-new:work") { + t.Fatalf("post-publication direct RunTeam member did not use the active runtime: %q", got) + } + teamRuntimes.close() } func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *testing.T) { From 6151d2146cfc33f19e699b9df5bef99dcc98968d Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Wed, 16 Sep 2026 23:05:08 +0200 Subject: [PATCH 05/14] feat(mcp): add explicit source refresh control Co-Authored-By: OpenAI Codex --- cmd/mecatui/client/capabilities.go | 15 +- cmd/mecatui/client/mcp.go | 67 +- cmd/mecatui/ui/builtins.go | 15 +- cmd/mecatui/ui/builtins_test.go | 2 +- cmd/mecatui/ui/keymark_liveness_test.go | 6 +- cmd/mecatui/ui/mcp.go | 58 +- cmd/mecatui/ui/mcp_refresh_routing_test.go | 94 + cmd/mecatui/ui/mcp_test.go | 13 +- .../ui/testdata/mcp_err_not_configured.golden | 2 +- cmd/mecatui/ui/testdata/mcp_panel.golden | 30 +- .../ui/testdata/mcp_panel_groups.golden | 30 +- cmd/mecatui/ui/update.go | 9 + contracts/gen/go/mecatl/v1/harness.pb.go | 6891 +++++++++-------- contracts/gen/go/mecatl/v1/harness_grpc.pb.go | 54 +- contracts/proto/mecatl/v1/harness.proto | 31 +- docs/adr/0027-cloud-native.md | 8 + docs/adr/README.md | 2 +- docs/architecture.md | 13 +- docs/architecture/extensibility.md | 20 +- docs/design/IMPLEMENTATION-NOTES.md | 14 + internal/adapter/server/classification.go | 3 +- internal/adapter/server/grpc.go | 21 +- internal/adapter/server/http.go | 31 +- internal/adapter/server/mcp_refresh.go | 202 + internal/adapter/server/mcp_refresh_test.go | 321 + .../server/mcp_refresh_transport_test.go | 106 + internal/adapter/server/mcp_test.go | 57 +- .../server/sdk_typescript_release_test.go | 4 +- internal/adapter/server/service.go | 66 +- .../server/session_affinity_grpc_test.go | 1 + internal/app/build.go | 59 +- internal/app/catalog.go | 1 + internal/app/mcp_reconciler.go | 23 +- sdk/typescript/etc/mecatl-sdk-deno.api.md | 3 + sdk/typescript/etc/mecatl-sdk-node.api.md | 3 + sdk/typescript/etc/mecatl-sdk.api.md | 3 + .../src/gen/mecatl/v1/harness_pb.ts | 290 +- sdk/typescript/src/namespaces-core.ts | 13 + sdk/typescript/src/rpc-catalog.ts | 9 + sdk/typescript/test/namespaces-core.test.ts | 5 + sdk/typescript/test/rpc-catalog.test.ts | 4 +- .../test/session-projections.test.ts | 1 + user-docs/building/deployment/mecak8s.md | 5 +- user-docs/building/what-you-get/mcp-client.md | 48 +- user-docs/mecatui/commands-and-memory.md | 17 +- user-docs/mecatui/using-the-tui.md | 1 + user-docs/reference/grpc-api.md | 3 +- user-docs/reference/http-sse-api.md | 3 +- .../reference/typescript-sdk-api/core.md | 17 +- 49 files changed, 4995 insertions(+), 3699 deletions(-) create mode 100644 cmd/mecatui/ui/mcp_refresh_routing_test.go create mode 100644 internal/adapter/server/mcp_refresh.go create mode 100644 internal/adapter/server/mcp_refresh_test.go create mode 100644 internal/adapter/server/mcp_refresh_transport_test.go diff --git a/cmd/mecatui/client/capabilities.go b/cmd/mecatui/client/capabilities.go index 82ac141ff0..3c92750bb1 100644 --- a/cmd/mecatui/client/capabilities.go +++ b/cmd/mecatui/client/capabilities.go @@ -13,12 +13,14 @@ type Capabilities struct { // MCPConnectorStatus gates the broker-local connector inventory. It is separate // from MCP: broker-only deployments deliberately expose no direct resources or prompts. MCPConnectorStatus bool - MCP bool - SlashCommands bool - Memory bool - Skills bool - Teams bool - Agents bool + // MCPRefresh gates explicit direct/global source reconciliation. + MCPRefresh bool + MCP bool + SlashCommands bool + Memory bool + Skills bool + Teams bool + Agents bool // Bash reports availability of the canonical Shell tool. Its historical // spelling is retained for compatibility with the established wire/Go API. Bash bool @@ -108,6 +110,7 @@ func capabilitiesFrom(c *mecatlv1.ServerCapabilities) Capabilities { } return Capabilities{ MCPConnectorStatus: c.GetMcpConnectorStatus(), + MCPRefresh: c.GetMcpRefresh(), MCP: c.GetMcp(), SlashCommands: c.GetSlashCommands(), Memory: c.GetMemory(), diff --git a/cmd/mecatui/client/mcp.go b/cmd/mecatui/client/mcp.go index 4f2e469c01..94f67db274 100644 --- a/cmd/mecatui/client/mcp.go +++ b/cmd/mecatui/client/mcp.go @@ -71,9 +71,7 @@ type MCPServerInfo struct { Group string } -// MCPSource is one inventory source — a ToolHive group or config block — with its -// servers and any diagnostics (proto McpSource). NOTE: ListMcpSources reflects a -// startup snapshot; servers started AFTER mecated launched won't appear. +// MCPSource is one cached published/pre-shadow source inventory row. type MCPSource struct { Name string Kind string @@ -160,7 +158,22 @@ type MCPPromptGotMsg struct { // MCPSourcesMsg carries a ListMcpSources success (the panel inventory). type MCPSourcesMsg struct { - Sources []MCPSource + Sources []MCPSource + Revision uint64 + Stale bool + Reconciling bool +} + +// MCPRefreshResult identifies the direct runtime considered by one refresh. +type MCPRefreshResult struct { + Revision uint64 + Changed bool +} + +// MCPRefreshMsg carries an explicit direct-source refresh result. +type MCPRefreshMsg struct { + Result MCPRefreshResult + Err error } // MCPGroupsMsg carries a ListToolHiveGroups success. @@ -262,13 +275,28 @@ func (c *Client) GetMCPPrompt(ctx context.Context, server, name string, args map return resp.GetDescription(), mapPromptMessages(resp.GetMessages()), nil } -// ListMCPSources lists the inventory sources (the panel snapshot). +// ListMCPSources lists the cached inventory sources. func (c *Client) ListMCPSources(ctx context.Context) ([]MCPSource, error) { + result, err := c.ListMCPSourceStatus(ctx) + return result.Sources, err +} + +// ListMCPSourceStatus returns cached inventory plus publication status. +func (c *Client) ListMCPSourceStatus(ctx context.Context) (MCPSourcesMsg, error) { resp, err := c.svc.ListMcpSources(ctx, &mecatlv1.ListMcpSourcesRequest{}) if err != nil { - return nil, err + return MCPSourcesMsg{}, err + } + return MCPSourcesMsg{Sources: mapSources(resp.GetSources()), Revision: resp.GetRevision(), Stale: resp.GetStale(), Reconciling: resp.GetReconciling()}, nil +} + +// RefreshMCP explicitly reconciles direct MCP sources for one session. +func (c *Client) RefreshMCP(ctx context.Context, sessionID string) (MCPRefreshResult, error) { + resp, err := c.svc.RefreshMcpSources(ctx, &mecatlv1.RefreshMcpSourcesRequest{SessionId: sessionID}) + if err != nil { + return MCPRefreshResult{}, err } - return mapSources(resp.GetSources()), nil + return MCPRefreshResult{Revision: resp.GetRevision(), Changed: resp.GetChanged()}, nil } // ListToolHiveGroups lists the configured ToolHive group names. @@ -412,6 +440,16 @@ type MCPConnectorReader interface { ListMCPConnectors(ctx context.Context, sessionID string) (MCPConnectorInventory, error) } +// MCPRefresher is the optional explicit direct-source control. +type MCPRefresher interface { + RefreshMCP(ctx context.Context, sessionID string) (MCPRefreshResult, error) +} + +// MCPSourceStatusReader is the optional cached status extension. +type MCPSourceStatusReader interface { + ListMCPSourceStatus(ctx context.Context) (MCPSourcesMsg, error) +} + // ListMcpResourcesCmd lists resources (server "" = all). func ListMcpResourcesCmd(ctx context.Context, m MCP, server string) tea.Cmd { return func() tea.Msg { @@ -459,6 +497,13 @@ func GetMcpPromptCmd(ctx context.Context, m MCP, server, name string, args map[s // ListMcpSourcesCmd lists the inventory sources (the panel snapshot). func ListMcpSourcesCmd(ctx context.Context, m MCP) tea.Cmd { return func() tea.Msg { + if statusReader, ok := m.(MCPSourceStatusReader); ok { + status, err := statusReader.ListMCPSourceStatus(ctx) + if err != nil { + return MCPErrMsg{Op: "list sources", Class: classifyMCPErr(err), Err: err} + } + return status + } s, err := m.ListMCPSources(ctx) if err != nil { return MCPErrMsg{Op: "list sources", Class: classifyMCPErr(err), Err: err} @@ -467,6 +512,14 @@ func ListMcpSourcesCmd(ctx context.Context, m MCP) tea.Cmd { } } +// RefreshMcpSourcesCmd invokes explicit direct-source refresh. +func RefreshMcpSourcesCmd(ctx context.Context, m MCPRefresher, sessionID string) tea.Cmd { + return func() tea.Msg { + result, err := m.RefreshMCP(ctx, sessionID) + return MCPRefreshMsg{Result: result, Err: err} + } +} + // ListToolHiveGroupsCmd lists the configured ToolHive groups. func ListToolHiveGroupsCmd(ctx context.Context, m MCP) tea.Cmd { return func() tea.Msg { diff --git a/cmd/mecatui/ui/builtins.go b/cmd/mecatui/ui/builtins.go index 70b00c08fc..dda5ab35c0 100644 --- a/cmd/mecatui/ui/builtins.go +++ b/cmd/mecatui/ui/builtins.go @@ -30,6 +30,7 @@ type builtin struct { // read clearly and a new collaborator is one field, not an 8th positional bool. type wiredCollaborators struct { MCP bool + MCPRefresh bool MCPConnector bool Agents bool Skills bool @@ -58,8 +59,9 @@ type wiredCollaborators struct { // though the actual dispatch path built it correctly). func (m Model) wiredCollaborators() wiredCollaborators { _, mcpConnector := m.deps.MCP.(client.MCPConnectorReader) + _, mcpRefresh := m.deps.MCP.(client.MCPRefresher) return wiredCollaborators{ - MCP: m.deps.MCP != nil, MCPConnector: mcpConnector, + MCP: m.deps.MCP != nil, MCPRefresh: mcpRefresh, MCPConnector: mcpConnector, Agents: m.deps.Agents != nil, Skills: m.deps.Skills != nil, Soul: m.deps.Soul != nil, UserModel: m.deps.UserModel != nil, Models: m.deps.Models != nil, Reflections: m.deps.Reflections != nil, @@ -154,6 +156,15 @@ func builtinCommands(caps client.Capabilities, w wiredCollaborators) []builtin { run: Model.runMCP, }) } + directRefresh := caps.MCPRefresh && !caps.WorkspaceEnrollment && w.MCPRefresh + brokerRefresh := caps.WorkspaceEnrollment && !caps.MCPRefresh && w.Workspace + if directRefresh || brokerRefresh { + out = append(out, builtin{ + name: "mcp-refresh", + desc: "refresh MCP tools for this session", + run: Model.runMCPRefresh, + }) + } if caps.Agents && w.Agents { out = append(out, builtin{ name: "agents", @@ -241,7 +252,7 @@ func builtinCommands(caps client.Capabilities, w wiredCollaborators) []builtin { } if caps.WorkspaceEnrollment && w.Workspace { out = append(out, - builtin{name: "tools-connect", desc: "connect the bundled protected-tool workspace services", run: Model.runToolsConnect}, + builtin{name: "tools-connect", desc: "deprecated alias for /mcp-refresh in broker mode", run: Model.runToolsConnect}, builtin{name: "tools-cancel", desc: "cancel a pending workspace-services connection", run: Model.runToolsCancel}, ) } diff --git a/cmd/mecatui/ui/builtins_test.go b/cmd/mecatui/ui/builtins_test.go index f0e867eafe..dbee3d64eb 100644 --- a/cmd/mecatui/ui/builtins_test.go +++ b/cmd/mecatui/ui/builtins_test.go @@ -123,7 +123,7 @@ func TestBuiltinCommandsCapsFilter(t *testing.T) { {"sessions not wired", client.Capabilities{}, wiredCollaborators{}, []string{"clear", "help"}}, {"workspace enrollment cap but not wired", client.Capabilities{WorkspaceEnrollment: true}, wiredCollaborators{}, []string{"clear", "help"}}, {"workspace enrollment wired but no cap", client.Capabilities{}, wiredCollaborators{Workspace: true}, []string{"clear", "help"}}, - {"workspace enrollment cap and wired", client.Capabilities{WorkspaceEnrollment: true}, wiredCollaborators{Workspace: true}, []string{"clear", "help", "tools-connect", "tools-cancel"}}, + {"workspace enrollment cap and wired", client.Capabilities{WorkspaceEnrollment: true}, wiredCollaborators{Workspace: true}, []string{"clear", "help", "mcp-refresh", "tools-connect", "tools-cancel"}}, {"posture empty omits the builtin", client.Capabilities{}, wiredCollaborators{}, []string{"clear", "help"}}, {"posture set adds the builtin", client.Capabilities{Posture: "yolo"}, wiredCollaborators{}, []string{"clear", "help", "posture"}}, {"posture strict still shows (chrome is reportable)", client.Capabilities{Posture: "strict"}, wiredCollaborators{}, []string{"clear", "help", "posture"}}, diff --git a/cmd/mecatui/ui/keymark_liveness_test.go b/cmd/mecatui/ui/keymark_liveness_test.go index 4ec2de7f49..6b8050172f 100644 --- a/cmd/mecatui/ui/keymark_liveness_test.go +++ b/cmd/mecatui/ui/keymark_liveness_test.go @@ -726,10 +726,10 @@ func TestMCPOverlayHintsReflectKeyOverride(t *testing.T) { } t.Run("panel footer", func(t *testing.T) { got := render(mcpState{view: mcpPanel}) - if !strings.Contains(got, "ctrl+f24 refresh · ctrl+f16 close") { - t.Errorf("panel footer should carry live refresh+close: %q", got) + if !strings.Contains(got, "ctrl+f24 reload status · ctrl+f16 close") { + t.Errorf("panel footer should carry live status-reload+close: %q", got) } - if strings.Contains(got, "r refresh · esc close") { + if strings.Contains(got, "r reload status · esc close") { t.Errorf("panel footer still shows defaults: %q", got) } }) diff --git a/cmd/mecatui/ui/mcp.go b/cmd/mecatui/ui/mcp.go index 29045b6120..1e6470ffc5 100644 --- a/cmd/mecatui/ui/mcp.go +++ b/cmd/mecatui/ui/mcp.go @@ -16,6 +16,29 @@ func (m Model) runMCP() (tea.Model, tea.Cmd) { return m.openMCP(mcpPane func (m Model) runMCPResources() (tea.Model, tea.Cmd) { return m.openMCP(mcpResources) } func (m Model) runMCPPrompts() (tea.Model, tea.Cmd) { return m.openMCP(mcpPrompts) } +func (m Model) runMCPRefresh() (tea.Model, tea.Cmd) { + direct := m.caps.MCPRefresh + broker := m.caps.WorkspaceEnrollment + if direct == broker { + m.statusMsg = m.deps.Theme.Style("warning").Render("MCP refresh is unavailable for this server mode") + return m, nil + } + if broker { + if m.deps.WorkspaceEnrollment == nil { + m.statusMsg = m.deps.Theme.Style("warning").Render("MCP refresh collaborator is unavailable") + return m, nil + } + return m.runToolsConnect() + } + refresher, ok := m.deps.MCP.(client.MCPRefresher) + if !ok || refresher == nil || m.sessionID == "" || m.phase != phaseIdle { + m.statusMsg = m.deps.Theme.Style("warning").Render("MCP refresh is available only for an idle active session") + return m, nil + } + m.statusMsg = m.deps.Theme.Style("muted").Render("refreshing MCP tools…") + return m, client.RefreshMcpSourcesCmd(m.deps.Ctx, refresher, m.sessionID) +} + // openMCP opens the selected MCP surface and starts its initial RPC. func (m Model) openMCP(v mcpView) (tea.Model, tea.Cmd) { if m.phase != phaseIdle || m.deps.MCP == nil || (v != mcpPanel && !m.caps.MCP) { @@ -81,10 +104,13 @@ type mcpState struct { errCls client.MCPErrorClass // Inventory panel. - sources []client.MCPSource - groups []string // ToolHive groups (best-effort; see groupsErr) - groupsErr bool // the groups fetch failed — degrade quietly, panel still works - groupsDone bool // a groups result (success or error) has arrived + sources []client.MCPSource + revision uint64 + stale bool + reconciling bool + groups []string // ToolHive groups (best-effort; see groupsErr) + groupsErr bool // the groups fetch failed — degrade quietly, panel still works + groupsDone bool // a groups result (success or error) has arrived // Broker-only panel state. It is intentionally separate from direct MCP sources: // broker capability must never trigger direct source/resource/prompt/group RPCs. @@ -472,6 +498,9 @@ func (s *mcpState) HandleMsg(msg tea.Msg) (cmd tea.Cmd, handled bool, closed boo s.refreshed = true // panel now shows live-re-probed state, not the startup snapshot } s.sources = msg.Sources + s.revision = msg.Revision + s.stale = msg.Stale + s.reconciling = msg.Reconciling return nil, true, false case client.MCPGroupsMsg: s.groups = msg.Groups @@ -783,21 +812,22 @@ func brokerCatalogueLabel(state string) string { } } -// mcpPanelFooter is the panel's footer hint. Before any manual refresh it carries -// the startup-snapshot caveat; after a successful re-probe it reads "updated" so -// the user knows the panel reflects LIVE source status. Both forms advertise the -// r-refresh and esc-close keys, sourced from the LIVE Refresh/Close markings -// (issue #457). No wall-clock — the wording is state-driven so the View stays -// golden-stable. +// mcpPanelFooter reports cached reconciler status. The r key reloads that cache; +// explicit direct/broker mutation is the separate /mcp-refresh command. func mcpPanelFooter(st mcpState, hk helpKeys) string { - refreshClose := hk.refresh + " refresh · " + hk.closeOnly + " close" + refreshClose := hk.refresh + " reload status · " + hk.closeOnly + " close" + prefix := fmt.Sprintf("revision %d · cached", st.revision) switch { case st.refreshing: - return "refreshing… · " + refreshClose + return "reloading status… · " + refreshClose + case st.reconciling: + return prefix + " · reconciling… · " + refreshClose + case st.stale: + return prefix + " · stale · " + refreshClose case st.refreshed: - return "updated — live MCP source status · " + refreshClose + return prefix + " · updated · " + refreshClose default: - return "snapshot from mecated startup — servers started later won't appear · " + refreshClose + return prefix + " · " + refreshClose } } diff --git a/cmd/mecatui/ui/mcp_refresh_routing_test.go b/cmd/mecatui/ui/mcp_refresh_routing_test.go new file mode 100644 index 0000000000..865a108055 --- /dev/null +++ b/cmd/mecatui/ui/mcp_refresh_routing_test.go @@ -0,0 +1,94 @@ +package ui + +import ( + "context" + "testing" + + tea "charm.land/bubbletea/v2" + + "github.com/stacklok/mecatl/cmd/mecatui/client" +) + +type refreshRoutingMCP struct { + fakeMCP + refreshes int +} + +func (f *refreshRoutingMCP) RefreshMCP(context.Context, string) (client.MCPRefreshResult, error) { + f.refreshes++ + return client.MCPRefreshResult{Revision: 9, Changed: true}, nil +} + +type refreshRoutingBroker struct{ connects int } + +func (f *refreshRoutingBroker) ConnectWorkspaceServices(context.Context, string) (client.WorkspaceEnrollment, error) { + f.connects++ + return client.WorkspaceEnrollment{ID: "enroll-1", Status: client.WorkspaceEnrollmentPending}, nil +} +func (*refreshRoutingBroker) RetryWorkspaceEnrollment(context.Context, string, string) (client.WorkspaceEnrollment, error) { + return client.WorkspaceEnrollment{}, nil +} +func (*refreshRoutingBroker) CancelWorkspaceEnrollment(context.Context, string, string) (client.WorkspaceEnrollment, error) { + return client.WorkspaceEnrollment{}, nil +} + +func TestMCPSourceReconciliation_Scenario4_UnifiedCommandRoutingMatrix(t *testing.T) { + for _, tc := range []struct { + name string + caps client.Capabilities + withDirect bool + withBroker bool + wantRefreshCommand bool + wantAlias bool + wantDirectCalls int + wantBrokerCalls int + }{ + {name: "direct-only", caps: client.Capabilities{MCPRefresh: true}, withDirect: true, wantRefreshCommand: true, wantDirectCalls: 1}, + {name: "broker-only", caps: client.Capabilities{WorkspaceEnrollment: true}, withBroker: true, wantRefreshCommand: true, wantAlias: true, wantBrokerCalls: 1}, + {name: "both-fail-closed", caps: client.Capabilities{MCPRefresh: true, WorkspaceEnrollment: true}, withDirect: true, withBroker: true, wantAlias: true}, + {name: "neither-fail-closed"}, + {name: "direct-missing-collaborator", caps: client.Capabilities{MCPRefresh: true}}, + {name: "broker-missing-collaborator", caps: client.Capabilities{WorkspaceEnrollment: true}}, + } { + t.Run(tc.name, func(t *testing.T) { + direct := &refreshRoutingMCP{} + broker := &refreshRoutingBroker{} + m, _ := builtinDispatchModel(t, tc.caps, false) + if tc.withDirect { + m.deps.MCP = direct + } + if tc.withBroker { + m.deps.WorkspaceEnrollment = broker + } + m.caps = tc.caps + + refresh, refreshOK := builtinByName(m.caps, m.wiredCollaborators(), "mcp-refresh") + if refreshOK != tc.wantRefreshCommand { + t.Fatalf("mcp-refresh registered=%v want %v", refreshOK, tc.wantRefreshCommand) + } + _, aliasOK := builtinByName(m.caps, m.wiredCollaborators(), "tools-connect") + if aliasOK != tc.wantAlias { + t.Fatalf("tools-connect registered=%v want %v", aliasOK, tc.wantAlias) + } + if refreshOK { + mm, cmd := refresh.run(m) + m = mm.(Model) + if cmd == nil { + t.Fatal("mcp-refresh returned nil command") + } + msg := cmd() + if batch, ok := msg.(tea.BatchMsg); ok { + if len(batch) == 0 { + t.Fatal("empty command batch") + } + msg = batch[0]() + } + mm, _ = m.Update(msg) + m = mm.(Model) + } + if direct.refreshes != tc.wantDirectCalls || broker.connects != tc.wantBrokerCalls { + t.Fatalf("direct calls=%d broker calls=%d, want %d/%d", direct.refreshes, broker.connects, tc.wantDirectCalls, tc.wantBrokerCalls) + } + }) + } +} diff --git a/cmd/mecatui/ui/mcp_test.go b/cmd/mecatui/ui/mcp_test.go index 97089fd255..6c44d36fde 100644 --- a/cmd/mecatui/ui/mcp_test.go +++ b/cmd/mecatui/ui/mcp_test.go @@ -395,17 +395,16 @@ func TestMCPPanelRefreshPicksUpLiveStatus(t *testing.T) { } // The footer advertises the updated state and the refresh key. view := string(stripANSI([]byte(m.View().Content))) - if !strings.Contains(view, "updated") || !strings.Contains(view, "r refresh") { - t.Fatalf("footer missing updated/refresh hint:\n%s", view) + if !strings.Contains(view, "updated") || !strings.Contains(view, "reload status") { + t.Fatalf("footer missing updated/status-reload hint:\n%s", view) } if !strings.Contains(view, "legacy") { t.Fatalf("refreshed server 'legacy' not rendered:\n%s", view) } } -// TestMCPPanelRefreshIndicatorWhileInFlight asserts that while a refresh is in -// flight the footer reads "refreshing…" and a second r is a no-op (no duplicate -// fetch), without clearing the already-shown sources. +// TestMCPPanelRefreshIndicatorWhileInFlight asserts that while a cached-status +// reload is in flight the footer reports it and a second r is a no-op. func TestMCPPanelRefreshIndicatorWhileInFlight(t *testing.T) { fm := samplePanelMCP() m := newMCPModel(t, aztec(), fm) @@ -425,8 +424,8 @@ func TestMCPPanelRefreshIndicatorWhileInFlight(t *testing.T) { t.Fatalf("sources cleared during refresh (should stay visible)") } view := string(stripANSI([]byte(m.View().Content))) - if !strings.Contains(view, "refreshing") { - t.Fatalf("footer missing refreshing indicator:\n%s", view) + if !strings.Contains(view, "reloading status") { + t.Fatalf("footer missing status-reload indicator:\n%s", view) } // A second r while in flight is a no-op. mm, cmd2 := m.Update(tea.KeyPressMsg{Code: 'r', Text: "r"}) diff --git a/cmd/mecatui/ui/testdata/mcp_err_not_configured.golden b/cmd/mecatui/ui/testdata/mcp_err_not_configured.golden index d6248c81ae..fa63f4d8ee 100644 --- a/cmd/mecatui/ui/testdata/mcp_err_not_configured.golden +++ b/cmd/mecatui/ui/testdata/mcp_err_not_configured.golden @@ -12,7 +12,7 @@ ┃ ┃ ┃ ToolHive groups: unavailable ┃ ┃ ┃ -┃ snapshot from mecated startup — servers started later won't appear · r refresh · esc close ┃ +┃ revision 0 · cached · r reload status · esc close ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/mcp_panel.golden b/cmd/mecatui/ui/testdata/mcp_panel.golden index 099bb90023..e38af2c7e7 100644 --- a/cmd/mecatui/ui/testdata/mcp_panel.golden +++ b/cmd/mecatui/ui/testdata/mcp_panel.golden @@ -2,21 +2,21 @@ ──────────────────────────────────────────────────────────────────────────────────────────────────── - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - ┃ ┃ - ┃ MCP inventory ┃ - ┃ ┃ - ┃ toolhive [toolhive] enabled group=dev ┃ - ┃ • fetch streamable-http http://127.0.0.1:9001 ┃ - ┃ • github streamable-http http://127.0.0.1:9002 ┃ - ┃ ! skipped sse server 'legacy' (unsupported transport) ┃ - ┃ static [static] disabled ┃ - ┃ ┃ - ┃ ToolHive groups: none ┃ - ┃ ┃ - ┃ snapshot from mecated startup — servers started later won't appear · r refresh · esc close ┃ - ┃ ┃ - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ ┃ + ┃ MCP inventory ┃ + ┃ ┃ + ┃ toolhive [toolhive] enabled group=dev ┃ + ┃ • fetch streamable-http http://127.0.0.1:9001 ┃ + ┃ • github streamable-http http://127.0.0.1:9002 ┃ + ┃ ! skipped sse server 'legacy' (unsupported transport) ┃ + ┃ static [static] disabled ┃ + ┃ ┃ + ┃ ToolHive groups: none ┃ + ┃ ┃ + ┃ revision 0 · cached · r reload status · esc close ┃ + ┃ ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/testdata/mcp_panel_groups.golden b/cmd/mecatui/ui/testdata/mcp_panel_groups.golden index 0e762e2998..9c5eea8dc7 100644 --- a/cmd/mecatui/ui/testdata/mcp_panel_groups.golden +++ b/cmd/mecatui/ui/testdata/mcp_panel_groups.golden @@ -2,21 +2,21 @@ ──────────────────────────────────────────────────────────────────────────────────────────────────── - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - ┃ ┃ - ┃ MCP inventory ┃ - ┃ ┃ - ┃ toolhive [toolhive] enabled group=dev ┃ - ┃ • fetch streamable-http http://127.0.0.1:9001 ┃ - ┃ • github streamable-http http://127.0.0.1:9002 ┃ - ┃ ! skipped sse server 'legacy' (unsupported transport) ┃ - ┃ static [static] disabled ┃ - ┃ ┃ - ┃ ToolHive groups: dev, prod ┃ - ┃ ┃ - ┃ snapshot from mecated startup — servers started later won't appear · r refresh · esc close ┃ - ┃ ┃ - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ ┃ + ┃ MCP inventory ┃ + ┃ ┃ + ┃ toolhive [toolhive] enabled group=dev ┃ + ┃ • fetch streamable-http http://127.0.0.1:9001 ┃ + ┃ • github streamable-http http://127.0.0.1:9002 ┃ + ┃ ! skipped sse server 'legacy' (unsupported transport) ┃ + ┃ static [static] disabled ┃ + ┃ ┃ + ┃ ToolHive groups: dev, prod ┃ + ┃ ┃ + ┃ revision 0 · cached · r reload status · esc close ┃ + ┃ ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index 943af3fece..cdef67ce22 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -696,6 +696,15 @@ func (m Model) updateLifecycle(msg tea.Msg) (tea.Model, tea.Cmd, bool) { case workspaceEnrollmentPollTickMsg: mm, cmd := m.applyWorkspaceEnrollmentPollTick(msg) return mm, cmd, true + case client.MCPRefreshMsg: + if msg.Err != nil { + m.statusMsg = m.deps.Theme.Style("warning").Render("MCP refresh failed: " + sanitizeTerminal(msg.Err.Error())) + } else if msg.Result.Changed { + m.statusMsg = m.deps.Theme.Style("muted").Render(fmt.Sprintf("MCP tools refreshed (revision %d)", msg.Result.Revision)) + } else { + m.statusMsg = m.deps.Theme.Style("muted").Render(fmt.Sprintf("MCP tools already current (revision %d)", msg.Result.Revision)) + } + return m, nil, true case client.SessionCompactedMsg: if msg.RequestToken != m.compactRequestToken || msg.SessionID != m.sessionID || !m.compactPending { return m, nil, true diff --git a/contracts/gen/go/mecatl/v1/harness.pb.go b/contracts/gen/go/mecatl/v1/harness.pb.go index 084292ae2a..30cfa0388e 100644 --- a/contracts/gen/go/mecatl/v1/harness.pb.go +++ b/contracts/gen/go/mecatl/v1/harness.pb.go @@ -1365,8 +1365,11 @@ type ServerCapabilities struct { // mcp_connector_status requires a wired broker inspector, enforced ownership // and a verified caller. It does not enable direct MCP resources or prompts. McpConnectorStatus bool `protobuf:"varint,29,opt,name=mcp_connector_status,json=mcpConnectorStatus,proto3" json:"mcp_connector_status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // mcp_refresh is true when direct/global MCP source reconciliation is wired. + // It is mutually exclusive with workspace_enrollment in a valid deployment. + McpRefresh bool `protobuf:"varint,30,opt,name=mcp_refresh,json=mcpRefresh,proto3" json:"mcp_refresh,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ServerCapabilities) Reset() { @@ -1595,6 +1598,13 @@ func (x *ServerCapabilities) GetMcpConnectorStatus() bool { return false } +func (x *ServerCapabilities) GetMcpRefresh() bool { + if x != nil { + return x.McpRefresh + } + return false +} + // ListSessionMcpConnectorsRequest names an owned, broker-bound session. type ListSessionMcpConnectorsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -10856,7 +10866,13 @@ func (*ListMcpSourcesRequest) Descriptor() ([]byte, []int) { type ListMcpSourcesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // sources are the (possibly empty) resolved sources. - Sources []*McpSource `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` + Sources []*McpSource `protobuf:"bytes,1,rep,name=sources,proto3" json:"sources,omitempty"` + // revision is the current published direct-runtime revision. + Revision uint64 `protobuf:"varint,2,opt,name=revision,proto3" json:"revision,omitempty"` + // stale is true when source or candidate degradation retained an older runtime. + Stale bool `protobuf:"varint,3,opt,name=stale,proto3" json:"stale,omitempty"` + // reconciling is true while the shared reconciler is processing a cycle. + Reconciling bool `protobuf:"varint,4,opt,name=reconciling,proto3" json:"reconciling,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -10898,6 +10914,126 @@ func (x *ListMcpSourcesResponse) GetSources() []*McpSource { return nil } +func (x *ListMcpSourcesResponse) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *ListMcpSourcesResponse) GetStale() bool { + if x != nil { + return x.Stale + } + return false +} + +func (x *ListMcpSourcesResponse) GetReconciling() bool { + if x != nil { + return x.Reconciling + } + return false +} + +// RefreshMcpSourcesRequest names the owned session whose direct-name authority +// may be widened after reconciliation. +type RefreshMcpSourcesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshMcpSourcesRequest) Reset() { + *x = RefreshMcpSourcesRequest{} + mi := &file_mecatl_v1_harness_proto_msgTypes[122] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshMcpSourcesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshMcpSourcesRequest) ProtoMessage() {} + +func (x *RefreshMcpSourcesRequest) ProtoReflect() protoreflect.Message { + mi := &file_mecatl_v1_harness_proto_msgTypes[122] + 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 RefreshMcpSourcesRequest.ProtoReflect.Descriptor instead. +func (*RefreshMcpSourcesRequest) Descriptor() ([]byte, []int) { + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{122} +} + +func (x *RefreshMcpSourcesRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +// RefreshMcpSourcesResponse identifies the request-pinned runtime snapshot. +type RefreshMcpSourcesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Revision uint64 `protobuf:"varint,1,opt,name=revision,proto3" json:"revision,omitempty"` + Changed bool `protobuf:"varint,2,opt,name=changed,proto3" json:"changed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshMcpSourcesResponse) Reset() { + *x = RefreshMcpSourcesResponse{} + mi := &file_mecatl_v1_harness_proto_msgTypes[123] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshMcpSourcesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshMcpSourcesResponse) ProtoMessage() {} + +func (x *RefreshMcpSourcesResponse) ProtoReflect() protoreflect.Message { + mi := &file_mecatl_v1_harness_proto_msgTypes[123] + 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 RefreshMcpSourcesResponse.ProtoReflect.Descriptor instead. +func (*RefreshMcpSourcesResponse) Descriptor() ([]byte, []int) { + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{123} +} + +func (x *RefreshMcpSourcesResponse) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *RefreshMcpSourcesResponse) GetChanged() bool { + if x != nil { + return x.Changed + } + return false +} + // ListToolHiveGroupsRequest requests the distinct ToolHive groups in the // resolved inventory. type ListToolHiveGroupsRequest struct { @@ -10908,7 +11044,7 @@ type ListToolHiveGroupsRequest struct { func (x *ListToolHiveGroupsRequest) Reset() { *x = ListToolHiveGroupsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[122] + mi := &file_mecatl_v1_harness_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10920,7 +11056,7 @@ func (x *ListToolHiveGroupsRequest) String() string { func (*ListToolHiveGroupsRequest) ProtoMessage() {} func (x *ListToolHiveGroupsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[122] + mi := &file_mecatl_v1_harness_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10933,7 +11069,7 @@ func (x *ListToolHiveGroupsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListToolHiveGroupsRequest.ProtoReflect.Descriptor instead. func (*ListToolHiveGroupsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{122} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{124} } // ListToolHiveGroupsResponse carries the distinct, non-empty ToolHive groups. @@ -10947,7 +11083,7 @@ type ListToolHiveGroupsResponse struct { func (x *ListToolHiveGroupsResponse) Reset() { *x = ListToolHiveGroupsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[123] + mi := &file_mecatl_v1_harness_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10959,7 +11095,7 @@ func (x *ListToolHiveGroupsResponse) String() string { func (*ListToolHiveGroupsResponse) ProtoMessage() {} func (x *ListToolHiveGroupsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[123] + mi := &file_mecatl_v1_harness_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10972,7 +11108,7 @@ func (x *ListToolHiveGroupsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListToolHiveGroupsResponse.ProtoReflect.Descriptor instead. func (*ListToolHiveGroupsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{123} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{125} } func (x *ListToolHiveGroupsResponse) GetGroups() []string { @@ -11008,7 +11144,7 @@ type AgentInfo struct { func (x *AgentInfo) Reset() { *x = AgentInfo{} - mi := &file_mecatl_v1_harness_proto_msgTypes[124] + mi := &file_mecatl_v1_harness_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11020,7 +11156,7 @@ func (x *AgentInfo) String() string { func (*AgentInfo) ProtoMessage() {} func (x *AgentInfo) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[124] + mi := &file_mecatl_v1_harness_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11033,7 +11169,7 @@ func (x *AgentInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use AgentInfo.ProtoReflect.Descriptor instead. func (*AgentInfo) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{124} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{126} } func (x *AgentInfo) GetName() string { @@ -11087,7 +11223,7 @@ type ListAgentsRequest struct { func (x *ListAgentsRequest) Reset() { *x = ListAgentsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[125] + mi := &file_mecatl_v1_harness_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11099,7 +11235,7 @@ func (x *ListAgentsRequest) String() string { func (*ListAgentsRequest) ProtoMessage() {} func (x *ListAgentsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[125] + mi := &file_mecatl_v1_harness_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11112,7 +11248,7 @@ func (x *ListAgentsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAgentsRequest.ProtoReflect.Descriptor instead. func (*ListAgentsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{125} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{127} } // ListAgentsResponse carries the resolved agent definitions. @@ -11126,7 +11262,7 @@ type ListAgentsResponse struct { func (x *ListAgentsResponse) Reset() { *x = ListAgentsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[126] + mi := &file_mecatl_v1_harness_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11138,7 +11274,7 @@ func (x *ListAgentsResponse) String() string { func (*ListAgentsResponse) ProtoMessage() {} func (x *ListAgentsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[126] + mi := &file_mecatl_v1_harness_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11151,7 +11287,7 @@ func (x *ListAgentsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAgentsResponse.ProtoReflect.Descriptor instead. func (*ListAgentsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{126} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{128} } func (x *ListAgentsResponse) GetAgents() []*AgentInfo { @@ -11178,7 +11314,7 @@ type Command struct { func (x *Command) Reset() { *x = Command{} - mi := &file_mecatl_v1_harness_proto_msgTypes[127] + mi := &file_mecatl_v1_harness_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11190,7 +11326,7 @@ func (x *Command) String() string { func (*Command) ProtoMessage() {} func (x *Command) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[127] + mi := &file_mecatl_v1_harness_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11203,7 +11339,7 @@ func (x *Command) ProtoReflect() protoreflect.Message { // Deprecated: Use Command.ProtoReflect.Descriptor instead. func (*Command) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{127} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{129} } func (x *Command) GetName() string { @@ -11229,7 +11365,7 @@ type ListCommandsRequest struct { func (x *ListCommandsRequest) Reset() { *x = ListCommandsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[128] + mi := &file_mecatl_v1_harness_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11241,7 +11377,7 @@ func (x *ListCommandsRequest) String() string { func (*ListCommandsRequest) ProtoMessage() {} func (x *ListCommandsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[128] + mi := &file_mecatl_v1_harness_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11254,7 +11390,7 @@ func (x *ListCommandsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCommandsRequest.ProtoReflect.Descriptor instead. func (*ListCommandsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{128} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{130} } func (x *ListCommandsRequest) GetSessionId() string { @@ -11275,7 +11411,7 @@ type ListCommandsResponse struct { func (x *ListCommandsResponse) Reset() { *x = ListCommandsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[129] + mi := &file_mecatl_v1_harness_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11287,7 +11423,7 @@ func (x *ListCommandsResponse) String() string { func (*ListCommandsResponse) ProtoMessage() {} func (x *ListCommandsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[129] + mi := &file_mecatl_v1_harness_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11300,7 +11436,7 @@ func (x *ListCommandsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCommandsResponse.ProtoReflect.Descriptor instead. func (*ListCommandsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{129} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{131} } func (x *ListCommandsResponse) GetCommands() []*Command { @@ -11326,7 +11462,7 @@ type Worktree struct { func (x *Worktree) Reset() { *x = Worktree{} - mi := &file_mecatl_v1_harness_proto_msgTypes[130] + mi := &file_mecatl_v1_harness_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11338,7 +11474,7 @@ func (x *Worktree) String() string { func (*Worktree) ProtoMessage() {} func (x *Worktree) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[130] + mi := &file_mecatl_v1_harness_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11351,7 +11487,7 @@ func (x *Worktree) ProtoReflect() protoreflect.Message { // Deprecated: Use Worktree.ProtoReflect.Descriptor instead. func (*Worktree) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{130} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{132} } func (x *Worktree) GetSelector() string { @@ -11405,7 +11541,7 @@ type ListWorktreesRequest struct { func (x *ListWorktreesRequest) Reset() { *x = ListWorktreesRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[131] + mi := &file_mecatl_v1_harness_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11417,7 +11553,7 @@ func (x *ListWorktreesRequest) String() string { func (*ListWorktreesRequest) ProtoMessage() {} func (x *ListWorktreesRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[131] + mi := &file_mecatl_v1_harness_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11430,7 +11566,7 @@ func (x *ListWorktreesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorktreesRequest.ProtoReflect.Descriptor instead. func (*ListWorktreesRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{131} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{133} } func (x *ListWorktreesRequest) GetSessionId() string { @@ -11452,7 +11588,7 @@ type ListWorktreesResponse struct { func (x *ListWorktreesResponse) Reset() { *x = ListWorktreesResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[132] + mi := &file_mecatl_v1_harness_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11464,7 +11600,7 @@ func (x *ListWorktreesResponse) String() string { func (*ListWorktreesResponse) ProtoMessage() {} func (x *ListWorktreesResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[132] + mi := &file_mecatl_v1_harness_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11477,7 +11613,7 @@ func (x *ListWorktreesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorktreesResponse.ProtoReflect.Descriptor instead. func (*ListWorktreesResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{132} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{134} } func (x *ListWorktreesResponse) GetWorktrees() []*Worktree { @@ -11508,7 +11644,7 @@ type SkillInfo struct { func (x *SkillInfo) Reset() { *x = SkillInfo{} - mi := &file_mecatl_v1_harness_proto_msgTypes[133] + mi := &file_mecatl_v1_harness_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11520,7 +11656,7 @@ func (x *SkillInfo) String() string { func (*SkillInfo) ProtoMessage() {} func (x *SkillInfo) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[133] + mi := &file_mecatl_v1_harness_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11533,7 +11669,7 @@ func (x *SkillInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use SkillInfo.ProtoReflect.Descriptor instead. func (*SkillInfo) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{133} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{135} } func (x *SkillInfo) GetName() string { @@ -11580,7 +11716,7 @@ type ListSkillsRequest struct { func (x *ListSkillsRequest) Reset() { *x = ListSkillsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[134] + mi := &file_mecatl_v1_harness_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11592,7 +11728,7 @@ func (x *ListSkillsRequest) String() string { func (*ListSkillsRequest) ProtoMessage() {} func (x *ListSkillsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[134] + mi := &file_mecatl_v1_harness_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11605,7 +11741,7 @@ func (x *ListSkillsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSkillsRequest.ProtoReflect.Descriptor instead. func (*ListSkillsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{134} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{136} } // ListSkillsResponse carries the resolved skills inventory. @@ -11619,7 +11755,7 @@ type ListSkillsResponse struct { func (x *ListSkillsResponse) Reset() { *x = ListSkillsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[135] + mi := &file_mecatl_v1_harness_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11631,7 +11767,7 @@ func (x *ListSkillsResponse) String() string { func (*ListSkillsResponse) ProtoMessage() {} func (x *ListSkillsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[135] + mi := &file_mecatl_v1_harness_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11644,7 +11780,7 @@ func (x *ListSkillsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSkillsResponse.ProtoReflect.Descriptor instead. func (*ListSkillsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{135} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{137} } func (x *ListSkillsResponse) GetSkills() []*SkillInfo { @@ -11685,7 +11821,7 @@ type SoulInfo struct { func (x *SoulInfo) Reset() { *x = SoulInfo{} - mi := &file_mecatl_v1_harness_proto_msgTypes[136] + mi := &file_mecatl_v1_harness_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11697,7 +11833,7 @@ func (x *SoulInfo) String() string { func (*SoulInfo) ProtoMessage() {} func (x *SoulInfo) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[136] + mi := &file_mecatl_v1_harness_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11710,7 +11846,7 @@ func (x *SoulInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use SoulInfo.ProtoReflect.Descriptor instead. func (*SoulInfo) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{136} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{138} } func (x *SoulInfo) GetContent() string { @@ -11771,7 +11907,7 @@ type GetSoulRequest struct { func (x *GetSoulRequest) Reset() { *x = GetSoulRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[137] + mi := &file_mecatl_v1_harness_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11783,7 +11919,7 @@ func (x *GetSoulRequest) String() string { func (*GetSoulRequest) ProtoMessage() {} func (x *GetSoulRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[137] + mi := &file_mecatl_v1_harness_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11796,7 +11932,7 @@ func (x *GetSoulRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSoulRequest.ProtoReflect.Descriptor instead. func (*GetSoulRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{137} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{139} } // GetSoulResponse carries the resolved soul snapshot. @@ -11811,7 +11947,7 @@ type GetSoulResponse struct { func (x *GetSoulResponse) Reset() { *x = GetSoulResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[138] + mi := &file_mecatl_v1_harness_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11823,7 +11959,7 @@ func (x *GetSoulResponse) String() string { func (*GetSoulResponse) ProtoMessage() {} func (x *GetSoulResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[138] + mi := &file_mecatl_v1_harness_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11836,7 +11972,7 @@ func (x *GetSoulResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSoulResponse.ProtoReflect.Descriptor instead. func (*GetSoulResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{138} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{140} } func (x *GetSoulResponse) GetSoul() *SoulInfo { @@ -11861,7 +11997,7 @@ type UserModelEntry struct { func (x *UserModelEntry) Reset() { *x = UserModelEntry{} - mi := &file_mecatl_v1_harness_proto_msgTypes[139] + mi := &file_mecatl_v1_harness_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11873,7 +12009,7 @@ func (x *UserModelEntry) String() string { func (*UserModelEntry) ProtoMessage() {} func (x *UserModelEntry) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[139] + mi := &file_mecatl_v1_harness_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11886,7 +12022,7 @@ func (x *UserModelEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use UserModelEntry.ProtoReflect.Descriptor instead. func (*UserModelEntry) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{139} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{141} } func (x *UserModelEntry) GetKey() string { @@ -11914,7 +12050,7 @@ type GetUserModelRequest struct { func (x *GetUserModelRequest) Reset() { *x = GetUserModelRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[140] + mi := &file_mecatl_v1_harness_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11926,7 +12062,7 @@ func (x *GetUserModelRequest) String() string { func (*GetUserModelRequest) ProtoMessage() {} func (x *GetUserModelRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[140] + mi := &file_mecatl_v1_harness_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11939,7 +12075,7 @@ func (x *GetUserModelRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserModelRequest.ProtoReflect.Descriptor instead. func (*GetUserModelRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{140} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{142} } func (x *GetUserModelRequest) GetKey() string { @@ -11968,7 +12104,7 @@ type UserModelRevision struct { func (x *UserModelRevision) Reset() { *x = UserModelRevision{} - mi := &file_mecatl_v1_harness_proto_msgTypes[141] + mi := &file_mecatl_v1_harness_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11980,7 +12116,7 @@ func (x *UserModelRevision) String() string { func (*UserModelRevision) ProtoMessage() {} func (x *UserModelRevision) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[141] + mi := &file_mecatl_v1_harness_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11993,7 +12129,7 @@ func (x *UserModelRevision) ProtoReflect() protoreflect.Message { // Deprecated: Use UserModelRevision.ProtoReflect.Descriptor instead. func (*UserModelRevision) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{141} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{143} } func (x *UserModelRevision) GetKey() string { @@ -12078,7 +12214,7 @@ type UserModelDetail struct { func (x *UserModelDetail) Reset() { *x = UserModelDetail{} - mi := &file_mecatl_v1_harness_proto_msgTypes[142] + mi := &file_mecatl_v1_harness_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12090,7 +12226,7 @@ func (x *UserModelDetail) String() string { func (*UserModelDetail) ProtoMessage() {} func (x *UserModelDetail) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[142] + mi := &file_mecatl_v1_harness_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12103,7 +12239,7 @@ func (x *UserModelDetail) ProtoReflect() protoreflect.Message { // Deprecated: Use UserModelDetail.ProtoReflect.Descriptor instead. func (*UserModelDetail) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{142} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{144} } func (x *UserModelDetail) GetCurrent() *UserModelRevision { @@ -12147,7 +12283,7 @@ type GetUserModelResponse struct { func (x *GetUserModelResponse) Reset() { *x = GetUserModelResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[143] + mi := &file_mecatl_v1_harness_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12159,7 +12295,7 @@ func (x *GetUserModelResponse) String() string { func (*GetUserModelResponse) ProtoMessage() {} func (x *GetUserModelResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[143] + mi := &file_mecatl_v1_harness_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12172,7 +12308,7 @@ func (x *GetUserModelResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserModelResponse.ProtoReflect.Descriptor instead. func (*GetUserModelResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{143} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{145} } func (x *GetUserModelResponse) GetEntries() []*UserModelEntry { @@ -12229,7 +12365,7 @@ type ModelInfo struct { func (x *ModelInfo) Reset() { *x = ModelInfo{} - mi := &file_mecatl_v1_harness_proto_msgTypes[144] + mi := &file_mecatl_v1_harness_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12241,7 +12377,7 @@ func (x *ModelInfo) String() string { func (*ModelInfo) ProtoMessage() {} func (x *ModelInfo) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[144] + mi := &file_mecatl_v1_harness_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12254,7 +12390,7 @@ func (x *ModelInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ModelInfo.ProtoReflect.Descriptor instead. func (*ModelInfo) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{144} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{146} } func (x *ModelInfo) GetId() string { @@ -12308,7 +12444,7 @@ type ListModelsRequest struct { func (x *ListModelsRequest) Reset() { *x = ListModelsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[145] + mi := &file_mecatl_v1_harness_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12320,7 +12456,7 @@ func (x *ListModelsRequest) String() string { func (*ListModelsRequest) ProtoMessage() {} func (x *ListModelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[145] + mi := &file_mecatl_v1_harness_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12333,7 +12469,7 @@ func (x *ListModelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListModelsRequest.ProtoReflect.Descriptor instead. func (*ListModelsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{145} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{147} } // ProviderStatus is one provider's last live-listing outcome, for client @@ -12380,7 +12516,7 @@ type ProviderStatus struct { func (x *ProviderStatus) Reset() { *x = ProviderStatus{} - mi := &file_mecatl_v1_harness_proto_msgTypes[146] + mi := &file_mecatl_v1_harness_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12392,7 +12528,7 @@ func (x *ProviderStatus) String() string { func (*ProviderStatus) ProtoMessage() {} func (x *ProviderStatus) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[146] + mi := &file_mecatl_v1_harness_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12405,7 +12541,7 @@ func (x *ProviderStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderStatus.ProtoReflect.Descriptor instead. func (*ProviderStatus) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{146} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{148} } func (x *ProviderStatus) GetProviderId() string { @@ -12469,7 +12605,7 @@ type ListModelsResponse struct { func (x *ListModelsResponse) Reset() { *x = ListModelsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[147] + mi := &file_mecatl_v1_harness_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12481,7 +12617,7 @@ func (x *ListModelsResponse) String() string { func (*ListModelsResponse) ProtoMessage() {} func (x *ListModelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[147] + mi := &file_mecatl_v1_harness_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12494,7 +12630,7 @@ func (x *ListModelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListModelsResponse.ProtoReflect.Descriptor instead. func (*ListModelsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{147} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{149} } func (x *ListModelsResponse) GetModels() []*ModelInfo { @@ -12520,7 +12656,7 @@ type ReflectSessionRequest struct { func (x *ReflectSessionRequest) Reset() { *x = ReflectSessionRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[148] + mi := &file_mecatl_v1_harness_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12532,7 +12668,7 @@ func (x *ReflectSessionRequest) String() string { func (*ReflectSessionRequest) ProtoMessage() {} func (x *ReflectSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[148] + mi := &file_mecatl_v1_harness_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12545,7 +12681,7 @@ func (x *ReflectSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReflectSessionRequest.ProtoReflect.Descriptor instead. func (*ReflectSessionRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{148} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{150} } func (x *ReflectSessionRequest) GetSessionId() string { @@ -12574,7 +12710,7 @@ type ReflectionReceipt struct { func (x *ReflectionReceipt) Reset() { *x = ReflectionReceipt{} - mi := &file_mecatl_v1_harness_proto_msgTypes[149] + mi := &file_mecatl_v1_harness_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12586,7 +12722,7 @@ func (x *ReflectionReceipt) String() string { func (*ReflectionReceipt) ProtoMessage() {} func (x *ReflectionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[149] + mi := &file_mecatl_v1_harness_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12599,7 +12735,7 @@ func (x *ReflectionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ReflectionReceipt.ProtoReflect.Descriptor instead. func (*ReflectionReceipt) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{149} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{151} } func (x *ReflectionReceipt) GetReflectionId() string { @@ -12674,7 +12810,7 @@ type ReflectSessionResponse struct { func (x *ReflectSessionResponse) Reset() { *x = ReflectSessionResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[150] + mi := &file_mecatl_v1_harness_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12686,7 +12822,7 @@ func (x *ReflectSessionResponse) String() string { func (*ReflectSessionResponse) ProtoMessage() {} func (x *ReflectSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[150] + mi := &file_mecatl_v1_harness_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12699,7 +12835,7 @@ func (x *ReflectSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReflectSessionResponse.ProtoReflect.Descriptor instead. func (*ReflectSessionResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{150} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{152} } func (x *ReflectSessionResponse) GetReceipt() *ReflectionReceipt { @@ -12733,7 +12869,7 @@ type LearningAttempt struct { func (x *LearningAttempt) Reset() { *x = LearningAttempt{} - mi := &file_mecatl_v1_harness_proto_msgTypes[151] + mi := &file_mecatl_v1_harness_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12745,7 +12881,7 @@ func (x *LearningAttempt) String() string { func (*LearningAttempt) ProtoMessage() {} func (x *LearningAttempt) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[151] + mi := &file_mecatl_v1_harness_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12758,7 +12894,7 @@ func (x *LearningAttempt) ProtoReflect() protoreflect.Message { // Deprecated: Use LearningAttempt.ProtoReflect.Descriptor instead. func (*LearningAttempt) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{151} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{153} } func (x *LearningAttempt) GetId() string { @@ -12861,7 +12997,7 @@ type GetLearningAttemptRequest struct { func (x *GetLearningAttemptRequest) Reset() { *x = GetLearningAttemptRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[152] + mi := &file_mecatl_v1_harness_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12873,7 +13009,7 @@ func (x *GetLearningAttemptRequest) String() string { func (*GetLearningAttemptRequest) ProtoMessage() {} func (x *GetLearningAttemptRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[152] + mi := &file_mecatl_v1_harness_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12886,7 +13022,7 @@ func (x *GetLearningAttemptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearningAttemptRequest.ProtoReflect.Descriptor instead. func (*GetLearningAttemptRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{152} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{154} } func (x *GetLearningAttemptRequest) GetId() string { @@ -12905,7 +13041,7 @@ type GetLearningAttemptResponse struct { func (x *GetLearningAttemptResponse) Reset() { *x = GetLearningAttemptResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[153] + mi := &file_mecatl_v1_harness_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12917,7 +13053,7 @@ func (x *GetLearningAttemptResponse) String() string { func (*GetLearningAttemptResponse) ProtoMessage() {} func (x *GetLearningAttemptResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[153] + mi := &file_mecatl_v1_harness_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12930,7 +13066,7 @@ func (x *GetLearningAttemptResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearningAttemptResponse.ProtoReflect.Descriptor instead. func (*GetLearningAttemptResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{153} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{155} } func (x *GetLearningAttemptResponse) GetAttempt() *LearningAttempt { @@ -12951,7 +13087,7 @@ type ListLearningAttemptsRequest struct { func (x *ListLearningAttemptsRequest) Reset() { *x = ListLearningAttemptsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[154] + mi := &file_mecatl_v1_harness_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12963,7 +13099,7 @@ func (x *ListLearningAttemptsRequest) String() string { func (*ListLearningAttemptsRequest) ProtoMessage() {} func (x *ListLearningAttemptsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[154] + mi := &file_mecatl_v1_harness_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12976,7 +13112,7 @@ func (x *ListLearningAttemptsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearningAttemptsRequest.ProtoReflect.Descriptor instead. func (*ListLearningAttemptsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{154} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{156} } func (x *ListLearningAttemptsRequest) GetState() string { @@ -13010,7 +13146,7 @@ type ListLearningAttemptsResponse struct { func (x *ListLearningAttemptsResponse) Reset() { *x = ListLearningAttemptsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[155] + mi := &file_mecatl_v1_harness_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13022,7 +13158,7 @@ func (x *ListLearningAttemptsResponse) String() string { func (*ListLearningAttemptsResponse) ProtoMessage() {} func (x *ListLearningAttemptsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[155] + mi := &file_mecatl_v1_harness_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13035,7 +13171,7 @@ func (x *ListLearningAttemptsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearningAttemptsResponse.ProtoReflect.Descriptor instead. func (*ListLearningAttemptsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{155} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{157} } func (x *ListLearningAttemptsResponse) GetAttempts() []*LearningAttempt { @@ -13062,7 +13198,7 @@ type MutateLearningAttemptRequest struct { func (x *MutateLearningAttemptRequest) Reset() { *x = MutateLearningAttemptRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[156] + mi := &file_mecatl_v1_harness_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13074,7 +13210,7 @@ func (x *MutateLearningAttemptRequest) String() string { func (*MutateLearningAttemptRequest) ProtoMessage() {} func (x *MutateLearningAttemptRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[156] + mi := &file_mecatl_v1_harness_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13087,7 +13223,7 @@ func (x *MutateLearningAttemptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutateLearningAttemptRequest.ProtoReflect.Descriptor instead. func (*MutateLearningAttemptRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{156} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{158} } func (x *MutateLearningAttemptRequest) GetId() string { @@ -13113,7 +13249,7 @@ type MutateLearningAttemptResponse struct { func (x *MutateLearningAttemptResponse) Reset() { *x = MutateLearningAttemptResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[157] + mi := &file_mecatl_v1_harness_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13125,7 +13261,7 @@ func (x *MutateLearningAttemptResponse) String() string { func (*MutateLearningAttemptResponse) ProtoMessage() {} func (x *MutateLearningAttemptResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[157] + mi := &file_mecatl_v1_harness_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13138,7 +13274,7 @@ func (x *MutateLearningAttemptResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutateLearningAttemptResponse.ProtoReflect.Descriptor instead. func (*MutateLearningAttemptResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{157} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{159} } func (x *MutateLearningAttemptResponse) GetAttempt() *LearningAttempt { @@ -13161,7 +13297,7 @@ type ListLearningProposalsRequest struct { func (x *ListLearningProposalsRequest) Reset() { *x = ListLearningProposalsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[158] + mi := &file_mecatl_v1_harness_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13173,7 +13309,7 @@ func (x *ListLearningProposalsRequest) String() string { func (*ListLearningProposalsRequest) ProtoMessage() {} func (x *ListLearningProposalsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[158] + mi := &file_mecatl_v1_harness_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13186,7 +13322,7 @@ func (x *ListLearningProposalsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearningProposalsRequest.ProtoReflect.Descriptor instead. func (*ListLearningProposalsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{158} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{160} } func (x *ListLearningProposalsRequest) GetStatus() string { @@ -13236,7 +13372,7 @@ type LearningEvidenceRef struct { func (x *LearningEvidenceRef) Reset() { *x = LearningEvidenceRef{} - mi := &file_mecatl_v1_harness_proto_msgTypes[159] + mi := &file_mecatl_v1_harness_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13248,7 +13384,7 @@ func (x *LearningEvidenceRef) String() string { func (*LearningEvidenceRef) ProtoMessage() {} func (x *LearningEvidenceRef) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[159] + mi := &file_mecatl_v1_harness_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13261,7 +13397,7 @@ func (x *LearningEvidenceRef) ProtoReflect() protoreflect.Message { // Deprecated: Use LearningEvidenceRef.ProtoReflect.Descriptor instead. func (*LearningEvidenceRef) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{159} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{161} } func (x *LearningEvidenceRef) GetSessionId() string { @@ -13339,7 +13475,7 @@ type LearningDecision struct { func (x *LearningDecision) Reset() { *x = LearningDecision{} - mi := &file_mecatl_v1_harness_proto_msgTypes[160] + mi := &file_mecatl_v1_harness_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13351,7 +13487,7 @@ func (x *LearningDecision) String() string { func (*LearningDecision) ProtoMessage() {} func (x *LearningDecision) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[160] + mi := &file_mecatl_v1_harness_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13364,7 +13500,7 @@ func (x *LearningDecision) ProtoReflect() protoreflect.Message { // Deprecated: Use LearningDecision.ProtoReflect.Descriptor instead. func (*LearningDecision) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{160} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{162} } func (x *LearningDecision) GetKind() string { @@ -13407,7 +13543,7 @@ type LearningPromotionReceipt struct { func (x *LearningPromotionReceipt) Reset() { *x = LearningPromotionReceipt{} - mi := &file_mecatl_v1_harness_proto_msgTypes[161] + mi := &file_mecatl_v1_harness_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13419,7 +13555,7 @@ func (x *LearningPromotionReceipt) String() string { func (*LearningPromotionReceipt) ProtoMessage() {} func (x *LearningPromotionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[161] + mi := &file_mecatl_v1_harness_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13432,7 +13568,7 @@ func (x *LearningPromotionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use LearningPromotionReceipt.ProtoReflect.Descriptor instead. func (*LearningPromotionReceipt) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{161} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{163} } func (x *LearningPromotionReceipt) GetMemoryKey() string { @@ -13494,7 +13630,7 @@ type LearningProposal struct { func (x *LearningProposal) Reset() { *x = LearningProposal{} - mi := &file_mecatl_v1_harness_proto_msgTypes[162] + mi := &file_mecatl_v1_harness_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13506,7 +13642,7 @@ func (x *LearningProposal) String() string { func (*LearningProposal) ProtoMessage() {} func (x *LearningProposal) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[162] + mi := &file_mecatl_v1_harness_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13519,7 +13655,7 @@ func (x *LearningProposal) ProtoReflect() protoreflect.Message { // Deprecated: Use LearningProposal.ProtoReflect.Descriptor instead. func (*LearningProposal) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{162} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{164} } func (x *LearningProposal) GetId() string { @@ -13665,7 +13801,7 @@ type ListLearningProposalsResponse struct { func (x *ListLearningProposalsResponse) Reset() { *x = ListLearningProposalsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[163] + mi := &file_mecatl_v1_harness_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13677,7 +13813,7 @@ func (x *ListLearningProposalsResponse) String() string { func (*ListLearningProposalsResponse) ProtoMessage() {} func (x *ListLearningProposalsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[163] + mi := &file_mecatl_v1_harness_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13690,7 +13826,7 @@ func (x *ListLearningProposalsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearningProposalsResponse.ProtoReflect.Descriptor instead. func (*ListLearningProposalsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{163} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{165} } func (x *ListLearningProposalsResponse) GetProposals() []*LearningProposal { @@ -13717,7 +13853,7 @@ type GetLearningProposalRequest struct { func (x *GetLearningProposalRequest) Reset() { *x = GetLearningProposalRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[164] + mi := &file_mecatl_v1_harness_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13729,7 +13865,7 @@ func (x *GetLearningProposalRequest) String() string { func (*GetLearningProposalRequest) ProtoMessage() {} func (x *GetLearningProposalRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[164] + mi := &file_mecatl_v1_harness_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13742,7 +13878,7 @@ func (x *GetLearningProposalRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearningProposalRequest.ProtoReflect.Descriptor instead. func (*GetLearningProposalRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{164} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{166} } func (x *GetLearningProposalRequest) GetId() string { @@ -13768,7 +13904,7 @@ type GetLearningProposalResponse struct { func (x *GetLearningProposalResponse) Reset() { *x = GetLearningProposalResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[165] + mi := &file_mecatl_v1_harness_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13780,7 +13916,7 @@ func (x *GetLearningProposalResponse) String() string { func (*GetLearningProposalResponse) ProtoMessage() {} func (x *GetLearningProposalResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[165] + mi := &file_mecatl_v1_harness_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13793,7 +13929,7 @@ func (x *GetLearningProposalResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearningProposalResponse.ProtoReflect.Descriptor instead. func (*GetLearningProposalResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{165} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{167} } func (x *GetLearningProposalResponse) GetProposal() *LearningProposal { @@ -13816,7 +13952,7 @@ type DecideLearningProposalRequest struct { func (x *DecideLearningProposalRequest) Reset() { *x = DecideLearningProposalRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[166] + mi := &file_mecatl_v1_harness_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13828,7 +13964,7 @@ func (x *DecideLearningProposalRequest) String() string { func (*DecideLearningProposalRequest) ProtoMessage() {} func (x *DecideLearningProposalRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[166] + mi := &file_mecatl_v1_harness_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13841,7 +13977,7 @@ func (x *DecideLearningProposalRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DecideLearningProposalRequest.ProtoReflect.Descriptor instead. func (*DecideLearningProposalRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{166} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{168} } func (x *DecideLearningProposalRequest) GetId() string { @@ -13888,7 +14024,7 @@ type DecideLearningProposalResponse struct { func (x *DecideLearningProposalResponse) Reset() { *x = DecideLearningProposalResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[167] + mi := &file_mecatl_v1_harness_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13900,7 +14036,7 @@ func (x *DecideLearningProposalResponse) String() string { func (*DecideLearningProposalResponse) ProtoMessage() {} func (x *DecideLearningProposalResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[167] + mi := &file_mecatl_v1_harness_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13913,7 +14049,7 @@ func (x *DecideLearningProposalResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DecideLearningProposalResponse.ProtoReflect.Descriptor instead. func (*DecideLearningProposalResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{167} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{169} } func (x *DecideLearningProposalResponse) GetProposal() *LearningProposal { @@ -13934,7 +14070,7 @@ type UndoLearningPromotionRequest struct { func (x *UndoLearningPromotionRequest) Reset() { *x = UndoLearningPromotionRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[168] + mi := &file_mecatl_v1_harness_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13946,7 +14082,7 @@ func (x *UndoLearningPromotionRequest) String() string { func (*UndoLearningPromotionRequest) ProtoMessage() {} func (x *UndoLearningPromotionRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[168] + mi := &file_mecatl_v1_harness_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13959,7 +14095,7 @@ func (x *UndoLearningPromotionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoLearningPromotionRequest.ProtoReflect.Descriptor instead. func (*UndoLearningPromotionRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{168} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{170} } func (x *UndoLearningPromotionRequest) GetId() string { @@ -13992,7 +14128,7 @@ type UndoLearningPromotionResponse struct { func (x *UndoLearningPromotionResponse) Reset() { *x = UndoLearningPromotionResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[169] + mi := &file_mecatl_v1_harness_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14004,7 +14140,7 @@ func (x *UndoLearningPromotionResponse) String() string { func (*UndoLearningPromotionResponse) ProtoMessage() {} func (x *UndoLearningPromotionResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[169] + mi := &file_mecatl_v1_harness_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14017,7 +14153,7 @@ func (x *UndoLearningPromotionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoLearningPromotionResponse.ProtoReflect.Descriptor instead. func (*UndoLearningPromotionResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{169} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{171} } func (x *UndoLearningPromotionResponse) GetProposal() *LearningProposal { @@ -14054,7 +14190,7 @@ type LearnedSkillVersion struct { func (x *LearnedSkillVersion) Reset() { *x = LearnedSkillVersion{} - mi := &file_mecatl_v1_harness_proto_msgTypes[170] + mi := &file_mecatl_v1_harness_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14066,7 +14202,7 @@ func (x *LearnedSkillVersion) String() string { func (*LearnedSkillVersion) ProtoMessage() {} func (x *LearnedSkillVersion) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[170] + mi := &file_mecatl_v1_harness_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14079,7 +14215,7 @@ func (x *LearnedSkillVersion) ProtoReflect() protoreflect.Message { // Deprecated: Use LearnedSkillVersion.ProtoReflect.Descriptor instead. func (*LearnedSkillVersion) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{170} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{172} } func (x *LearnedSkillVersion) GetId() string { @@ -14215,7 +14351,7 @@ type SkillEvaluation struct { func (x *SkillEvaluation) Reset() { *x = SkillEvaluation{} - mi := &file_mecatl_v1_harness_proto_msgTypes[171] + mi := &file_mecatl_v1_harness_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14227,7 +14363,7 @@ func (x *SkillEvaluation) String() string { func (*SkillEvaluation) ProtoMessage() {} func (x *SkillEvaluation) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[171] + mi := &file_mecatl_v1_harness_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14240,7 +14376,7 @@ func (x *SkillEvaluation) ProtoReflect() protoreflect.Message { // Deprecated: Use SkillEvaluation.ProtoReflect.Descriptor instead. func (*SkillEvaluation) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{171} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{173} } func (x *SkillEvaluation) GetVerdict() string { @@ -14310,7 +14446,7 @@ type SkillChangeReceipt struct { func (x *SkillChangeReceipt) Reset() { *x = SkillChangeReceipt{} - mi := &file_mecatl_v1_harness_proto_msgTypes[172] + mi := &file_mecatl_v1_harness_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14322,7 +14458,7 @@ func (x *SkillChangeReceipt) String() string { func (*SkillChangeReceipt) ProtoMessage() {} func (x *SkillChangeReceipt) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[172] + mi := &file_mecatl_v1_harness_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14335,7 +14471,7 @@ func (x *SkillChangeReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use SkillChangeReceipt.ProtoReflect.Descriptor instead. func (*SkillChangeReceipt) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{172} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{174} } func (x *SkillChangeReceipt) GetId() string { @@ -14470,7 +14606,7 @@ type ListLearnedSkillsRequest struct { func (x *ListLearnedSkillsRequest) Reset() { *x = ListLearnedSkillsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[173] + mi := &file_mecatl_v1_harness_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14482,7 +14618,7 @@ func (x *ListLearnedSkillsRequest) String() string { func (*ListLearnedSkillsRequest) ProtoMessage() {} func (x *ListLearnedSkillsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[173] + mi := &file_mecatl_v1_harness_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14495,7 +14631,7 @@ func (x *ListLearnedSkillsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearnedSkillsRequest.ProtoReflect.Descriptor instead. func (*ListLearnedSkillsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{173} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{175} } func (x *ListLearnedSkillsRequest) GetProject() string { @@ -14545,7 +14681,7 @@ type ListLearnedSkillsResponse struct { func (x *ListLearnedSkillsResponse) Reset() { *x = ListLearnedSkillsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[174] + mi := &file_mecatl_v1_harness_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14557,7 +14693,7 @@ func (x *ListLearnedSkillsResponse) String() string { func (*ListLearnedSkillsResponse) ProtoMessage() {} func (x *ListLearnedSkillsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[174] + mi := &file_mecatl_v1_harness_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14570,7 +14706,7 @@ func (x *ListLearnedSkillsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLearnedSkillsResponse.ProtoReflect.Descriptor instead. func (*ListLearnedSkillsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{174} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{176} } func (x *ListLearnedSkillsResponse) GetSkills() []*LearnedSkillVersion { @@ -14613,7 +14749,7 @@ type GetLearnedSkillRequest struct { func (x *GetLearnedSkillRequest) Reset() { *x = GetLearnedSkillRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[175] + mi := &file_mecatl_v1_harness_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14625,7 +14761,7 @@ func (x *GetLearnedSkillRequest) String() string { func (*GetLearnedSkillRequest) ProtoMessage() {} func (x *GetLearnedSkillRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[175] + mi := &file_mecatl_v1_harness_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14638,7 +14774,7 @@ func (x *GetLearnedSkillRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearnedSkillRequest.ProtoReflect.Descriptor instead. func (*GetLearnedSkillRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{175} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{177} } func (x *GetLearnedSkillRequest) GetProject() string { @@ -14680,7 +14816,7 @@ type GetLearnedSkillResponse struct { func (x *GetLearnedSkillResponse) Reset() { *x = GetLearnedSkillResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[176] + mi := &file_mecatl_v1_harness_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14692,7 +14828,7 @@ func (x *GetLearnedSkillResponse) String() string { func (*GetLearnedSkillResponse) ProtoMessage() {} func (x *GetLearnedSkillResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[176] + mi := &file_mecatl_v1_harness_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14705,7 +14841,7 @@ func (x *GetLearnedSkillResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLearnedSkillResponse.ProtoReflect.Descriptor instead. func (*GetLearnedSkillResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{176} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{178} } func (x *GetLearnedSkillResponse) GetSkill() *LearnedSkillVersion { @@ -14742,7 +14878,7 @@ type DiffLearnedSkillVersionsRequest struct { func (x *DiffLearnedSkillVersionsRequest) Reset() { *x = DiffLearnedSkillVersionsRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[177] + mi := &file_mecatl_v1_harness_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14754,7 +14890,7 @@ func (x *DiffLearnedSkillVersionsRequest) String() string { func (*DiffLearnedSkillVersionsRequest) ProtoMessage() {} func (x *DiffLearnedSkillVersionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[177] + mi := &file_mecatl_v1_harness_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14767,7 +14903,7 @@ func (x *DiffLearnedSkillVersionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DiffLearnedSkillVersionsRequest.ProtoReflect.Descriptor instead. func (*DiffLearnedSkillVersionsRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{177} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{179} } func (x *DiffLearnedSkillVersionsRequest) GetProject() string { @@ -14819,7 +14955,7 @@ type DiffLearnedSkillVersionsResponse struct { func (x *DiffLearnedSkillVersionsResponse) Reset() { *x = DiffLearnedSkillVersionsResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[178] + mi := &file_mecatl_v1_harness_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14831,7 +14967,7 @@ func (x *DiffLearnedSkillVersionsResponse) String() string { func (*DiffLearnedSkillVersionsResponse) ProtoMessage() {} func (x *DiffLearnedSkillVersionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[178] + mi := &file_mecatl_v1_harness_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14844,7 +14980,7 @@ func (x *DiffLearnedSkillVersionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DiffLearnedSkillVersionsResponse.ProtoReflect.Descriptor instead. func (*DiffLearnedSkillVersionsResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{178} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{180} } func (x *DiffLearnedSkillVersionsResponse) GetDiff() string { @@ -14902,7 +15038,7 @@ type MutateLearnedSkillRequest struct { func (x *MutateLearnedSkillRequest) Reset() { *x = MutateLearnedSkillRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[179] + mi := &file_mecatl_v1_harness_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14914,7 +15050,7 @@ func (x *MutateLearnedSkillRequest) String() string { func (*MutateLearnedSkillRequest) ProtoMessage() {} func (x *MutateLearnedSkillRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[179] + mi := &file_mecatl_v1_harness_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14927,7 +15063,7 @@ func (x *MutateLearnedSkillRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MutateLearnedSkillRequest.ProtoReflect.Descriptor instead. func (*MutateLearnedSkillRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{179} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{181} } func (x *MutateLearnedSkillRequest) GetProject() string { @@ -14978,7 +15114,7 @@ type MutateLearnedSkillResponse struct { func (x *MutateLearnedSkillResponse) Reset() { *x = MutateLearnedSkillResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[180] + mi := &file_mecatl_v1_harness_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14990,7 +15126,7 @@ func (x *MutateLearnedSkillResponse) String() string { func (*MutateLearnedSkillResponse) ProtoMessage() {} func (x *MutateLearnedSkillResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[180] + mi := &file_mecatl_v1_harness_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15003,7 +15139,7 @@ func (x *MutateLearnedSkillResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MutateLearnedSkillResponse.ProtoReflect.Descriptor instead. func (*MutateLearnedSkillResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{180} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{182} } func (x *MutateLearnedSkillResponse) GetSkill() *LearnedSkillVersion { @@ -15054,7 +15190,7 @@ type RollbackLearnedSkillRequest struct { func (x *RollbackLearnedSkillRequest) Reset() { *x = RollbackLearnedSkillRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[181] + mi := &file_mecatl_v1_harness_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15066,7 +15202,7 @@ func (x *RollbackLearnedSkillRequest) String() string { func (*RollbackLearnedSkillRequest) ProtoMessage() {} func (x *RollbackLearnedSkillRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[181] + mi := &file_mecatl_v1_harness_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15079,7 +15215,7 @@ func (x *RollbackLearnedSkillRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RollbackLearnedSkillRequest.ProtoReflect.Descriptor instead. func (*RollbackLearnedSkillRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{181} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{183} } func (x *RollbackLearnedSkillRequest) GetProject() string { @@ -15128,7 +15264,7 @@ type ListSkillChangesRequest struct { func (x *ListSkillChangesRequest) Reset() { *x = ListSkillChangesRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[182] + mi := &file_mecatl_v1_harness_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15140,7 +15276,7 @@ func (x *ListSkillChangesRequest) String() string { func (*ListSkillChangesRequest) ProtoMessage() {} func (x *ListSkillChangesRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[182] + mi := &file_mecatl_v1_harness_proto_msgTypes[184] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15153,7 +15289,7 @@ func (x *ListSkillChangesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSkillChangesRequest.ProtoReflect.Descriptor instead. func (*ListSkillChangesRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{182} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{184} } func (x *ListSkillChangesRequest) GetProject() string { @@ -15189,7 +15325,7 @@ type ListSkillChangesResponse struct { func (x *ListSkillChangesResponse) Reset() { *x = ListSkillChangesResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[183] + mi := &file_mecatl_v1_harness_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15201,7 +15337,7 @@ func (x *ListSkillChangesResponse) String() string { func (*ListSkillChangesResponse) ProtoMessage() {} func (x *ListSkillChangesResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[183] + mi := &file_mecatl_v1_harness_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15214,7 +15350,7 @@ func (x *ListSkillChangesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSkillChangesResponse.ProtoReflect.Descriptor instead. func (*ListSkillChangesResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{183} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{185} } func (x *ListSkillChangesResponse) GetChanges() []*SkillChangeReceipt { @@ -15278,7 +15414,7 @@ type CreateTeamRequest struct { func (x *CreateTeamRequest) Reset() { *x = CreateTeamRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[184] + mi := &file_mecatl_v1_harness_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15290,7 +15426,7 @@ func (x *CreateTeamRequest) String() string { func (*CreateTeamRequest) ProtoMessage() {} func (x *CreateTeamRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[184] + mi := &file_mecatl_v1_harness_proto_msgTypes[186] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15303,7 +15439,7 @@ func (x *CreateTeamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateTeamRequest.ProtoReflect.Descriptor instead. func (*CreateTeamRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{184} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{186} } func (x *CreateTeamRequest) GetSessionId() string { @@ -15355,7 +15491,7 @@ type CreateTeamResponse struct { func (x *CreateTeamResponse) Reset() { *x = CreateTeamResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[185] + mi := &file_mecatl_v1_harness_proto_msgTypes[187] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15367,7 +15503,7 @@ func (x *CreateTeamResponse) String() string { func (*CreateTeamResponse) ProtoMessage() {} func (x *CreateTeamResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[185] + mi := &file_mecatl_v1_harness_proto_msgTypes[187] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15380,7 +15516,7 @@ func (x *CreateTeamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateTeamResponse.ProtoReflect.Descriptor instead. func (*CreateTeamResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{185} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{187} } func (x *CreateTeamResponse) GetTeamId() string { @@ -15417,7 +15553,7 @@ type TeammateSpec struct { func (x *TeammateSpec) Reset() { *x = TeammateSpec{} - mi := &file_mecatl_v1_harness_proto_msgTypes[186] + mi := &file_mecatl_v1_harness_proto_msgTypes[188] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15429,7 +15565,7 @@ func (x *TeammateSpec) String() string { func (*TeammateSpec) ProtoMessage() {} func (x *TeammateSpec) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[186] + mi := &file_mecatl_v1_harness_proto_msgTypes[188] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15442,7 +15578,7 @@ func (x *TeammateSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use TeammateSpec.ProtoReflect.Descriptor instead. func (*TeammateSpec) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{186} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{188} } func (x *TeammateSpec) GetName() string { @@ -15501,7 +15637,7 @@ type SpawnTeammateRequest struct { func (x *SpawnTeammateRequest) Reset() { *x = SpawnTeammateRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[187] + mi := &file_mecatl_v1_harness_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15513,7 +15649,7 @@ func (x *SpawnTeammateRequest) String() string { func (*SpawnTeammateRequest) ProtoMessage() {} func (x *SpawnTeammateRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[187] + mi := &file_mecatl_v1_harness_proto_msgTypes[189] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15526,7 +15662,7 @@ func (x *SpawnTeammateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SpawnTeammateRequest.ProtoReflect.Descriptor instead. func (*SpawnTeammateRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{187} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{189} } func (x *SpawnTeammateRequest) GetTeamId() string { @@ -15582,7 +15718,7 @@ type SpawnTeammateResponse struct { func (x *SpawnTeammateResponse) Reset() { *x = SpawnTeammateResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[188] + mi := &file_mecatl_v1_harness_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15594,7 +15730,7 @@ func (x *SpawnTeammateResponse) String() string { func (*SpawnTeammateResponse) ProtoMessage() {} func (x *SpawnTeammateResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[188] + mi := &file_mecatl_v1_harness_proto_msgTypes[190] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15607,7 +15743,7 @@ func (x *SpawnTeammateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SpawnTeammateResponse.ProtoReflect.Descriptor instead. func (*SpawnTeammateResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{188} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{190} } func (x *SpawnTeammateResponse) GetMember() *TeamMember { @@ -15634,7 +15770,7 @@ type SendTeammateMessageRequest struct { func (x *SendTeammateMessageRequest) Reset() { *x = SendTeammateMessageRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[189] + mi := &file_mecatl_v1_harness_proto_msgTypes[191] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15646,7 +15782,7 @@ func (x *SendTeammateMessageRequest) String() string { func (*SendTeammateMessageRequest) ProtoMessage() {} func (x *SendTeammateMessageRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[189] + mi := &file_mecatl_v1_harness_proto_msgTypes[191] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15659,7 +15795,7 @@ func (x *SendTeammateMessageRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SendTeammateMessageRequest.ProtoReflect.Descriptor instead. func (*SendTeammateMessageRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{189} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{191} } func (x *SendTeammateMessageRequest) GetTeamId() string { @@ -15699,7 +15835,7 @@ type SendTeammateMessageResponse struct { func (x *SendTeammateMessageResponse) Reset() { *x = SendTeammateMessageResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[190] + mi := &file_mecatl_v1_harness_proto_msgTypes[192] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15711,7 +15847,7 @@ func (x *SendTeammateMessageResponse) String() string { func (*SendTeammateMessageResponse) ProtoMessage() {} func (x *SendTeammateMessageResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[190] + mi := &file_mecatl_v1_harness_proto_msgTypes[192] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15724,7 +15860,7 @@ func (x *SendTeammateMessageResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SendTeammateMessageResponse.ProtoReflect.Descriptor instead. func (*SendTeammateMessageResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{190} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{192} } // CancelTeammateRequest cancels one member of a running team. @@ -15740,7 +15876,7 @@ type CancelTeammateRequest struct { func (x *CancelTeammateRequest) Reset() { *x = CancelTeammateRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[191] + mi := &file_mecatl_v1_harness_proto_msgTypes[193] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15752,7 +15888,7 @@ func (x *CancelTeammateRequest) String() string { func (*CancelTeammateRequest) ProtoMessage() {} func (x *CancelTeammateRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[191] + mi := &file_mecatl_v1_harness_proto_msgTypes[193] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15765,7 +15901,7 @@ func (x *CancelTeammateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CancelTeammateRequest.ProtoReflect.Descriptor instead. func (*CancelTeammateRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{191} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{193} } func (x *CancelTeammateRequest) GetTeamId() string { @@ -15791,7 +15927,7 @@ type CancelTeammateResponse struct { func (x *CancelTeammateResponse) Reset() { *x = CancelTeammateResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[192] + mi := &file_mecatl_v1_harness_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15803,7 +15939,7 @@ func (x *CancelTeammateResponse) String() string { func (*CancelTeammateResponse) ProtoMessage() {} func (x *CancelTeammateResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[192] + mi := &file_mecatl_v1_harness_proto_msgTypes[194] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15816,7 +15952,7 @@ func (x *CancelTeammateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CancelTeammateResponse.ProtoReflect.Descriptor instead. func (*CancelTeammateResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{192} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{194} } // RunTeamRequest drives a team to quiescence, streaming member events. @@ -15830,7 +15966,7 @@ type RunTeamRequest struct { func (x *RunTeamRequest) Reset() { *x = RunTeamRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[193] + mi := &file_mecatl_v1_harness_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15842,7 +15978,7 @@ func (x *RunTeamRequest) String() string { func (*RunTeamRequest) ProtoMessage() {} func (x *RunTeamRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[193] + mi := &file_mecatl_v1_harness_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15855,7 +15991,7 @@ func (x *RunTeamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RunTeamRequest.ProtoReflect.Descriptor instead. func (*RunTeamRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{193} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{195} } func (x *RunTeamRequest) GetTeamId() string { @@ -15883,7 +16019,7 @@ type TeamEvent struct { func (x *TeamEvent) Reset() { *x = TeamEvent{} - mi := &file_mecatl_v1_harness_proto_msgTypes[194] + mi := &file_mecatl_v1_harness_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15895,7 +16031,7 @@ func (x *TeamEvent) String() string { func (*TeamEvent) ProtoMessage() {} func (x *TeamEvent) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[194] + mi := &file_mecatl_v1_harness_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15908,7 +16044,7 @@ func (x *TeamEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamEvent.ProtoReflect.Descriptor instead. func (*TeamEvent) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{194} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{196} } func (x *TeamEvent) GetMember() string { @@ -15968,7 +16104,7 @@ type TeamOutcome struct { func (x *TeamOutcome) Reset() { *x = TeamOutcome{} - mi := &file_mecatl_v1_harness_proto_msgTypes[195] + mi := &file_mecatl_v1_harness_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15980,7 +16116,7 @@ func (x *TeamOutcome) String() string { func (*TeamOutcome) ProtoMessage() {} func (x *TeamOutcome) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[195] + mi := &file_mecatl_v1_harness_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15993,7 +16129,7 @@ func (x *TeamOutcome) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamOutcome.ProtoReflect.Descriptor instead. func (*TeamOutcome) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{195} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{197} } func (x *TeamOutcome) GetRounds() int32 { @@ -16056,7 +16192,7 @@ type ListTeamRequest struct { func (x *ListTeamRequest) Reset() { *x = ListTeamRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[196] + mi := &file_mecatl_v1_harness_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16068,7 +16204,7 @@ func (x *ListTeamRequest) String() string { func (*ListTeamRequest) ProtoMessage() {} func (x *ListTeamRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[196] + mi := &file_mecatl_v1_harness_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16081,7 +16217,7 @@ func (x *ListTeamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTeamRequest.ProtoReflect.Descriptor instead. func (*ListTeamRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{196} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{198} } func (x *ListTeamRequest) GetTeamId() string { @@ -16106,7 +16242,7 @@ type ListTeamResponse struct { func (x *ListTeamResponse) Reset() { *x = ListTeamResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[197] + mi := &file_mecatl_v1_harness_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16118,7 +16254,7 @@ func (x *ListTeamResponse) String() string { func (*ListTeamResponse) ProtoMessage() {} func (x *ListTeamResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[197] + mi := &file_mecatl_v1_harness_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16131,7 +16267,7 @@ func (x *ListTeamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTeamResponse.ProtoReflect.Descriptor instead. func (*ListTeamResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{197} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{199} } func (x *ListTeamResponse) GetMembers() []*TeamMember { @@ -16172,7 +16308,7 @@ type TeamMember struct { func (x *TeamMember) Reset() { *x = TeamMember{} - mi := &file_mecatl_v1_harness_proto_msgTypes[198] + mi := &file_mecatl_v1_harness_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16184,7 +16320,7 @@ func (x *TeamMember) String() string { func (*TeamMember) ProtoMessage() {} func (x *TeamMember) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[198] + mi := &file_mecatl_v1_harness_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16197,7 +16333,7 @@ func (x *TeamMember) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamMember.ProtoReflect.Descriptor instead. func (*TeamMember) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{198} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{200} } func (x *TeamMember) GetName() string { @@ -16247,7 +16383,7 @@ type TeamTask struct { func (x *TeamTask) Reset() { *x = TeamTask{} - mi := &file_mecatl_v1_harness_proto_msgTypes[199] + mi := &file_mecatl_v1_harness_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16259,7 +16395,7 @@ func (x *TeamTask) String() string { func (*TeamTask) ProtoMessage() {} func (x *TeamTask) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[199] + mi := &file_mecatl_v1_harness_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16272,7 +16408,7 @@ func (x *TeamTask) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamTask.ProtoReflect.Descriptor instead. func (*TeamTask) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{199} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{201} } func (x *TeamTask) GetId() string { @@ -16325,7 +16461,7 @@ type TeamFinding struct { func (x *TeamFinding) Reset() { *x = TeamFinding{} - mi := &file_mecatl_v1_harness_proto_msgTypes[200] + mi := &file_mecatl_v1_harness_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16337,7 +16473,7 @@ func (x *TeamFinding) String() string { func (*TeamFinding) ProtoMessage() {} func (x *TeamFinding) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[200] + mi := &file_mecatl_v1_harness_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16350,7 +16486,7 @@ func (x *TeamFinding) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamFinding.ProtoReflect.Descriptor instead. func (*TeamFinding) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{200} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{202} } func (x *TeamFinding) GetMember() string { @@ -16393,7 +16529,7 @@ type TeamMemberDisposition struct { func (x *TeamMemberDisposition) Reset() { *x = TeamMemberDisposition{} - mi := &file_mecatl_v1_harness_proto_msgTypes[201] + mi := &file_mecatl_v1_harness_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16405,7 +16541,7 @@ func (x *TeamMemberDisposition) String() string { func (*TeamMemberDisposition) ProtoMessage() {} func (x *TeamMemberDisposition) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[201] + mi := &file_mecatl_v1_harness_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16418,7 +16554,7 @@ func (x *TeamMemberDisposition) ProtoReflect() protoreflect.Message { // Deprecated: Use TeamMemberDisposition.ProtoReflect.Descriptor instead. func (*TeamMemberDisposition) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{201} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{203} } func (x *TeamMemberDisposition) GetName() string { @@ -16460,7 +16596,7 @@ type CleanupTeamRequest struct { func (x *CleanupTeamRequest) Reset() { *x = CleanupTeamRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[202] + mi := &file_mecatl_v1_harness_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16472,7 +16608,7 @@ func (x *CleanupTeamRequest) String() string { func (*CleanupTeamRequest) ProtoMessage() {} func (x *CleanupTeamRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[202] + mi := &file_mecatl_v1_harness_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16485,7 +16621,7 @@ func (x *CleanupTeamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CleanupTeamRequest.ProtoReflect.Descriptor instead. func (*CleanupTeamRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{202} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{204} } func (x *CleanupTeamRequest) GetTeamId() string { @@ -16504,7 +16640,7 @@ type CleanupTeamResponse struct { func (x *CleanupTeamResponse) Reset() { *x = CleanupTeamResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[203] + mi := &file_mecatl_v1_harness_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16516,7 +16652,7 @@ func (x *CleanupTeamResponse) String() string { func (*CleanupTeamResponse) ProtoMessage() {} func (x *CleanupTeamResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[203] + mi := &file_mecatl_v1_harness_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16529,7 +16665,7 @@ func (x *CleanupTeamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CleanupTeamResponse.ProtoReflect.Descriptor instead. func (*CleanupTeamResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{203} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{205} } // ApprovePlanRequest resolves a parked plan-approval ask (issue #206). See the @@ -16552,7 +16688,7 @@ type ApprovePlanRequest struct { func (x *ApprovePlanRequest) Reset() { *x = ApprovePlanRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[204] + mi := &file_mecatl_v1_harness_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16564,7 +16700,7 @@ func (x *ApprovePlanRequest) String() string { func (*ApprovePlanRequest) ProtoMessage() {} func (x *ApprovePlanRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[204] + mi := &file_mecatl_v1_harness_proto_msgTypes[206] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16577,7 +16713,7 @@ func (x *ApprovePlanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApprovePlanRequest.ProtoReflect.Descriptor instead. func (*ApprovePlanRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{204} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{206} } func (x *ApprovePlanRequest) GetSessionId() string { @@ -16613,7 +16749,7 @@ type ManualDreamCapabilities struct { func (x *ManualDreamCapabilities) Reset() { *x = ManualDreamCapabilities{} - mi := &file_mecatl_v1_harness_proto_msgTypes[205] + mi := &file_mecatl_v1_harness_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16625,7 +16761,7 @@ func (x *ManualDreamCapabilities) String() string { func (*ManualDreamCapabilities) ProtoMessage() {} func (x *ManualDreamCapabilities) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[205] + mi := &file_mecatl_v1_harness_proto_msgTypes[207] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16638,7 +16774,7 @@ func (x *ManualDreamCapabilities) ProtoReflect() protoreflect.Message { // Deprecated: Use ManualDreamCapabilities.ProtoReflect.Descriptor instead. func (*ManualDreamCapabilities) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{205} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{207} } func (x *ManualDreamCapabilities) GetProjectMemory() *DreamTargetCapability { @@ -16666,7 +16802,7 @@ type DreamTargetCapability struct { func (x *DreamTargetCapability) Reset() { *x = DreamTargetCapability{} - mi := &file_mecatl_v1_harness_proto_msgTypes[206] + mi := &file_mecatl_v1_harness_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16678,7 +16814,7 @@ func (x *DreamTargetCapability) String() string { func (*DreamTargetCapability) ProtoMessage() {} func (x *DreamTargetCapability) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[206] + mi := &file_mecatl_v1_harness_proto_msgTypes[208] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16691,7 +16827,7 @@ func (x *DreamTargetCapability) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamTargetCapability.ProtoReflect.Descriptor instead. func (*DreamTargetCapability) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{206} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{208} } func (x *DreamTargetCapability) GetGenerate() bool { @@ -16725,7 +16861,7 @@ type GenerateDreamPlanRequest struct { func (x *GenerateDreamPlanRequest) Reset() { *x = GenerateDreamPlanRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[207] + mi := &file_mecatl_v1_harness_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16737,7 +16873,7 @@ func (x *GenerateDreamPlanRequest) String() string { func (*GenerateDreamPlanRequest) ProtoMessage() {} func (x *GenerateDreamPlanRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[207] + mi := &file_mecatl_v1_harness_proto_msgTypes[209] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16750,7 +16886,7 @@ func (x *GenerateDreamPlanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateDreamPlanRequest.ProtoReflect.Descriptor instead. func (*GenerateDreamPlanRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{207} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{209} } func (x *GenerateDreamPlanRequest) GetTarget() string { @@ -16769,7 +16905,7 @@ type GenerateDreamPlanResponse struct { func (x *GenerateDreamPlanResponse) Reset() { *x = GenerateDreamPlanResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[208] + mi := &file_mecatl_v1_harness_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16781,7 +16917,7 @@ func (x *GenerateDreamPlanResponse) String() string { func (*GenerateDreamPlanResponse) ProtoMessage() {} func (x *GenerateDreamPlanResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[208] + mi := &file_mecatl_v1_harness_proto_msgTypes[210] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16794,7 +16930,7 @@ func (x *GenerateDreamPlanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateDreamPlanResponse.ProtoReflect.Descriptor instead. func (*GenerateDreamPlanResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{208} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{210} } func (x *GenerateDreamPlanResponse) GetPlan() *DreamReviewPlan { @@ -16815,7 +16951,7 @@ type DecideDreamPlanRequest struct { func (x *DecideDreamPlanRequest) Reset() { *x = DecideDreamPlanRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[209] + mi := &file_mecatl_v1_harness_proto_msgTypes[211] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16827,7 +16963,7 @@ func (x *DecideDreamPlanRequest) String() string { func (*DecideDreamPlanRequest) ProtoMessage() {} func (x *DecideDreamPlanRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[209] + mi := &file_mecatl_v1_harness_proto_msgTypes[211] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16840,7 +16976,7 @@ func (x *DecideDreamPlanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DecideDreamPlanRequest.ProtoReflect.Descriptor instead. func (*DecideDreamPlanRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{209} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{211} } func (x *DecideDreamPlanRequest) GetPlanId() string { @@ -16866,7 +17002,7 @@ type DecideDreamPlanResponse struct { func (x *DecideDreamPlanResponse) Reset() { *x = DecideDreamPlanResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[210] + mi := &file_mecatl_v1_harness_proto_msgTypes[212] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16878,7 +17014,7 @@ func (x *DecideDreamPlanResponse) String() string { func (*DecideDreamPlanResponse) ProtoMessage() {} func (x *DecideDreamPlanResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[210] + mi := &file_mecatl_v1_harness_proto_msgTypes[212] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16891,7 +17027,7 @@ func (x *DecideDreamPlanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DecideDreamPlanResponse.ProtoReflect.Descriptor instead. func (*DecideDreamPlanResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{210} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{212} } func (x *DecideDreamPlanResponse) GetReceipt() *DreamReceipt { @@ -16915,7 +17051,7 @@ type DreamReviewPlan struct { func (x *DreamReviewPlan) Reset() { *x = DreamReviewPlan{} - mi := &file_mecatl_v1_harness_proto_msgTypes[211] + mi := &file_mecatl_v1_harness_proto_msgTypes[213] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16927,7 +17063,7 @@ func (x *DreamReviewPlan) String() string { func (*DreamReviewPlan) ProtoMessage() {} func (x *DreamReviewPlan) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[211] + mi := &file_mecatl_v1_harness_proto_msgTypes[213] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16940,7 +17076,7 @@ func (x *DreamReviewPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamReviewPlan.ProtoReflect.Descriptor instead. func (*DreamReviewPlan) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{211} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{213} } func (x *DreamReviewPlan) GetId() string { @@ -16999,7 +17135,7 @@ type DreamOperation struct { func (x *DreamOperation) Reset() { *x = DreamOperation{} - mi := &file_mecatl_v1_harness_proto_msgTypes[212] + mi := &file_mecatl_v1_harness_proto_msgTypes[214] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17011,7 +17147,7 @@ func (x *DreamOperation) String() string { func (*DreamOperation) ProtoMessage() {} func (x *DreamOperation) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[212] + mi := &file_mecatl_v1_harness_proto_msgTypes[214] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17024,7 +17160,7 @@ func (x *DreamOperation) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamOperation.ProtoReflect.Descriptor instead. func (*DreamOperation) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{212} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{214} } func (x *DreamOperation) GetKind() string { @@ -17080,7 +17216,7 @@ type DreamParticipant struct { func (x *DreamParticipant) Reset() { *x = DreamParticipant{} - mi := &file_mecatl_v1_harness_proto_msgTypes[213] + mi := &file_mecatl_v1_harness_proto_msgTypes[215] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17092,7 +17228,7 @@ func (x *DreamParticipant) String() string { func (*DreamParticipant) ProtoMessage() {} func (x *DreamParticipant) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[213] + mi := &file_mecatl_v1_harness_proto_msgTypes[215] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17105,7 +17241,7 @@ func (x *DreamParticipant) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamParticipant.ProtoReflect.Descriptor instead. func (*DreamParticipant) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{213} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{215} } func (x *DreamParticipant) GetKey() string { @@ -17139,7 +17275,7 @@ type DreamReplacement struct { func (x *DreamReplacement) Reset() { *x = DreamReplacement{} - mi := &file_mecatl_v1_harness_proto_msgTypes[214] + mi := &file_mecatl_v1_harness_proto_msgTypes[216] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17151,7 +17287,7 @@ func (x *DreamReplacement) String() string { func (*DreamReplacement) ProtoMessage() {} func (x *DreamReplacement) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[214] + mi := &file_mecatl_v1_harness_proto_msgTypes[216] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17164,7 +17300,7 @@ func (x *DreamReplacement) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamReplacement.ProtoReflect.Descriptor instead. func (*DreamReplacement) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{214} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{216} } func (x *DreamReplacement) GetValue() string { @@ -17197,7 +17333,7 @@ type DreamReceipt struct { func (x *DreamReceipt) Reset() { *x = DreamReceipt{} - mi := &file_mecatl_v1_harness_proto_msgTypes[215] + mi := &file_mecatl_v1_harness_proto_msgTypes[217] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17209,7 +17345,7 @@ func (x *DreamReceipt) String() string { func (*DreamReceipt) ProtoMessage() {} func (x *DreamReceipt) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[215] + mi := &file_mecatl_v1_harness_proto_msgTypes[217] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17222,7 +17358,7 @@ func (x *DreamReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use DreamReceipt.ProtoReflect.Descriptor instead. func (*DreamReceipt) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{215} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{217} } func (x *DreamReceipt) GetId() string { @@ -17291,7 +17427,7 @@ type CompactSessionRequest struct { func (x *CompactSessionRequest) Reset() { *x = CompactSessionRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[216] + mi := &file_mecatl_v1_harness_proto_msgTypes[218] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17303,7 +17439,7 @@ func (x *CompactSessionRequest) String() string { func (*CompactSessionRequest) ProtoMessage() {} func (x *CompactSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[216] + mi := &file_mecatl_v1_harness_proto_msgTypes[218] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17316,7 +17452,7 @@ func (x *CompactSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompactSessionRequest.ProtoReflect.Descriptor instead. func (*CompactSessionRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{216} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{218} } func (x *CompactSessionRequest) GetSessionId() string { @@ -17336,7 +17472,7 @@ type CompactSessionResponse struct { func (x *CompactSessionResponse) Reset() { *x = CompactSessionResponse{} - mi := &file_mecatl_v1_harness_proto_msgTypes[217] + mi := &file_mecatl_v1_harness_proto_msgTypes[219] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17348,7 +17484,7 @@ func (x *CompactSessionResponse) String() string { func (*CompactSessionResponse) ProtoMessage() {} func (x *CompactSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[217] + mi := &file_mecatl_v1_harness_proto_msgTypes[219] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17361,7 +17497,7 @@ func (x *CompactSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompactSessionResponse.ProtoReflect.Descriptor instead. func (*CompactSessionResponse) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{217} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{219} } func (x *CompactSessionResponse) GetCompacted() bool { @@ -17381,7 +17517,7 @@ type WorkspaceEnrollmentConnectRequest struct { func (x *WorkspaceEnrollmentConnectRequest) Reset() { *x = WorkspaceEnrollmentConnectRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[218] + mi := &file_mecatl_v1_harness_proto_msgTypes[220] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17393,7 +17529,7 @@ func (x *WorkspaceEnrollmentConnectRequest) String() string { func (*WorkspaceEnrollmentConnectRequest) ProtoMessage() {} func (x *WorkspaceEnrollmentConnectRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[218] + mi := &file_mecatl_v1_harness_proto_msgTypes[220] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17406,7 +17542,7 @@ func (x *WorkspaceEnrollmentConnectRequest) ProtoReflect() protoreflect.Message // Deprecated: Use WorkspaceEnrollmentConnectRequest.ProtoReflect.Descriptor instead. func (*WorkspaceEnrollmentConnectRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{218} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{220} } func (x *WorkspaceEnrollmentConnectRequest) GetSessionId() string { @@ -17428,7 +17564,7 @@ type WorkspaceEnrollmentControlRequest struct { func (x *WorkspaceEnrollmentControlRequest) Reset() { *x = WorkspaceEnrollmentControlRequest{} - mi := &file_mecatl_v1_harness_proto_msgTypes[219] + mi := &file_mecatl_v1_harness_proto_msgTypes[221] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17440,7 +17576,7 @@ func (x *WorkspaceEnrollmentControlRequest) String() string { func (*WorkspaceEnrollmentControlRequest) ProtoMessage() {} func (x *WorkspaceEnrollmentControlRequest) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[219] + mi := &file_mecatl_v1_harness_proto_msgTypes[221] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17453,7 +17589,7 @@ func (x *WorkspaceEnrollmentControlRequest) ProtoReflect() protoreflect.Message // Deprecated: Use WorkspaceEnrollmentControlRequest.ProtoReflect.Descriptor instead. func (*WorkspaceEnrollmentControlRequest) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{219} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{221} } func (x *WorkspaceEnrollmentControlRequest) GetSessionId() string { @@ -17484,7 +17620,7 @@ type WorkspaceEnrollment struct { func (x *WorkspaceEnrollment) Reset() { *x = WorkspaceEnrollment{} - mi := &file_mecatl_v1_harness_proto_msgTypes[220] + mi := &file_mecatl_v1_harness_proto_msgTypes[222] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17496,7 +17632,7 @@ func (x *WorkspaceEnrollment) String() string { func (*WorkspaceEnrollment) ProtoMessage() {} func (x *WorkspaceEnrollment) ProtoReflect() protoreflect.Message { - mi := &file_mecatl_v1_harness_proto_msgTypes[220] + mi := &file_mecatl_v1_harness_proto_msgTypes[222] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17509,7 +17645,7 @@ func (x *WorkspaceEnrollment) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceEnrollment.ProtoReflect.Descriptor instead. func (*WorkspaceEnrollment) Descriptor() ([]byte, []int) { - return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{220} + return file_mecatl_v1_harness_proto_rawDescGZIP(), []int{222} } func (x *WorkspaceEnrollment) GetEnrollmentId() string { @@ -17627,7 +17763,7 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xda, 0x07, 0x0a, 0x12, + 0x0a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xfb, 0x07, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x63, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x63, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x63, 0x6f, @@ -17688,2831 +17824,2854 @@ var file_mecatl_v1_harness_proto_rawDesc = string([]byte{ 0x30, 0x0a, 0x14, 0x6d, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x4a, 0x04, 0x08, 0x14, 0x10, 0x15, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, - 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x40, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xf9, 0x01, 0x0a, 0x20, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3d, - 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x29, 0x0a, - 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, 0x6e, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, 0x75, - 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x70, 0x0a, 0x12, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x75, 0x65, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, - 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, - 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x15, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x14, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x71, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x9d, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x29, 0x0a, 0x10, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x66, 0x66, 0x6f, 0x72, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, - 0x67, 0x45, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x22, 0x41, 0x0a, 0x13, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x22, 0x3b, 0x0a, 0x11, 0x47, 0x65, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x42, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, - 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x1b, 0x47, - 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, + 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6d, 0x63, 0x70, 0x52, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x4a, 0x04, 0x08, 0x14, 0x10, 0x15, 0x52, 0x0f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x5f, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x40, 0x0a, 0x1f, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xf9, 0x01, 0x0a, 0x20, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x3d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x29, + 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, + 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, + 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x70, 0x0a, 0x12, 0x4d, 0x63, 0x70, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x75, 0x65, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, + 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, + 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x15, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x14, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x71, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x9d, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x29, 0x0a, + 0x10, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x66, 0x66, 0x6f, 0x72, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, + 0x6e, 0x67, 0x45, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x22, 0x41, 0x0a, 0x13, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, + 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x22, 0x3b, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x42, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, + 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x1b, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x70, 0x6c, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x22, 0xaa, 0x02, 0x0a, 0x1c, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x68, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x22, 0x44, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x42, + 0x0a, 0x18, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, + 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x22, 0x76, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x70, 0x6c, 0x61, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x22, 0xaa, 0x02, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x49, 0x64, 0x22, 0x72, 0x0a, 0x19, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, + 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x72, 0x0a, 0x1a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, + 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x22, 0x4a, 0x0a, 0x13, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x70, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, + 0x70, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd9, 0x06, 0x0a, 0x0e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, - 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x68, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x22, 0x44, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x42, 0x0a, - 0x18, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x22, 0x72, 0x0a, 0x19, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, - 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x15, - 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x72, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x72, 0x0a, 0x1a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, - 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, - 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x22, 0x4a, 0x0a, 0x13, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, - 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x70, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xd9, 0x06, 0x0a, 0x0e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x6f, 0x64, - 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x55, - 0x6e, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x75, 0x72, - 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x12, - 0x19, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, 0x6e, - 0x69, 0x78, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x2a, 0x0a, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, - 0x6c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, 0x0c, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, - 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, - 0x12, 0x4b, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, - 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2d, - 0x0a, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0f, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x3a, 0x0a, - 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, - 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0e, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0d, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4a, 0x0a, 0x0b, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, - 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x54, 0x0a, 0x0f, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x22, 0xd5, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2a, 0x0a, 0x11, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, - 0x12, 0x26, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x63, 0x68, 0x65, - 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, - 0x11, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, - 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, - 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x64, 0x65, 0x62, 0x75, 0x67, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x87, 0x03, 0x0a, 0x1c, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, + 0x55, 0x6e, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x75, + 0x72, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, + 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, + 0x6e, 0x69, 0x78, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x2a, 0x0a, + 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, + 0x61, 0x6c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, + 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x68, 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, + 0x70, 0x12, 0x4b, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, + 0x74, 0x6f, 0x72, 0x79, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x2d, 0x0a, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0f, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x3a, + 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, + 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0e, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0d, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4a, 0x0a, 0x0b, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x55, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x54, 0x0a, + 0x0f, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x22, 0xd5, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2a, 0x0a, 0x11, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, + 0x64, 0x12, 0x26, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, + 0x0a, 0x11, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, + 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, + 0x6d, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x64, 0x65, 0x62, 0x75, 0x67, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, + 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x87, 0x03, 0x0a, + 0x1c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, + 0x79, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x39, 0x0a, 0x18, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, + 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x17, 0x0a, 0x07, + 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, + 0x6f, 0x70, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x76, 0x69, 0x65, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x6f, + 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x12, 0x42, 0x0a, 0x07, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, - 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x74, 0x12, 0x18, 0x0a, - 0x07, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x39, 0x0a, 0x18, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, - 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x63, - 0x6f, 0x70, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6f, - 0x70, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x76, - 0x69, 0x65, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x6f, 0x72, - 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x12, 0x42, 0x0a, 0x07, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x22, 0xe0, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x73, 0x70, - 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x73, 0x70, 0x65, - 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x70, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x76, - 0x69, 0x65, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x08, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, - 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, - 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x61, 0x69, - 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x78, - 0x41, 0x67, 0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, - 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x31, 0x0a, 0x15, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, - 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x78, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x63, 0x68, - 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x73, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, - 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, - 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, - 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x4d, 0x61, - 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, - 0x63, 0x61, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x73, 0x77, 0x65, 0x65, 0x70, 0x43, 0x61, 0x64, 0x65, - 0x6e, 0x63, 0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0xaa, 0x0c, 0x0a, 0x18, 0x47, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x22, 0xe0, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x68, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x73, + 0x70, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x70, 0x79, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, + 0x76, 0x69, 0x65, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, + 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, + 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, - 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x3e, - 0x0a, 0x1b, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x19, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x23, - 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x31, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x31, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x76, 0x32, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x07, 0x76, 0x32, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x61, - 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x68, - 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, - 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, - 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, - 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x06, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x75, 0x6e, - 0x69, 0x78, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x77, - 0x65, 0x65, 0x70, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, - 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x13, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, 0x55, 0x6e, 0x69, - 0x78, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, - 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x12, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6a, 0x6f, - 0x62, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4a, - 0x6f, 0x62, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, - 0x72, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, - 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x51, 0x0a, 0x25, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x75, 0x6e, - 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, - 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x1a, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x13, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, - 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x5f, - 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x1c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x73, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x42, 0x0a, - 0x1d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, - 0x75, 0x6c, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x1c, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x12, 0x53, 0x0a, 0x26, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x5f, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x1d, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x23, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, - 0x64, 0x75, 0x6c, 0x65, 0x73, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, - 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, - 0x65, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, - 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x1f, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x16, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x22, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x20, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, - 0x73, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x72, - 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x50, 0x6c, 0x61, 0x6e, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8f, 0x03, 0x0a, 0x14, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61, 0x6e, 0x12, - 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe2, 0x02, 0x0a, 0x0f, 0x52, 0x65, 0x74, 0x65, 0x6e, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2f, 0x0a, 0x14, 0x6d, 0x61, + 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, + 0x78, 0x41, 0x67, 0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, + 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, + 0x67, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x12, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x61, + 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x4d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, + 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x16, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, + 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x4d, + 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x77, 0x65, 0x65, 0x70, + 0x5f, 0x63, 0x61, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x73, 0x77, 0x65, 0x65, 0x70, 0x43, 0x61, 0x64, + 0x65, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0xaa, 0x0c, 0x0a, 0x18, + 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x31, 0x5f, 0x66, 0x61, 0x6d, 0x69, - 0x6c, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x31, 0x46, 0x61, - 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x32, 0x5f, 0x66, 0x61, 0x6d, - 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x32, 0x46, - 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, - 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x6b, - 0x69, 0x70, 0x70, 0x65, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, - 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x27, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5f, 0x0a, 0x1c, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, - 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x5e, 0x0a, 0x1d, 0x52, 0x65, 0x73, - 0x75, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, 0x6f, - 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, - 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x3f, 0x0a, 0x1d, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, 0x6f, - 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x1d, 0x47, 0x65, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, + 0x3e, 0x0a, 0x1b, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, + 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x31, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x31, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x76, 0x32, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x69, + 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, + 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x75, + 0x70, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x06, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x75, + 0x6e, 0x69, 0x78, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x53, + 0x77, 0x65, 0x65, 0x70, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x77, 0x65, 0x65, + 0x70, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x13, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, 0x55, 0x6e, + 0x69, 0x78, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, + 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x12, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, 0x41, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6a, + 0x6f, 0x62, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x4a, 0x6f, 0x62, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, + 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x41, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x51, 0x0a, 0x25, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x75, + 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x22, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, + 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x1a, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x13, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, + 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x1c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x42, + 0x0a, 0x1d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x73, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, + 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x53, 0x0a, 0x26, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x5f, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x1d, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x23, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x6c, 0x65, 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x1f, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x16, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x22, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x6c, 0x65, + 0x73, 0x73, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x54, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x50, 0x6c, 0x61, 0x6e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8f, 0x03, 0x0a, 0x14, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61, 0x6e, + 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x31, 0x5f, 0x66, 0x61, 0x6d, + 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x31, 0x46, + 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x32, 0x5f, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x32, + 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, + 0x69, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, + 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x23, + 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, + 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, + 0x72, 0x61, 0x72, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5f, 0x0a, 0x1c, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x70, 0x6c, 0x61, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x5e, 0x0a, 0x1d, 0x52, 0x65, + 0x73, 0x75, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x19, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x74, 0x65, 0x6d, - 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, - 0x74, 0x65, 0x6d, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x9f, 0x03, 0x0a, 0x0d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x3d, 0x0a, 0x07, - 0x62, 0x79, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x62, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x08, 0x62, - 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x62, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, - 0x09, 0x62, 0x79, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x52, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x62, 0x79, 0x52, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3a, 0x0a, - 0x0c, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x42, 0x79, 0x52, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc6, 0x01, 0x0a, 0x10, 0x43, 0x6c, 0x65, 0x61, 0x6e, - 0x75, 0x70, 0x43, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, - 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, - 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, 0x78, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x41, 0x74, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, - 0x31, 0x0a, 0x19, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, - 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x69, 0x6e, - 0x64, 0x73, 0x22, 0xe2, 0x03, 0x0a, 0x1a, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2d, - 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, - 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, - 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x08, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x43, 0x61, 0x6e, 0x64, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x08, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x36, 0x0a, - 0x09, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, - 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x4a, - 0x6f, 0x62, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x0e, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, - 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, 0x0a, - 0x1b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, - 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, - 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x3d, 0x0a, 0x1b, - 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x3f, 0x0a, 0x1d, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x10, 0x43, - 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x1f, 0x0a, 0x0b, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x74, 0x65, 0x6d, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xe5, 0x03, 0x0a, 0x13, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x1d, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, + 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x19, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x74, 0x65, + 0x6d, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x69, 0x74, 0x65, 0x6d, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9f, 0x03, 0x0a, 0x0d, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x3d, 0x0a, + 0x07, 0x62, 0x79, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x62, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x08, + 0x62, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x62, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x43, + 0x0a, 0x09, 0x62, 0x79, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x65, 0x61, 0x6e, 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x42, 0x79, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x62, 0x79, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3a, + 0x0a, 0x0c, 0x42, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x42, 0x79, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc6, 0x01, 0x0a, 0x10, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x75, 0x70, 0x43, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, + 0x10, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, 0x69, + 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x41, 0x74, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x73, 0x74, 0x69, 0x6d, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0e, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x22, 0x31, 0x0a, 0x19, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x69, + 0x6e, 0x64, 0x73, 0x22, 0xe2, 0x03, 0x0a, 0x1a, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1e, + 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x08, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, + 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x43, 0x61, 0x6e, 0x64, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x08, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x36, + 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x65, 0x61, 0x6e, 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, + 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0e, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x24, 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, + 0x4a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, + 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x0e, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, + 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x6c, + 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, + 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x11, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, + 0x0a, 0x1b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, + 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x3d, 0x0a, + 0x1b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, + 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x10, + 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x74, 0x65, 0x6d, 0x48, 0x61, 0x6e, 0x64, 0x6c, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xe5, 0x03, 0x0a, + 0x13, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x31, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x31, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, + 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x32, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x32, 0x46, 0x61, 0x6d, 0x69, 0x6c, + 0x69, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, + 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x29, + 0x0a, 0x10, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, + 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x74, + 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x06, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x73, 0x22, 0xee, 0x01, 0x0a, 0x0a, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x31, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x31, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x32, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x32, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, - 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x29, 0x0a, - 0x10, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, - 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, - 0x11, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x6c, 0x61, 0x69, - 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x65, - 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, - 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x3c, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, - 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x06, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x73, 0x22, 0xee, 0x01, 0x0a, 0x0a, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x4a, - 0x6f, 0x62, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, - 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, - 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, - 0x33, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x06, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x73, 0x22, 0x67, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, + 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x18, + 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, + 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, + 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x12, 0x33, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, + 0x61, 0x6e, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x06, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0x67, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x2d, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x3f, + 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x3d, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2d, - 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x3f, 0x0a, - 0x0f, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2c, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3d, - 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x16, 0x0a, - 0x14, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5d, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, - 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x22, 0x45, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, - 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x0a, 0x14, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x13, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x11, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x30, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, - 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, - 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x71, 0x0a, 0x14, 0x43, 0x6c, 0x65, - 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x8e, 0x02, 0x0a, - 0x12, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, - 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x29, - 0x0a, 0x10, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x66, 0x66, 0x6f, - 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x69, 0x6e, 0x67, 0x45, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x77, 0x6f, 0x72, - 0x6b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x77, 0x6f, 0x72, 0x6b, - 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x70, 0x0a, - 0x13, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x8b, 0x08, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x2d, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, - 0x29, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6d, 0x69, - 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x75, - 0x72, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x12, - 0x26, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x6e, - 0x69, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x3f, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x05, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, - 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x0f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, - 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2a, 0x0a, 0x11, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, 0x63, - 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x65, 0x62, 0x75, - 0x67, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0d, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, 0x63, 0x70, 0x54, 0x6f, 0x6f, 0x6c, 0x73, - 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, 0x0e, - 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0d, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, 0x0b, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x14, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x51, 0x0a, 0x14, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x16, + 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5d, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, + 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x45, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, + 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x0a, 0x14, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x13, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, + 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x30, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, + 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x71, 0x0a, 0x14, 0x43, 0x6c, + 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x8e, 0x02, + 0x0a, 0x12, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x66, 0x66, + 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x66, 0x66, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x0a, 0x11, 0x77, 0x6f, + 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, + 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, + 0x08, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x64, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x70, + 0x0a, 0x13, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x22, 0x8b, 0x08, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, + 0x12, 0x29, 0x0a, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x73, 0x52, 0x06, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x75, 0x72, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, + 0x6e, 0x69, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x3f, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x10, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, + 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, + 0x01, 0x52, 0x0f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x42, 0x0a, 0x0c, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, - 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x0f, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, - 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, - 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x52, 0x1a, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0xd2, 0x01, - 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x45, 0x0a, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x41, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x13, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6d, - 0x70, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, - 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, - 0x6f, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0xbc, 0x01, 0x0a, 0x0a, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x12, 0x39, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x1a, 0x4b, 0x0a, 0x0b, 0x4d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8c, 0x03, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x06, - 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, - 0x00, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x72, 0x65, 0x74, - 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x48, - 0x00, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x75, - 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x0e, - 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x2b, - 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x3b, 0x0a, 0x0c, 0x63, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x65, - 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x65, - 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0c, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, - 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0xb7, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, - 0x2b, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, - 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, - 0x3c, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x10, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, - 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, - 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x55, 0x44, 0x49, 0x4f, 0x10, 0x02, 0x22, 0xf3, 0x03, - 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x30, - 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, - 0x23, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x22, 0x9c, 0x01, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, - 0x10, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x45, 0x58, 0x54, - 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, - 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x55, 0x44, 0x49, 0x4f, - 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x4b, 0x49, - 0x4e, 0x44, 0x5f, 0x45, 0x4d, 0x42, 0x45, 0x44, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, - 0x54, 0x52, 0x55, 0x43, 0x54, 0x55, 0x52, 0x45, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, - 0x54, 0x10, 0x06, 0x22, 0x34, 0x0a, 0x0a, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x06, 0x50, 0x72, 0x6f, - 0x6d, 0x70, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, - 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x0e, 0x52, 0x65, - 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x1e, 0x0a, 0x06, - 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x12, 0x34, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x56, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x52, - 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, - 0x22, 0x30, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, - 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, - 0x49, 0x64, 0x22, 0x31, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, 0x6c, - 0x64, 0x12, 0x22, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x63, 0x68, - 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x65, 0x65, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x65, 0x78, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x49, 0x64, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, - 0x75, 0x6e, 0x49, 0x64, 0x22, 0x54, 0x0a, 0x0b, 0x53, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, - 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x26, 0x47, - 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x32, 0x0a, - 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x22, 0x3b, 0x0a, 0x27, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xe8, - 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x29, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x44, 0x0a, 0x0f, 0x72, - 0x65, 0x73, 0x75, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x48, - 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, - 0x6c, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x09, - 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, 0x49, 0x0a, 0x1f, 0x52, 0x65, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, + 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2a, 0x0a, + 0x11, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, + 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x65, 0x62, + 0x75, 0x67, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x11, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x62, 0x75, 0x67, 0x4d, 0x63, 0x70, 0x54, 0x6f, 0x6f, 0x6c, + 0x73, 0x12, 0x3a, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x12, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3e, 0x0a, + 0x0e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x0d, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x43, 0x0a, + 0x0b, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x14, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x51, 0x0a, 0x14, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x61, + 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x52, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x0f, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, + 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x04, 0x10, + 0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x1a, 0x61, 0x64, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0xd2, + 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x45, 0x0a, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6d, + 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, + 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x45, 0x0a, 0x13, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, + 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, + 0x63, 0x6f, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0xbc, 0x01, 0x0a, 0x0a, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x12, 0x39, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x1a, 0x4b, 0x0a, 0x0b, + 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8c, 0x03, 0x0a, 0x0f, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, + 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, + 0x48, 0x00, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x72, 0x65, + 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x74, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x0f, 0x72, 0x65, 0x73, + 0x75, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x48, 0x00, 0x52, + 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, + 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x3b, 0x0a, 0x0c, + 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x65, + 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, + 0x65, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0c, 0x73, 0x74, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x22, 0xe7, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, - 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x44, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, 0x48, - 0x0a, 0x1e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x39, - 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x03, 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, 0x09, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xab, 0x08, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x03, 0x73, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x04, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x30, 0x0a, 0x09, - 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, - 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x36, - 0x0a, 0x0b, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2a, 0x0a, 0x03, 0x61, 0x73, 0x6b, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x03, 0x61, - 0x73, 0x6b, 0x12, 0x29, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x26, 0x0a, - 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x65, 0x6e, - 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x52, 0x07, 0x74, 0x75, 0x72, - 0x6e, 0x45, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x48, - 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x2f, 0x0a, 0x08, 0x73, 0x75, 0x62, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x52, 0x08, 0x73, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x74, 0x65, - 0x61, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, - 0x2f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, - 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, - 0x12, 0x36, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x08, - 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, - 0x08, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x6d, 0x70, - 0x74, 0x12, 0x4b, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x11, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x2a, - 0x0a, 0x05, 0x73, 0x74, 0x65, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x45, - 0x63, 0x68, 0x6f, 0x52, 0x05, 0x73, 0x74, 0x65, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x74, - 0x65, 0x65, 0x72, 0x5f, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, - 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x52, 0x0c, 0x73, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, 0x74, - 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x72, 0x65, - 0x74, 0x72, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, 0x72, 0x79, - 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x15, 0x0a, 0x06, - 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, - 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x17, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x12, 0x48, 0x0a, 0x11, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, 0x69, - 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0f, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, - 0x68, 0x0a, 0x09, 0x53, 0x74, 0x65, 0x65, 0x72, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, + 0x76, 0x65, 0x6e, 0x74, 0x22, 0xb7, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x12, 0x2b, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x08, 0x53, 0x74, - 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x12, 0x31, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, - 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x8b, 0x01, 0x0a, 0x08, 0x41, 0x70, 0x70, - 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, - 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, - 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x77, - 0x61, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x22, 0x68, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, - 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, - 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, - 0x22, 0x4f, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, - 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x64, 0x22, 0xc4, 0x02, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, - 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x52, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1c, 0x0a, - 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x50, 0x68, 0x61, - 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, - 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, - 0x6e, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x0f, 0x53, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x23, 0x0a, 0x0d, - 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x72, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, - 0x70, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x65, 0x72, 0x72, 0x22, 0x7e, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x70, - 0x68, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x33, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, - 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, - 0x6c, 0x49, 0x64, 0x22, 0x9d, 0x04, 0x0a, 0x08, 0x53, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1d, 0x0a, - 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x05, - 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x61, 0x63, - 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, - 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x69, - 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x6e, 0x74, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x22, 0x3c, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x10, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, + 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x10, 0x01, 0x12, 0x0e, + 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x55, 0x44, 0x49, 0x4f, 0x10, 0x02, 0x22, 0xf3, + 0x03, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x30, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x75, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x75, 0x64, 0x69, + 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x61, 0x75, 0x64, 0x69, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x22, 0x9c, 0x01, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x14, + 0x0a, 0x10, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x45, 0x58, + 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4d, 0x41, 0x47, + 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x55, 0x44, 0x49, + 0x4f, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x53, 0x4f, + 0x55, 0x52, 0x43, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x4b, + 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4d, 0x42, 0x45, 0x44, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x55, 0x52, 0x45, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, + 0x4e, 0x54, 0x10, 0x06, 0x22, 0x34, 0x0a, 0x0a, 0x52, 0x65, 0x74, 0x72, 0x79, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x06, 0x50, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, + 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x0e, 0x52, + 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x1e, 0x0a, + 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x12, 0x34, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x56, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x70, + 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, + 0x64, 0x22, 0x30, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x65, + 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, + 0x6e, 0x49, 0x64, 0x22, 0x31, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x68, 0x69, + 0x6c, 0x64, 0x12, 0x22, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x65, 0x65, 0x72, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x65, 0x78, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x26, 0x0a, + 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x54, 0x0a, 0x0b, 0x53, 0x74, 0x65, 0x65, 0x72, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, + 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x26, + 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x32, + 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x22, 0x3b, 0x0a, 0x27, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, + 0xe8, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x44, 0x0a, 0x0f, + 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, + 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, + 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, + 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, 0x49, 0x0a, 0x1f, 0x52, 0x65, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, + 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xe7, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x44, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x41, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, + 0x48, 0x0a, 0x1e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, + 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x03, 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, + 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xab, 0x08, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x03, 0x73, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x75, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x30, 0x0a, + 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, + 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x12, + 0x36, 0x0a, 0x0b, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0a, 0x74, 0x6f, 0x6f, + 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2a, 0x0a, 0x03, 0x61, 0x73, 0x6b, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x52, 0x03, + 0x61, 0x73, 0x6b, 0x12, 0x29, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x26, + 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x65, + 0x6e, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x52, 0x07, 0x74, 0x75, + 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x2f, 0x0a, 0x08, 0x73, 0x75, + 0x62, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x52, 0x08, 0x73, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x74, + 0x65, 0x61, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x52, 0x08, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, + 0x6c, 0x12, 0x36, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, + 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, + 0x52, 0x08, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x6d, + 0x70, 0x74, 0x12, 0x4b, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x52, 0x11, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, + 0x2a, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, + 0x45, 0x63, 0x68, 0x6f, 0x52, 0x05, 0x73, 0x74, 0x65, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x0d, 0x73, + 0x74, 0x65, 0x65, 0x72, 0x5f, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x52, 0x0c, 0x73, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, + 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x72, + 0x65, 0x74, 0x72, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x15, 0x0a, + 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, + 0x75, 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x17, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x12, 0x48, 0x0a, 0x11, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, + 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, + 0x79, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0f, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x22, 0x68, 0x0a, 0x09, 0x53, 0x74, 0x65, 0x65, 0x72, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, + 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x08, 0x53, + 0x74, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x12, 0x31, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, + 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, + 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x8b, 0x01, 0x0a, 0x08, 0x41, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x63, + 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, + 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, + 0x77, 0x61, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x22, 0x68, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x50, + 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, + 0x72, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, + 0x63, 0x22, 0x4f, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x64, 0x22, 0xc4, 0x02, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, + 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, + 0x78, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x09, 0x74, 0x6f, 0x6f, + 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x52, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x50, 0x68, + 0x61, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x12, 0x2a, 0x0a, + 0x11, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, + 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x69, 0x6e, 0x67, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x0f, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x23, 0x0a, + 0x0d, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x69, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x72, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, + 0x6f, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x65, 0x72, 0x72, 0x22, 0x7e, 0x0a, 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, + 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x33, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x63, + 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, + 0x6c, 0x6c, 0x49, 0x64, 0x22, 0x9d, 0x04, 0x0a, 0x08, 0x53, 0x75, 0x62, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1d, + 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, + 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, + 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, + 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xf1, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, + 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6c, + 0x65, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x12, + 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, + 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, + 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x98, 0x05, 0x0a, 0x04, 0x54, 0x65, 0x61, + 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, + 0x12, 0x31, 0x0a, 0x06, 0x72, 0x6f, 0x73, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, + 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x06, 0x72, 0x6f, 0x73, + 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x69, + 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, - 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x12, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x22, 0xf1, 0x01, 0x0a, 0x0e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, - 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x65, - 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x12, 0x27, - 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x98, 0x05, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d, + 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x55, 0x73, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x29, 0x0a, 0x05, + 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, + 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x44, 0x0a, 0x0c, 0x64, + 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, + 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, + 0x75, 0x73, 0x65, 0x22, 0xd1, 0x05, 0x0a, 0x08, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, - 0x31, 0x0a, 0x06, 0x72, 0x6f, 0x73, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x52, 0x06, 0x72, 0x6f, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, - 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x74, 0x6f, 0x6f, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x73, 0x65, - 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x55, 0x73, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, - 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x29, 0x0a, 0x05, 0x74, - 0x61, 0x73, 0x6b, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, - 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x44, 0x0a, 0x0c, 0x64, 0x69, - 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, - 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, - 0x73, 0x65, 0x22, 0xd1, 0x05, 0x0a, 0x08, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x12, - 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, - 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x6f, 0x69, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x12, 0x21, 0x0a, - 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, - 0x6f, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x6f, 0x6f, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, - 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x0a, - 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x13, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x15, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x69, - 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4a, 0x04, 0x08, - 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x11, 0x10, 0x12, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x42, 0x0a, 0x08, 0x54, 0x6f, 0x6f, 0x6c, 0x43, 0x61, - 0x6c, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x0a, 0x54, - 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, 0x6c, - 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, - 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x75, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x64, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x66, 0x0a, 0x0d, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, - 0xce, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, - 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x4d, - 0x0a, 0x11, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, 0x79, 0x44, - 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x47, 0x0a, - 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, - 0x73, 0x48, 0x01, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, - 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x12, 0x0a, 0x10, - 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x52, 0x0a, 0x07, 0x54, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x12, 0x26, 0x0a, 0x05, 0x75, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, - 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x61, 0x64, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, - 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, - 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x0b, - 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x6f, + 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x12, 0x21, + 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, + 0x6f, 0x6f, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x74, 0x6f, 0x6f, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, + 0x6f, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, + 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, + 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x13, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x43, 0x61, 0x74, 0x65, 0x67, + 0x6f, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, + 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, + 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4a, 0x04, + 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, 0x11, 0x10, 0x12, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x10, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x42, 0x0a, 0x08, 0x54, 0x6f, 0x6f, 0x6c, 0x43, + 0x61, 0x6c, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x0a, + 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x61, + 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, + 0x6c, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, + 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x66, 0x0a, 0x0d, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x73, 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x73, 0x6b, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x6b, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x22, 0xce, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x74, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x12, + 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x74, 0x72, 0x79, + 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x47, + 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x48, 0x01, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x74, 0x72, + 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x12, 0x0a, + 0x10, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x22, 0x52, 0x0a, 0x07, 0x54, 0x75, 0x72, 0x6e, 0x45, 0x6e, 0x64, 0x12, 0x26, 0x0a, 0x05, + 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x63, 0x68, 0x65, + 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x61, 0x64, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x10, 0x63, 0x61, 0x63, 0x68, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0xd1, 0x01, 0x0a, + 0x0b, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, + 0x69, 0x7a, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, + 0x22, 0x31, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x76, 0x65, 0x72, 0x22, 0x50, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x13, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, + 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x1b, + 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, + 0x6c, 0x6f, 0x62, 0x22, 0x54, 0x0a, 0x16, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x19, + 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x55, 0x0a, 0x17, 0x52, 0x65, 0x61, + 0x64, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x22, 0x7b, 0x0a, 0x11, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x41, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, + 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, - 0x7a, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, - 0x31, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x22, 0x50, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, - 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, - 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x13, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x1b, 0x0a, - 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6c, - 0x6f, 0x62, 0x22, 0x54, 0x0a, 0x16, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x19, 0x0a, - 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x55, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x64, - 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x7b, 0x0a, 0x11, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x41, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0xab, 0x01, 0x0a, - 0x09, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, - 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, - 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, - 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2f, 0x0a, 0x15, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x48, 0x0a, 0x16, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x07, 0x70, 0x72, - 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x22, 0xde, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, - 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, - 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x41, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x41, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3a, 0x0a, 0x10, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, - 0x6d, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, - 0x78, 0x74, 0x22, 0x71, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x08, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x50, 0x72, - 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x69, 0x0a, 0x0d, 0x4d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x22, 0xb9, 0x01, 0x0a, 0x09, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x32, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0x17, 0x0a, 0x15, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2e, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, - 0x1b, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x1a, + 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0xab, 0x01, + 0x0a, 0x09, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x3a, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2f, 0x0a, 0x15, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x48, 0x0a, 0x16, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x07, 0x70, + 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x22, 0xde, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4d, 0x63, + 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x09, + 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, + 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x41, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3a, 0x0a, 0x10, 0x4d, 0x63, 0x70, 0x50, 0x72, + 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, + 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x22, 0x71, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, + 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, + 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x50, + 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x69, 0x0a, 0x0d, 0x4d, 0x63, 0x70, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, + 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x22, 0xb9, 0x01, 0x0a, 0x09, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x32, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x63, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0x17, 0x0a, + 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9c, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x69, + 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x63, + 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0x42, 0x0a, 0x18, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x51, 0x0a, 0x19, 0x52, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x22, 0xac, 0x01, 0x0a, 0x09, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, - 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6f, - 0x6c, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, - 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3f, 0x0a, 0x07, 0x43, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3d, 0x0a, 0x13, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a, 0x1a, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, + 0xac, 0x01, 0x0a, 0x09, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6f, + 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x12, + 0x27, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x13, + 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x06, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3f, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3d, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x46, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2e, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, + 0x98, 0x01, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x72, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x62, 0x61, 0x72, 0x65, 0x22, 0x3e, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x46, 0x0a, 0x14, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, - 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x1a, 0x0a, - 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x72, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x62, 0x61, 0x72, 0x65, 0x22, 0x3e, 0x0a, - 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x4a, 0x0a, - 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, - 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x52, 0x09, - 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x09, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, - 0x0b, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x12, 0x1f, - 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, - 0x25, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x22, - 0xe4, 0x01, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, - 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x76, - 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x64, 0x72, 0x69, 0x66, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, - 0x72, 0x69, 0x66, 0x74, 0x65, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, - 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, - 0x6f, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x73, - 0x6f, 0x75, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, - 0x73, 0x6f, 0x75, 0x6c, 0x22, 0x44, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, - 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x15, 0x4c, 0x69, + 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x52, 0x09, 0x77, 0x6f, 0x72, + 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x09, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x13, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x22, 0xfe, 0x02, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, - 0x6c, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, - 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, - 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 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, - 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, - 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x69, 0x64, 0x22, 0xae, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, - 0x65, 0x6c, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x12, 0x36, 0x0a, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x68, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, - 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, + 0x0a, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x22, 0xe4, 0x01, 0x0a, + 0x08, 0x53, 0x6f, 0x75, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x32, 0x0a, 0x06, 0x64, 0x65, - 0x74, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0xb8, - 0x01, 0x0a, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, - 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xef, - 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x1b, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x61, 0x75, - 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x41, - 0x75, 0x74, 0x6f, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, - 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x22, 0x86, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4c, 0x0a, 0x15, 0x52, 0x65, 0x66, - 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x72, 0x65, + 0x73, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, + 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, + 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x72, 0x69, + 0x66, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x72, 0x69, 0x66, + 0x74, 0x65, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x73, 0x6f, 0x75, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x75, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x73, 0x6f, 0x75, + 0x6c, 0x22, 0x44, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x22, 0xfe, 0x02, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x72, + 0x69, 0x67, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2c, + 0x0a, 0x12, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, + 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 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, 0x09, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x52, 0x0f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x52, 0x11, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, + 0x64, 0x22, 0xae, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x44, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, + 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, + 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x68, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, + 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x65, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, + 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x32, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0xb8, 0x01, 0x0a, 0x09, + 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, + 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, + 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, + 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xef, 0x01, 0x0a, 0x0e, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x1b, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x86, 0x01, + 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4c, 0x0a, 0x15, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x05, 0x61, + 0x73, 0x79, 0x6e, 0x63, 0x22, 0x96, 0x02, 0x0a, 0x11, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x62, 0x73, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x62, + 0x73, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x67, 0x65, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x67, 0x65, 0x64, 0x12, + 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x50, 0x0a, + 0x16, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22, + 0x8b, 0x04, 0x0a, 0x0f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x21, 0x0a, + 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x61, 0x74, + 0x74, 0x65, 0x6d, 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x10, 0x63, 0x6c, + 0x61, 0x69, 0x6d, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x08, + 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, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, + 0x12, 0x29, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0c, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x0d, 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, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x34, 0x0a, + 0x19, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, - 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x22, 0x96, 0x02, 0x0a, 0x11, 0x52, 0x65, 0x66, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, - 0x61, 0x62, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x61, 0x62, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x67, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x67, - 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x64, 0x12, 0x1e, - 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x50, 0x0a, 0x16, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x70, 0x74, 0x22, 0x8b, 0x04, 0x0a, 0x0f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, - 0x6f, 0x64, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x5f, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x11, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6c, - 0x61, 0x69, 0x6d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, - 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, - 0x74, 0x18, 0x08, 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, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x73, 0x41, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x12, - 0x19, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0c, 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, 0x09, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x0d, 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, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x22, 0x34, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, - 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x52, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x22, 0x61, 0x0a, 0x1b, 0x4c, 0x69, + 0x02, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x34, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x07, + 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x22, 0x61, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, + 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x77, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x61, 0x74, + 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, + 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, + 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, + 0x73, 0x6f, 0x72, 0x22, 0x6b, 0x0a, 0x1c, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x10, + 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x55, 0x0a, 0x1d, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x34, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x07, + 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x22, 0x7e, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x77, 0x0a, - 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, - 0x65, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, - 0x08, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x08, 0x61, 0x74, 0x74, - 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, - 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, - 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x6b, 0x0a, 0x1c, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x9b, 0x02, 0x0a, 0x13, 0x4c, 0x65, 0x61, 0x72, + 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x66, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, + 0x0a, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x71, 0x12, + 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x22, 0x80, 0x01, 0x0a, 0x10, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x02, + 0x61, 0x74, 0x18, 0x04, 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, 0x02, 0x61, 0x74, 0x22, 0xb4, 0x01, 0x0a, 0x18, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0xec, 0x05, 0x0a, 0x10, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3a, + 0x0a, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x66, + 0x52, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x65, + 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x41, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6d, 0x6f, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x0e, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 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, + 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, + 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, + 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x5f, + 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x22, 0x7b, + 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x4f, 0x0a, 0x1a, 0x47, + 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, + 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x56, 0x0a, 0x1b, + 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x32, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x1d, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, - 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, - 0x74, 0x52, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x22, 0x7e, 0x0a, 0x1c, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x9b, 0x02, 0x0a, 0x13, 0x4c, - 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x66, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6f, - 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6f, 0x72, - 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x65, 0x71, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x6f, 0x6c, 0x43, 0x61, - 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, - 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x22, 0x80, 0x01, 0x0a, 0x10, 0x4c, 0x65, 0x61, - 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, - 0x2a, 0x0a, 0x02, 0x61, 0x74, 0x18, 0x04, 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, 0x02, 0x61, 0x74, 0x22, 0xb4, 0x01, 0x0a, 0x18, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, - 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, - 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, - 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0xec, 0x05, 0x0a, 0x10, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, - 0x52, 0x65, 0x66, 0x52, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x64, 0x65, 0x63, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, - 0x67, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x65, 0x63, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, - 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x09, 0x70, 0x72, - 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x0f, 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, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x25, 0x0a, - 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x18, - 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x63, - 0x6f, 0x70, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x70, 0x72, 0x6f, - 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x65, 0x61, 0x72, 0x6e, - 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, - 0x64, 0x22, 0x7b, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, - 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x4f, - 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, - 0x56, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, + 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x59, 0x0a, 0x1e, 0x44, 0x65, + 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, + 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x85, 0x01, 0x0a, 0x1c, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, + 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x32, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x58, 0x0a, + 0x1d, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, + 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x63, 0x69, - 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x32, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x59, 0x0a, - 0x1e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x37, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, - 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x85, 0x01, 0x0a, 0x1c, 0x55, 0x6e, 0x64, - 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x32, 0x0a, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x22, 0x58, 0x0a, 0x1d, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, - 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0xa2, 0x05, 0x0a, 0x13, 0x4c, - 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x70, - 0x65, 0x72, 0x73, 0x65, 0x64, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, - 0x75, 0x70, 0x65, 0x72, 0x73, 0x65, 0x64, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x76, 0x69, - 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0d, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x66, 0x52, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x0b, - 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x08, 0x72, 0x65, 0x63, - 0x65, 0x69, 0x70, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0xa2, 0x05, 0x0a, 0x13, 0x4c, 0x65, 0x61, 0x72, + 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, + 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x70, 0x65, 0x72, 0x73, + 0x65, 0x64, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x70, 0x65, + 0x72, 0x73, 0x65, 0x64, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, + 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, + 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x0a, + 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, + 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x66, 0x52, + 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x65, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x65, 0x76, 0x61, 0x6c, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x70, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, + 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x0e, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, + 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 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, 0x09, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x64, 0x6f, 0x5f, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, + 0x6e, 0x64, 0x6f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xca, 0x01, 0x0a, + 0x0f, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, + 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, + 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, + 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x61, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x65, 0x61, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, + 0x02, 0x61, 0x74, 0x18, 0x06, 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, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, - 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, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x64, 0x6f, - 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x75, 0x6e, 0x64, 0x6f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, - 0xca, 0x01, 0x0a, 0x0f, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x49, 0x64, 0x73, 0x12, 0x1a, - 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, - 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, - 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x12, 0x2a, 0x0a, 0x02, 0x61, 0x74, 0x18, 0x06, 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, 0x02, 0x61, 0x74, 0x22, 0xc0, 0x04, 0x0a, - 0x12, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, - 0x69, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, - 0x6f, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x66, 0x72, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x65, 0x76, - 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, - 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, - 0x6f, 0x6f, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x64, 0x69, 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x64, 0x69, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x78, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, - 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x2a, 0x0a, 0x02, 0x61, 0x74, 0x18, 0x0f, 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, 0x02, 0x61, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, - 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x64, 0x6f, - 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x75, 0x6e, 0x64, 0x6f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, - 0x99, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, - 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x22, 0xae, 0x01, 0x0a, 0x19, - 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x73, 0x6b, 0x69, - 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, - 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x8f, 0x01, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x89, - 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x73, 0x6b, - 0x69, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, - 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xd2, 0x01, 0x0a, 0x1f, 0x44, - 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, - 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x0c, 0x66, - 0x72, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0a, 0x74, 0x6f, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xcd, 0x01, 0x0a, 0x20, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x69, 0x66, 0x66, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x64, 0x69, 0x66, 0x66, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, - 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xd1, 0x01, 0x0a, 0x19, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, - 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, - 0x11, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x61, 0x74, 0x22, 0xc0, 0x04, 0x0a, 0x12, 0x53, 0x6b, + 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x72, 0x6f, + 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x65, 0x76, 0x69, 0x64, 0x65, + 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x6f, 0x6f, 0x6c, + 0x43, 0x61, 0x6c, 0x6c, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, + 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x64, 0x69, 0x63, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x49, + 0x64, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x74, 0x72, 0x65, 0x61, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x02, + 0x61, 0x74, 0x18, 0x0f, 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, 0x02, 0x61, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x64, 0x6f, 0x5f, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, + 0x6e, 0x64, 0x6f, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x99, 0x01, 0x0a, + 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x22, 0xae, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, + 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, + 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x16, 0x47, 0x65, + 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, + 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x89, 0x01, 0x0a, 0x17, + 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, + 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, + 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xd2, 0x01, 0x0a, 0x1f, 0x44, 0x69, 0x66, 0x66, + 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, + 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x0c, 0x66, 0x72, 0x6f, 0x6d, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0a, 0x74, 0x6f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0xe8, 0x01, 0x0a, 0x1a, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, - 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, - 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, + 0x01, 0x52, 0x09, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xcd, 0x01, 0x0a, + 0x20, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x69, 0x66, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x64, 0x69, 0x66, 0x66, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, + 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, + 0x0a, 0x74, 0x6f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x74, 0x6f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xd1, 0x01, 0x0a, + 0x19, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, + 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x17, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x11, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x10, + 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0xe8, 0x01, 0x0a, 0x1a, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, + 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x34, 0x0a, 0x05, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x72, 0x6e, + 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x05, + 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x2d, 0x0a, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xe0, 0x01, 0x0a, 0x1b, + 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, + 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2e, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x11, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x10, 0x65, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x61, + 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x22, 0xae, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, + 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xe0, - 0x01, 0x0a, 0x1b, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x0b, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, - 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2e, 0x0a, 0x0e, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0d, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x11, 0x65, - 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x10, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0x61, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, - 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x22, 0xae, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, - 0x74, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x22, 0xbe, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x70, 0x65, - 0x63, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, - 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x26, - 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x65, 0x61, 0x6d, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0x5e, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, - 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, - 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x0c, 0x54, 0x65, 0x61, 0x6d, 0x6d, - 0x61, 0x74, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, - 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0xcb, 0x01, 0x0a, 0x14, 0x53, - 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, - 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x04, 0x6c, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, - 0x6d, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0x46, 0x0a, 0x15, 0x53, 0x70, 0x61, 0x77, - 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, - 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x22, 0x88, 0x01, 0x0a, 0x1a, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x22, 0xbe, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x07, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x6d, + 0x61, 0x78, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x22, 0x5e, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x65, 0x61, + 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, + 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x0c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, + 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, + 0x6c, 0x65, 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6d, + 0x70, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0xcb, 0x01, 0x0a, 0x14, 0x53, 0x70, 0x61, 0x77, + 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1d, 0x0a, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6c, 0x65, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6c, 0x65, + 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x25, + 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, + 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0x46, 0x0a, 0x15, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, + 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x88, 0x01, + 0x0a, 0x1a, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, + 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x1b, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x1d, 0x0a, 0x1b, 0x53, 0x65, 0x6e, 0x64, + 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x22, 0x18, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, + 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x32, 0x0a, + 0x0e, 0x52, 0x75, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, - 0x64, 0x12, 0x17, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, - 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x1b, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x1d, 0x0a, 0x1b, 0x53, - 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x0a, 0x15, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, - 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x18, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x32, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, - 0x61, 0x6d, 0x49, 0x64, 0x22, 0x7d, 0x0a, 0x09, 0x54, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x30, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x65, 0x61, 0x6d, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, - 0x6f, 0x6d, 0x65, 0x22, 0xa4, 0x02, 0x0a, 0x0b, 0x54, 0x65, 0x61, 0x6d, 0x4f, 0x75, 0x74, 0x63, - 0x6f, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x71, - 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x75, 0x64, - 0x67, 0x65, 0x74, 0x5f, 0x65, 0x78, 0x68, 0x61, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x45, 0x78, 0x68, 0x61, 0x75, - 0x73, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x44, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x69, 0x73, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x33, 0x0a, 0x0f, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, - 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, - 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x22, - 0x8c, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, - 0x12, 0x1c, 0x0a, 0x09, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x09, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x22, 0x74, - 0x0a, 0x0a, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, - 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x39, 0x0a, 0x0b, 0x54, 0x65, 0x61, - 0x6d, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x22, 0xa1, 0x01, 0x0a, 0x15, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x36, 0x0a, 0x12, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, - 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, - 0x22, 0x15, 0x0a, 0x13, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, - 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x22, 0xa3, 0x01, 0x0a, 0x17, 0x4d, 0x61, 0x6e, 0x75, 0x61, - 0x6c, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x3f, 0x0a, 0x0a, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, - 0x6d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x7a, 0x0a, 0x15, - 0x44, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x06, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x4b, 0x0a, 0x19, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x50, - 0x6c, 0x61, 0x6e, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x4d, 0x0a, 0x16, 0x44, 0x65, 0x63, - 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, - 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, 0x17, 0x44, 0x65, 0x63, 0x69, - 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x07, 0x72, - 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22, 0x99, 0x02, 0x0a, 0x0f, 0x44, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, - 0x18, 0x03, 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, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x36, 0x0a, - 0x17, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, - 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, - 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x12, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x0e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x75, 0x72, - 0x76, 0x69, 0x76, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x75, 0x72, 0x76, 0x69, 0x76, - 0x6f, 0x72, 0x12, 0x35, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, - 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x65, 0x70, - 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x72, 0x65, 0x70, - 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x61, 0x63, 0x74, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x16, 0x65, 0x78, 0x61, 0x63, 0x74, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x5c, 0x0a, 0x10, 0x44, 0x72, - 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4a, 0x0a, 0x10, 0x44, 0x72, 0x65, 0x61, - 0x6d, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd6, 0x02, 0x0a, 0x0c, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, - 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x30, 0x0a, 0x14, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x70, - 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x30, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x12, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, - 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x73, - 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x70, - 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, - 0x13, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x66, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3f, 0x0a, - 0x15, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x36, - 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x65, 0x64, 0x22, 0x42, 0x0a, 0x21, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x21, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x22, 0xaa, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x64, 0x22, 0x7d, 0x0a, 0x09, 0x54, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x30, + 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, + 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, + 0x22, 0xa4, 0x02, 0x0a, 0x0b, 0x54, 0x65, 0x61, 0x6d, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x71, 0x75, 0x69, 0x65, + 0x73, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x71, 0x75, 0x69, + 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, + 0x5f, 0x65, 0x78, 0x68, 0x61, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x45, 0x78, 0x68, 0x61, 0x75, 0x73, 0x74, 0x65, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x73, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x44, 0x0a, + 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, + 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x33, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, 0x65, + 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, + 0x10, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x12, 0x29, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, + 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x71, 0x75, 0x69, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x22, 0x74, 0x0a, 0x0a, 0x54, + 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x39, 0x0a, 0x0b, 0x54, 0x65, 0x61, 0x6d, 0x46, 0x69, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x22, 0xa1, 0x01, 0x0a, 0x15, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x36, 0x0a, 0x12, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, + 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x74, + 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x22, 0x15, 0x0a, + 0x13, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, + 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x6f, 0x74, 0x65, 0x22, 0xa3, 0x01, 0x0a, 0x17, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x44, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, + 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, + 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x3f, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x09, + 0x75, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x7a, 0x0a, 0x15, 0x44, 0x72, 0x65, + 0x61, 0x6d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x4b, 0x0a, 0x19, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x50, 0x6c, 0x61, 0x6e, + 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x4d, 0x0a, 0x16, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, + 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x63, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, 0x17, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x44, + 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x07, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x70, 0x74, 0x22, 0x99, 0x02, 0x0a, 0x0f, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x03, 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, + 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x6c, + 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x70, 0x6c, 0x61, + 0x6e, 0x6e, 0x65, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x12, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0xa5, 0x02, 0x0a, 0x0e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x75, 0x72, 0x76, 0x69, 0x76, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, + 0x69, 0x70, 0x61, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x75, 0x72, 0x76, 0x69, 0x76, 0x6f, 0x72, 0x12, + 0x35, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, + 0x61, 0x6d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x70, + 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, + 0x18, 0x65, 0x78, 0x61, 0x63, 0x74, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x5f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x16, 0x65, 0x78, 0x61, 0x63, 0x74, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, + 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x5c, 0x0a, 0x10, 0x44, 0x72, 0x65, 0x61, 0x6d, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4a, 0x0a, 0x10, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0xd6, 0x02, 0x0a, 0x0c, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x63, 0x65, 0x69, + 0x70, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, + 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, + 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x70, 0x6c, 0x61, 0x6e, + 0x6e, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, + 0x0a, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x70, + 0x70, 0x6c, 0x69, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x36, 0x0a, 0x17, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x6b, 0x69, 0x70, + 0x70, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3f, 0x0a, 0x15, 0x43, 0x6f, + 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x36, 0x0a, 0x16, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, + 0x74, 0x65, 0x64, 0x22, 0x42, 0x0a, 0x21, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x21, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x65, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, - 0x2a, 0x8a, 0x01, 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, - 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, - 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, - 0x01, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, - 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x50, - 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, - 0x43, 0x43, 0x45, 0x50, 0x54, 0x5f, 0x45, 0x44, 0x49, 0x54, 0x53, 0x10, 0x03, 0x2a, 0x92, 0x01, - 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x56, 0x65, 0x72, 0x64, 0x69, 0x63, - 0x74, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, - 0x52, 0x44, 0x49, 0x43, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, - 0x56, 0x45, 0x52, 0x44, 0x49, 0x43, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x01, 0x12, 0x1f, - 0x0a, 0x1b, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x44, 0x49, - 0x43, 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x02, 0x12, - 0x21, 0x0a, 0x1d, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x44, - 0x49, 0x43, 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x41, 0x4c, 0x57, 0x41, 0x59, 0x53, - 0x10, 0x03, 0x2a, 0xbe, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x63, - 0x6f, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, - 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, - 0x4f, 0x4d, 0x45, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1a, - 0x0a, 0x16, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, - 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, - 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, - 0x41, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x45, 0x45, 0x52, - 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x5f, 0x50, 0x45, - 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x45, 0x45, 0x52, - 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x41, 0x54, - 0x45, 0x10, 0x05, 0x2a, 0x98, 0x01, 0x0a, 0x0c, 0x48, 0x6f, 0x6f, 0x6b, 0x44, 0x65, 0x63, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, - 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, - 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, - 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, - 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, - 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x04, 0x2a, 0x96, - 0x01, 0x0a, 0x10, 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, 0x49, 0x53, - 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, - 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x59, - 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, - 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x4d, - 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x2a, 0xa8, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, - 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x54, 0x52, 0x45, - 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x43, - 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x52, 0x45, 0x41, - 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, - 0x4c, 0x45, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, - 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, - 0x10, 0x04, 0x2a, 0x84, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x76, 0x65, - 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, - 0x4f, 0x56, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, - 0x52, 0x4f, 0x56, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, - 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x4e, 0x41, - 0x4e, 0x43, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, - 0x5f, 0x44, 0x52, 0x49, 0x56, 0x45, 0x52, 0x10, 0x03, 0x2a, 0xad, 0x01, 0x0a, 0x14, 0x54, 0x65, - 0x61, 0x6d, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x23, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, - 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x54, + 0x22, 0xaa, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x2a, 0x8a, 0x01, + 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, + 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, + 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x01, 0x12, 0x18, + 0x0a, 0x14, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, + 0x45, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x45, 0x52, 0x4d, + 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x43, 0x43, 0x45, + 0x50, 0x54, 0x5f, 0x45, 0x44, 0x49, 0x54, 0x53, 0x10, 0x03, 0x2a, 0x92, 0x01, 0x0a, 0x0f, 0x41, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x56, 0x65, 0x72, 0x64, 0x69, 0x63, 0x74, 0x12, 0x20, + 0x0a, 0x1c, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x44, 0x49, + 0x43, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x19, 0x0a, 0x15, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, + 0x44, 0x49, 0x43, 0x54, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x41, + 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x44, 0x49, 0x43, 0x54, 0x5f, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, + 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, 0x41, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x44, 0x49, 0x43, 0x54, + 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x5f, 0x41, 0x4c, 0x57, 0x41, 0x59, 0x53, 0x10, 0x03, 0x2a, + 0xbe, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x65, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, + 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, + 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x53, + 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x41, 0x50, 0x50, + 0x45, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x45, 0x45, 0x52, + 0x5f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x41, 0x43, 0x54, + 0x45, 0x44, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, + 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, + 0x4e, 0x47, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x45, 0x45, 0x52, 0x5f, 0x4f, 0x55, + 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x05, + 0x2a, 0x98, 0x01, 0x0a, 0x0c, 0x48, 0x6f, 0x6f, 0x6b, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x16, 0x0a, 0x12, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, + 0x4e, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x4f, 0x4f, 0x4b, + 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, + 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x03, 0x12, + 0x1a, 0x0a, 0x16, 0x48, 0x4f, 0x4f, 0x4b, 0x5f, 0x44, 0x45, 0x43, 0x49, 0x53, 0x49, 0x4f, 0x4e, + 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x04, 0x2a, 0x96, 0x01, 0x0a, 0x10, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x50, 0x4f, 0x53, + 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, 0x49, 0x53, + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x50, + 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x59, 0x41, 0x42, 0x4c, + 0x45, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x54, 0x52, 0x59, 0x5f, 0x44, 0x49, 0x53, + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, + 0x4e, 0x54, 0x10, 0x03, 0x2a, 0xa8, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x54, 0x52, 0x45, 0x41, + 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x52, 0x45, + 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, + 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, + 0x49, 0x54, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, + 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x49, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, + 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x50, 0x52, 0x4f, 0x47, + 0x52, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x04, 0x2a, + 0x84, 0x01, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x6c, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, + 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, + 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1b, 0x0a, + 0x17, 0x53, 0x4f, 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, + 0x5f, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, + 0x55, 0x4c, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x44, 0x52, + 0x49, 0x56, 0x45, 0x52, 0x10, 0x03, 0x2a, 0xad, 0x01, 0x0a, 0x14, 0x54, 0x65, 0x61, 0x6d, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, + 0x27, 0x0a, 0x23, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x53, + 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x54, 0x45, 0x41, 0x4d, + 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, + 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x25, - 0x0a, 0x21, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x53, 0x54, - 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, - 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, - 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, - 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x10, 0x03, 0x32, 0xa1, 0x35, 0x0a, 0x0e, 0x48, 0x61, - 0x72, 0x6e, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x14, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, + 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, + 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, + 0x44, 0x47, 0x45, 0x54, 0x10, 0x03, 0x32, 0x81, 0x36, 0x0a, 0x0e, 0x48, 0x61, 0x72, 0x6e, 0x65, + 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x26, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, + 0x0a, 0x07, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4f, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, - 0x0a, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x40, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, - 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, - 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x47, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x12, 0x1a, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x10, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, - 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x61, 0x64, - 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4d, - 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, - 0x6d, 0x70, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x47, 0x65, 0x74, - 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, - 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4f, 0x0a, 0x0c, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, + 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, + 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, + 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x47, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x73, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2a, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, - 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x24, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, - 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x11, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, - 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x63, 0x0a, 0x12, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, - 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x88, - 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x63, 0x70, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, + 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, + 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x63, 0x70, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, + 0x0a, 0x11, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x63, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x63, 0x70, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, + 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, 0x70, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x63, + 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, + 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, + 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x6f, 0x6f, 0x6c, 0x48, 0x69, 0x76, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, + 0x65, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x74, 0x72, 0x65, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x4c, 0x0a, 0x11, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x23, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x63, 0x0a, 0x12, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x24, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x88, 0x01, 0x0a, 0x1f, + 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x31, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x17, 0x52, 0x65, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, - 0x71, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x17, 0x52, 0x65, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x4f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5f, 0x0a, 0x14, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, - 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x4d, 0x63, 0x70, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, + 0x4f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x5b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, + 0x14, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x60, + 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61, - 0x6e, 0x12, 0x60, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4a, 0x6f, 0x62, 0x12, 0x62, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x62, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, + 0x12, 0x62, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x62, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, - 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x62, 0x0a, 0x16, 0x47, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x62, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, + 0x6f, 0x62, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, - 0x61, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, - 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x53, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x55, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, - 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x55, - 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, - 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, - 0x61, 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, - 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x40, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, - 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x47, 0x65, - 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, - 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, - 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, - 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, - 0x65, 0x6d, 0x70, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, - 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, - 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x14, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4c, - 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x27, - 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, - 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, - 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6b, 0x0a, 0x16, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x4c, 0x65, 0x61, 0x72, + 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x61, 0x0a, 0x12, + 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, + 0x75, 0x70, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x53, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x55, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x26, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x4a, 0x6f, 0x62, 0x12, 0x55, 0x0a, 0x14, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, + 0x4a, 0x6f, 0x62, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, + 0x70, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x4a, + 0x6f, 0x62, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, + 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, + 0x07, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4f, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4c, 0x65, + 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x24, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, + 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, + 0x74, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, + 0x70, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, + 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x14, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, - 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, - 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, - 0x6c, 0x61, 0x6e, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, - 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, - 0x0a, 0x0f, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, - 0x6e, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x63, 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x73, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x25, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x16, 0x44, 0x65, - 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, + 0x0a, 0x16, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, + 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, + 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, + 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x11, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, + 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, + 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x44, + 0x65, 0x63, 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x69, 0x64, + 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x63, 0x69, 0x64, 0x65, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x12, 0x27, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x64, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, + 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x16, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x15, 0x55, 0x6e, 0x64, - 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x6e, 0x64, 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, - 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6d, 0x65, + 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x4c, 0x65, + 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x15, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, + 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x27, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x6f, + 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, + 0x67, 0x50, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, + 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x12, 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, + 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, - 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x73, 0x0a, 0x18, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x18, + 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x69, 0x66, 0x66, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x63, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, + 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, + 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, + 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, - 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x12, 0x52, 0x65, 0x6a, - 0x65, 0x63, 0x74, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, - 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, - 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, - 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, - 0x69, 0x6c, 0x6c, 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, - 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, - 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x65, 0x0a, 0x14, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, 0x72, - 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, - 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x41, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, + 0x12, 0x24, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, - 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x23, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, - 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x49, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x1c, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, - 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x53, 0x70, - 0x61, 0x77, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, 0x61, - 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, - 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, - 0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, - 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, - 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x52, - 0x75, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, - 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x08, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, - 0x0a, 0x0b, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, - 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, - 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, - 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x6d, 0x65, - 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x50, - 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x68, - 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, - 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x68, 0x0a, 0x18, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x69, 0x0a, 0x19, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x57, 0x6f, 0x72, 0x6b, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, + 0x14, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, + 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, + 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x65, + 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, + 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6b, 0x69, + 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x12, + 0x1c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, + 0x64, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x53, 0x70, 0x61, 0x77, 0x6e, + 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x77, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x6d, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x13, 0x53, + 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, + 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x55, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, + 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x6d, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x54, + 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x75, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x43, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, + 0x61, 0x6d, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, + 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x43, + 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, + 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x54, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x41, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x50, 0x6c, 0x61, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x18, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x68, 0x0a, 0x18, 0x52, 0x65, 0x74, 0x72, 0x79, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x2c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x2c, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0xa2, 0x01, - 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x42, - 0x0c, 0x48, 0x61, 0x72, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x61, 0x63, - 0x6b, 0x6c, 0x6f, 0x6b, 0x2f, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x63, - 0x61, 0x74, 0x6c, 0x2f, 0x76, 0x31, 0x3b, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x76, 0x31, 0xa2, - 0x02, 0x03, 0x4d, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x56, - 0x31, 0xca, 0x02, 0x09, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x15, - 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x3a, 0x3a, - 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x0a, 0x19, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x2e, 0x6d, + 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0xa2, 0x01, 0x0a, 0x0d, 0x63, + 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x48, 0x61, + 0x72, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x6c, 0x6f, + 0x6b, 0x2f, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x73, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, + 0x2f, 0x76, 0x31, 0x3b, 0x6d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, + 0x58, 0x58, 0xaa, 0x02, 0x09, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x09, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x15, 0x4d, 0x65, 0x63, + 0x61, 0x74, 0x6c, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x0a, 0x4d, 0x65, 0x63, 0x61, 0x74, 0x6c, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -20528,7 +20687,7 @@ func file_mecatl_v1_harness_proto_rawDescGZIP() []byte { } var file_mecatl_v1_harness_proto_enumTypes = make([]protoimpl.EnumInfo, 10) -var file_mecatl_v1_harness_proto_msgTypes = make([]protoimpl.MessageInfo, 229) +var file_mecatl_v1_harness_proto_msgTypes = make([]protoimpl.MessageInfo, 231) var file_mecatl_v1_harness_proto_goTypes = []any{ (PermissionMode)(0), // 0: mecatl.v1.PermissionMode (ApprovalVerdict)(0), // 1: mecatl.v1.ApprovalVerdict @@ -20662,122 +20821,124 @@ var file_mecatl_v1_harness_proto_goTypes = []any{ (*McpSource)(nil), // 129: mecatl.v1.McpSource (*ListMcpSourcesRequest)(nil), // 130: mecatl.v1.ListMcpSourcesRequest (*ListMcpSourcesResponse)(nil), // 131: mecatl.v1.ListMcpSourcesResponse - (*ListToolHiveGroupsRequest)(nil), // 132: mecatl.v1.ListToolHiveGroupsRequest - (*ListToolHiveGroupsResponse)(nil), // 133: mecatl.v1.ListToolHiveGroupsResponse - (*AgentInfo)(nil), // 134: mecatl.v1.AgentInfo - (*ListAgentsRequest)(nil), // 135: mecatl.v1.ListAgentsRequest - (*ListAgentsResponse)(nil), // 136: mecatl.v1.ListAgentsResponse - (*Command)(nil), // 137: mecatl.v1.Command - (*ListCommandsRequest)(nil), // 138: mecatl.v1.ListCommandsRequest - (*ListCommandsResponse)(nil), // 139: mecatl.v1.ListCommandsResponse - (*Worktree)(nil), // 140: mecatl.v1.Worktree - (*ListWorktreesRequest)(nil), // 141: mecatl.v1.ListWorktreesRequest - (*ListWorktreesResponse)(nil), // 142: mecatl.v1.ListWorktreesResponse - (*SkillInfo)(nil), // 143: mecatl.v1.SkillInfo - (*ListSkillsRequest)(nil), // 144: mecatl.v1.ListSkillsRequest - (*ListSkillsResponse)(nil), // 145: mecatl.v1.ListSkillsResponse - (*SoulInfo)(nil), // 146: mecatl.v1.SoulInfo - (*GetSoulRequest)(nil), // 147: mecatl.v1.GetSoulRequest - (*GetSoulResponse)(nil), // 148: mecatl.v1.GetSoulResponse - (*UserModelEntry)(nil), // 149: mecatl.v1.UserModelEntry - (*GetUserModelRequest)(nil), // 150: mecatl.v1.GetUserModelRequest - (*UserModelRevision)(nil), // 151: mecatl.v1.UserModelRevision - (*UserModelDetail)(nil), // 152: mecatl.v1.UserModelDetail - (*GetUserModelResponse)(nil), // 153: mecatl.v1.GetUserModelResponse - (*ModelInfo)(nil), // 154: mecatl.v1.ModelInfo - (*ListModelsRequest)(nil), // 155: mecatl.v1.ListModelsRequest - (*ProviderStatus)(nil), // 156: mecatl.v1.ProviderStatus - (*ListModelsResponse)(nil), // 157: mecatl.v1.ListModelsResponse - (*ReflectSessionRequest)(nil), // 158: mecatl.v1.ReflectSessionRequest - (*ReflectionReceipt)(nil), // 159: mecatl.v1.ReflectionReceipt - (*ReflectSessionResponse)(nil), // 160: mecatl.v1.ReflectSessionResponse - (*LearningAttempt)(nil), // 161: mecatl.v1.LearningAttempt - (*GetLearningAttemptRequest)(nil), // 162: mecatl.v1.GetLearningAttemptRequest - (*GetLearningAttemptResponse)(nil), // 163: mecatl.v1.GetLearningAttemptResponse - (*ListLearningAttemptsRequest)(nil), // 164: mecatl.v1.ListLearningAttemptsRequest - (*ListLearningAttemptsResponse)(nil), // 165: mecatl.v1.ListLearningAttemptsResponse - (*MutateLearningAttemptRequest)(nil), // 166: mecatl.v1.MutateLearningAttemptRequest - (*MutateLearningAttemptResponse)(nil), // 167: mecatl.v1.MutateLearningAttemptResponse - (*ListLearningProposalsRequest)(nil), // 168: mecatl.v1.ListLearningProposalsRequest - (*LearningEvidenceRef)(nil), // 169: mecatl.v1.LearningEvidenceRef - (*LearningDecision)(nil), // 170: mecatl.v1.LearningDecision - (*LearningPromotionReceipt)(nil), // 171: mecatl.v1.LearningPromotionReceipt - (*LearningProposal)(nil), // 172: mecatl.v1.LearningProposal - (*ListLearningProposalsResponse)(nil), // 173: mecatl.v1.ListLearningProposalsResponse - (*GetLearningProposalRequest)(nil), // 174: mecatl.v1.GetLearningProposalRequest - (*GetLearningProposalResponse)(nil), // 175: mecatl.v1.GetLearningProposalResponse - (*DecideLearningProposalRequest)(nil), // 176: mecatl.v1.DecideLearningProposalRequest - (*DecideLearningProposalResponse)(nil), // 177: mecatl.v1.DecideLearningProposalResponse - (*UndoLearningPromotionRequest)(nil), // 178: mecatl.v1.UndoLearningPromotionRequest - (*UndoLearningPromotionResponse)(nil), // 179: mecatl.v1.UndoLearningPromotionResponse - (*LearnedSkillVersion)(nil), // 180: mecatl.v1.LearnedSkillVersion - (*SkillEvaluation)(nil), // 181: mecatl.v1.SkillEvaluation - (*SkillChangeReceipt)(nil), // 182: mecatl.v1.SkillChangeReceipt - (*ListLearnedSkillsRequest)(nil), // 183: mecatl.v1.ListLearnedSkillsRequest - (*ListLearnedSkillsResponse)(nil), // 184: mecatl.v1.ListLearnedSkillsResponse - (*GetLearnedSkillRequest)(nil), // 185: mecatl.v1.GetLearnedSkillRequest - (*GetLearnedSkillResponse)(nil), // 186: mecatl.v1.GetLearnedSkillResponse - (*DiffLearnedSkillVersionsRequest)(nil), // 187: mecatl.v1.DiffLearnedSkillVersionsRequest - (*DiffLearnedSkillVersionsResponse)(nil), // 188: mecatl.v1.DiffLearnedSkillVersionsResponse - (*MutateLearnedSkillRequest)(nil), // 189: mecatl.v1.MutateLearnedSkillRequest - (*MutateLearnedSkillResponse)(nil), // 190: mecatl.v1.MutateLearnedSkillResponse - (*RollbackLearnedSkillRequest)(nil), // 191: mecatl.v1.RollbackLearnedSkillRequest - (*ListSkillChangesRequest)(nil), // 192: mecatl.v1.ListSkillChangesRequest - (*ListSkillChangesResponse)(nil), // 193: mecatl.v1.ListSkillChangesResponse - (*CreateTeamRequest)(nil), // 194: mecatl.v1.CreateTeamRequest - (*CreateTeamResponse)(nil), // 195: mecatl.v1.CreateTeamResponse - (*TeammateSpec)(nil), // 196: mecatl.v1.TeammateSpec - (*SpawnTeammateRequest)(nil), // 197: mecatl.v1.SpawnTeammateRequest - (*SpawnTeammateResponse)(nil), // 198: mecatl.v1.SpawnTeammateResponse - (*SendTeammateMessageRequest)(nil), // 199: mecatl.v1.SendTeammateMessageRequest - (*SendTeammateMessageResponse)(nil), // 200: mecatl.v1.SendTeammateMessageResponse - (*CancelTeammateRequest)(nil), // 201: mecatl.v1.CancelTeammateRequest - (*CancelTeammateResponse)(nil), // 202: mecatl.v1.CancelTeammateResponse - (*RunTeamRequest)(nil), // 203: mecatl.v1.RunTeamRequest - (*TeamEvent)(nil), // 204: mecatl.v1.TeamEvent - (*TeamOutcome)(nil), // 205: mecatl.v1.TeamOutcome - (*ListTeamRequest)(nil), // 206: mecatl.v1.ListTeamRequest - (*ListTeamResponse)(nil), // 207: mecatl.v1.ListTeamResponse - (*TeamMember)(nil), // 208: mecatl.v1.TeamMember - (*TeamTask)(nil), // 209: mecatl.v1.TeamTask - (*TeamFinding)(nil), // 210: mecatl.v1.TeamFinding - (*TeamMemberDisposition)(nil), // 211: mecatl.v1.TeamMemberDisposition - (*CleanupTeamRequest)(nil), // 212: mecatl.v1.CleanupTeamRequest - (*CleanupTeamResponse)(nil), // 213: mecatl.v1.CleanupTeamResponse - (*ApprovePlanRequest)(nil), // 214: mecatl.v1.ApprovePlanRequest - (*ManualDreamCapabilities)(nil), // 215: mecatl.v1.ManualDreamCapabilities - (*DreamTargetCapability)(nil), // 216: mecatl.v1.DreamTargetCapability - (*GenerateDreamPlanRequest)(nil), // 217: mecatl.v1.GenerateDreamPlanRequest - (*GenerateDreamPlanResponse)(nil), // 218: mecatl.v1.GenerateDreamPlanResponse - (*DecideDreamPlanRequest)(nil), // 219: mecatl.v1.DecideDreamPlanRequest - (*DecideDreamPlanResponse)(nil), // 220: mecatl.v1.DecideDreamPlanResponse - (*DreamReviewPlan)(nil), // 221: mecatl.v1.DreamReviewPlan - (*DreamOperation)(nil), // 222: mecatl.v1.DreamOperation - (*DreamParticipant)(nil), // 223: mecatl.v1.DreamParticipant - (*DreamReplacement)(nil), // 224: mecatl.v1.DreamReplacement - (*DreamReceipt)(nil), // 225: mecatl.v1.DreamReceipt - (*CompactSessionRequest)(nil), // 226: mecatl.v1.CompactSessionRequest - (*CompactSessionResponse)(nil), // 227: mecatl.v1.CompactSessionResponse - (*WorkspaceEnrollmentConnectRequest)(nil), // 228: mecatl.v1.WorkspaceEnrollmentConnectRequest - (*WorkspaceEnrollmentControlRequest)(nil), // 229: mecatl.v1.WorkspaceEnrollmentControlRequest - (*WorkspaceEnrollment)(nil), // 230: mecatl.v1.WorkspaceEnrollment - nil, // 231: mecatl.v1.McpServerSpec.HeadersEntry - nil, // 232: mecatl.v1.SessionSummary.TokenUsageEntry - nil, // 233: mecatl.v1.CleanupCounts.ByKindEntry - nil, // 234: mecatl.v1.CleanupCounts.ByStateEntry - nil, // 235: mecatl.v1.CleanupCounts.ByReasonEntry - nil, // 236: mecatl.v1.Session.TokenUsageEntry - nil, // 237: mecatl.v1.TokenUsage.ModelsEntry - nil, // 238: mecatl.v1.GetMcpPromptRequest.ArgumentsEntry - (*timestamppb.Timestamp)(nil), // 239: google.protobuf.Timestamp + (*RefreshMcpSourcesRequest)(nil), // 132: mecatl.v1.RefreshMcpSourcesRequest + (*RefreshMcpSourcesResponse)(nil), // 133: mecatl.v1.RefreshMcpSourcesResponse + (*ListToolHiveGroupsRequest)(nil), // 134: mecatl.v1.ListToolHiveGroupsRequest + (*ListToolHiveGroupsResponse)(nil), // 135: mecatl.v1.ListToolHiveGroupsResponse + (*AgentInfo)(nil), // 136: mecatl.v1.AgentInfo + (*ListAgentsRequest)(nil), // 137: mecatl.v1.ListAgentsRequest + (*ListAgentsResponse)(nil), // 138: mecatl.v1.ListAgentsResponse + (*Command)(nil), // 139: mecatl.v1.Command + (*ListCommandsRequest)(nil), // 140: mecatl.v1.ListCommandsRequest + (*ListCommandsResponse)(nil), // 141: mecatl.v1.ListCommandsResponse + (*Worktree)(nil), // 142: mecatl.v1.Worktree + (*ListWorktreesRequest)(nil), // 143: mecatl.v1.ListWorktreesRequest + (*ListWorktreesResponse)(nil), // 144: mecatl.v1.ListWorktreesResponse + (*SkillInfo)(nil), // 145: mecatl.v1.SkillInfo + (*ListSkillsRequest)(nil), // 146: mecatl.v1.ListSkillsRequest + (*ListSkillsResponse)(nil), // 147: mecatl.v1.ListSkillsResponse + (*SoulInfo)(nil), // 148: mecatl.v1.SoulInfo + (*GetSoulRequest)(nil), // 149: mecatl.v1.GetSoulRequest + (*GetSoulResponse)(nil), // 150: mecatl.v1.GetSoulResponse + (*UserModelEntry)(nil), // 151: mecatl.v1.UserModelEntry + (*GetUserModelRequest)(nil), // 152: mecatl.v1.GetUserModelRequest + (*UserModelRevision)(nil), // 153: mecatl.v1.UserModelRevision + (*UserModelDetail)(nil), // 154: mecatl.v1.UserModelDetail + (*GetUserModelResponse)(nil), // 155: mecatl.v1.GetUserModelResponse + (*ModelInfo)(nil), // 156: mecatl.v1.ModelInfo + (*ListModelsRequest)(nil), // 157: mecatl.v1.ListModelsRequest + (*ProviderStatus)(nil), // 158: mecatl.v1.ProviderStatus + (*ListModelsResponse)(nil), // 159: mecatl.v1.ListModelsResponse + (*ReflectSessionRequest)(nil), // 160: mecatl.v1.ReflectSessionRequest + (*ReflectionReceipt)(nil), // 161: mecatl.v1.ReflectionReceipt + (*ReflectSessionResponse)(nil), // 162: mecatl.v1.ReflectSessionResponse + (*LearningAttempt)(nil), // 163: mecatl.v1.LearningAttempt + (*GetLearningAttemptRequest)(nil), // 164: mecatl.v1.GetLearningAttemptRequest + (*GetLearningAttemptResponse)(nil), // 165: mecatl.v1.GetLearningAttemptResponse + (*ListLearningAttemptsRequest)(nil), // 166: mecatl.v1.ListLearningAttemptsRequest + (*ListLearningAttemptsResponse)(nil), // 167: mecatl.v1.ListLearningAttemptsResponse + (*MutateLearningAttemptRequest)(nil), // 168: mecatl.v1.MutateLearningAttemptRequest + (*MutateLearningAttemptResponse)(nil), // 169: mecatl.v1.MutateLearningAttemptResponse + (*ListLearningProposalsRequest)(nil), // 170: mecatl.v1.ListLearningProposalsRequest + (*LearningEvidenceRef)(nil), // 171: mecatl.v1.LearningEvidenceRef + (*LearningDecision)(nil), // 172: mecatl.v1.LearningDecision + (*LearningPromotionReceipt)(nil), // 173: mecatl.v1.LearningPromotionReceipt + (*LearningProposal)(nil), // 174: mecatl.v1.LearningProposal + (*ListLearningProposalsResponse)(nil), // 175: mecatl.v1.ListLearningProposalsResponse + (*GetLearningProposalRequest)(nil), // 176: mecatl.v1.GetLearningProposalRequest + (*GetLearningProposalResponse)(nil), // 177: mecatl.v1.GetLearningProposalResponse + (*DecideLearningProposalRequest)(nil), // 178: mecatl.v1.DecideLearningProposalRequest + (*DecideLearningProposalResponse)(nil), // 179: mecatl.v1.DecideLearningProposalResponse + (*UndoLearningPromotionRequest)(nil), // 180: mecatl.v1.UndoLearningPromotionRequest + (*UndoLearningPromotionResponse)(nil), // 181: mecatl.v1.UndoLearningPromotionResponse + (*LearnedSkillVersion)(nil), // 182: mecatl.v1.LearnedSkillVersion + (*SkillEvaluation)(nil), // 183: mecatl.v1.SkillEvaluation + (*SkillChangeReceipt)(nil), // 184: mecatl.v1.SkillChangeReceipt + (*ListLearnedSkillsRequest)(nil), // 185: mecatl.v1.ListLearnedSkillsRequest + (*ListLearnedSkillsResponse)(nil), // 186: mecatl.v1.ListLearnedSkillsResponse + (*GetLearnedSkillRequest)(nil), // 187: mecatl.v1.GetLearnedSkillRequest + (*GetLearnedSkillResponse)(nil), // 188: mecatl.v1.GetLearnedSkillResponse + (*DiffLearnedSkillVersionsRequest)(nil), // 189: mecatl.v1.DiffLearnedSkillVersionsRequest + (*DiffLearnedSkillVersionsResponse)(nil), // 190: mecatl.v1.DiffLearnedSkillVersionsResponse + (*MutateLearnedSkillRequest)(nil), // 191: mecatl.v1.MutateLearnedSkillRequest + (*MutateLearnedSkillResponse)(nil), // 192: mecatl.v1.MutateLearnedSkillResponse + (*RollbackLearnedSkillRequest)(nil), // 193: mecatl.v1.RollbackLearnedSkillRequest + (*ListSkillChangesRequest)(nil), // 194: mecatl.v1.ListSkillChangesRequest + (*ListSkillChangesResponse)(nil), // 195: mecatl.v1.ListSkillChangesResponse + (*CreateTeamRequest)(nil), // 196: mecatl.v1.CreateTeamRequest + (*CreateTeamResponse)(nil), // 197: mecatl.v1.CreateTeamResponse + (*TeammateSpec)(nil), // 198: mecatl.v1.TeammateSpec + (*SpawnTeammateRequest)(nil), // 199: mecatl.v1.SpawnTeammateRequest + (*SpawnTeammateResponse)(nil), // 200: mecatl.v1.SpawnTeammateResponse + (*SendTeammateMessageRequest)(nil), // 201: mecatl.v1.SendTeammateMessageRequest + (*SendTeammateMessageResponse)(nil), // 202: mecatl.v1.SendTeammateMessageResponse + (*CancelTeammateRequest)(nil), // 203: mecatl.v1.CancelTeammateRequest + (*CancelTeammateResponse)(nil), // 204: mecatl.v1.CancelTeammateResponse + (*RunTeamRequest)(nil), // 205: mecatl.v1.RunTeamRequest + (*TeamEvent)(nil), // 206: mecatl.v1.TeamEvent + (*TeamOutcome)(nil), // 207: mecatl.v1.TeamOutcome + (*ListTeamRequest)(nil), // 208: mecatl.v1.ListTeamRequest + (*ListTeamResponse)(nil), // 209: mecatl.v1.ListTeamResponse + (*TeamMember)(nil), // 210: mecatl.v1.TeamMember + (*TeamTask)(nil), // 211: mecatl.v1.TeamTask + (*TeamFinding)(nil), // 212: mecatl.v1.TeamFinding + (*TeamMemberDisposition)(nil), // 213: mecatl.v1.TeamMemberDisposition + (*CleanupTeamRequest)(nil), // 214: mecatl.v1.CleanupTeamRequest + (*CleanupTeamResponse)(nil), // 215: mecatl.v1.CleanupTeamResponse + (*ApprovePlanRequest)(nil), // 216: mecatl.v1.ApprovePlanRequest + (*ManualDreamCapabilities)(nil), // 217: mecatl.v1.ManualDreamCapabilities + (*DreamTargetCapability)(nil), // 218: mecatl.v1.DreamTargetCapability + (*GenerateDreamPlanRequest)(nil), // 219: mecatl.v1.GenerateDreamPlanRequest + (*GenerateDreamPlanResponse)(nil), // 220: mecatl.v1.GenerateDreamPlanResponse + (*DecideDreamPlanRequest)(nil), // 221: mecatl.v1.DecideDreamPlanRequest + (*DecideDreamPlanResponse)(nil), // 222: mecatl.v1.DecideDreamPlanResponse + (*DreamReviewPlan)(nil), // 223: mecatl.v1.DreamReviewPlan + (*DreamOperation)(nil), // 224: mecatl.v1.DreamOperation + (*DreamParticipant)(nil), // 225: mecatl.v1.DreamParticipant + (*DreamReplacement)(nil), // 226: mecatl.v1.DreamReplacement + (*DreamReceipt)(nil), // 227: mecatl.v1.DreamReceipt + (*CompactSessionRequest)(nil), // 228: mecatl.v1.CompactSessionRequest + (*CompactSessionResponse)(nil), // 229: mecatl.v1.CompactSessionResponse + (*WorkspaceEnrollmentConnectRequest)(nil), // 230: mecatl.v1.WorkspaceEnrollmentConnectRequest + (*WorkspaceEnrollmentControlRequest)(nil), // 231: mecatl.v1.WorkspaceEnrollmentControlRequest + (*WorkspaceEnrollment)(nil), // 232: mecatl.v1.WorkspaceEnrollment + nil, // 233: mecatl.v1.McpServerSpec.HeadersEntry + nil, // 234: mecatl.v1.SessionSummary.TokenUsageEntry + nil, // 235: mecatl.v1.CleanupCounts.ByKindEntry + nil, // 236: mecatl.v1.CleanupCounts.ByStateEntry + nil, // 237: mecatl.v1.CleanupCounts.ByReasonEntry + nil, // 238: mecatl.v1.Session.TokenUsageEntry + nil, // 239: mecatl.v1.TokenUsage.ModelsEntry + nil, // 240: mecatl.v1.GetMcpPromptRequest.ArgumentsEntry + (*timestamppb.Timestamp)(nil), // 241: google.protobuf.Timestamp } var file_mecatl_v1_harness_proto_depIdxs = []int32{ 0, // 0: mecatl.v1.CreateSessionRequest.mode:type_name -> mecatl.v1.PermissionMode 10, // 1: mecatl.v1.CreateSessionRequest.limits:type_name -> mecatl.v1.Limits 12, // 2: mecatl.v1.CreateSessionRequest.mcp_servers:type_name -> mecatl.v1.McpServerSpec - 231, // 3: mecatl.v1.McpServerSpec.headers:type_name -> mecatl.v1.McpServerSpec.HeadersEntry + 233, // 3: mecatl.v1.McpServerSpec.headers:type_name -> mecatl.v1.McpServerSpec.HeadersEntry 17, // 4: mecatl.v1.GetCompatibilityInfoResponse.capabilities:type_name -> mecatl.v1.ServerCapabilities - 215, // 5: mecatl.v1.ServerCapabilities.manual_dream:type_name -> mecatl.v1.ManualDreamCapabilities + 217, // 5: mecatl.v1.ServerCapabilities.manual_dream:type_name -> mecatl.v1.ManualDreamCapabilities 20, // 6: mecatl.v1.ListSessionMcpConnectorsResponse.connectors:type_name -> mecatl.v1.McpConnectorStatus 17, // 7: mecatl.v1.CreateSessionResponse.capabilities:type_name -> mecatl.v1.ServerCapabilities 24, // 8: mecatl.v1.CreateSessionResponse.session_capabilities:type_name -> mecatl.v1.SessionCapabilities @@ -20793,13 +20954,13 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 38, // 18: mecatl.v1.SessionSummary.capabilities:type_name -> mecatl.v1.SessionInventoryCapabilities 22, // 19: mecatl.v1.SessionSummary.placement:type_name -> mecatl.v1.PlacementMetadata 74, // 20: mecatl.v1.SessionSummary.title_metadata:type_name -> mecatl.v1.SessionTitle - 232, // 21: mecatl.v1.SessionSummary.token_usage:type_name -> mecatl.v1.SessionSummary.TokenUsageEntry + 234, // 21: mecatl.v1.SessionSummary.token_usage:type_name -> mecatl.v1.SessionSummary.TokenUsageEntry 39, // 22: mecatl.v1.SessionInventoryCapabilities.reasons:type_name -> mecatl.v1.SessionInventoryActionReasons 36, // 23: mecatl.v1.ListSessionsResponse.sessions:type_name -> mecatl.v1.SessionSummary 42, // 24: mecatl.v1.GetStorageHealthResponse.policy:type_name -> mecatl.v1.RetentionPolicy - 233, // 25: mecatl.v1.CleanupCounts.by_kind:type_name -> mecatl.v1.CleanupCounts.ByKindEntry - 234, // 26: mecatl.v1.CleanupCounts.by_state:type_name -> mecatl.v1.CleanupCounts.ByStateEntry - 235, // 27: mecatl.v1.CleanupCounts.by_reason:type_name -> mecatl.v1.CleanupCounts.ByReasonEntry + 235, // 25: mecatl.v1.CleanupCounts.by_kind:type_name -> mecatl.v1.CleanupCounts.ByKindEntry + 236, // 26: mecatl.v1.CleanupCounts.by_state:type_name -> mecatl.v1.CleanupCounts.ByStateEntry + 237, // 27: mecatl.v1.CleanupCounts.by_reason:type_name -> mecatl.v1.CleanupCounts.ByReasonEntry 52, // 28: mecatl.v1.PlanSessionCleanupResponse.eligible:type_name -> mecatl.v1.CleanupCandidate 51, // 29: mecatl.v1.PlanSessionCleanupResponse.protected:type_name -> mecatl.v1.CleanupCounts 51, // 30: mecatl.v1.PlanSessionCleanupResponse.eligible_counts:type_name -> mecatl.v1.CleanupCounts @@ -20817,11 +20978,11 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 37, // 42: mecatl.v1.Session.relationship:type_name -> mecatl.v1.SessionRelationship 22, // 43: mecatl.v1.Session.placement:type_name -> mecatl.v1.PlacementMetadata 74, // 44: mecatl.v1.Session.title_metadata:type_name -> mecatl.v1.SessionTitle - 236, // 45: mecatl.v1.Session.token_usage:type_name -> mecatl.v1.Session.TokenUsageEntry + 238, // 45: mecatl.v1.Session.token_usage:type_name -> mecatl.v1.Session.TokenUsageEntry 24, // 46: mecatl.v1.Session.session_capabilities:type_name -> mecatl.v1.SessionCapabilities 75, // 47: mecatl.v1.SessionTitle.latest_attempt:type_name -> mecatl.v1.TitleAttemptSummary 114, // 48: mecatl.v1.TokenUsage.total:type_name -> mecatl.v1.Usage - 237, // 49: mecatl.v1.TokenUsage.models:type_name -> mecatl.v1.TokenUsage.ModelsEntry + 239, // 49: mecatl.v1.TokenUsage.models:type_name -> mecatl.v1.TokenUsage.ModelsEntry 82, // 50: mecatl.v1.ConverseRequest.prompt:type_name -> mecatl.v1.Prompt 81, // 51: mecatl.v1.ConverseRequest.retry:type_name -> mecatl.v1.RetryStart 83, // 52: mecatl.v1.ConverseRequest.resume_approval:type_name -> mecatl.v1.ResumeApproval @@ -20841,7 +21002,7 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 83, // 66: mecatl.v1.CancelMcpAuthorizationRequest.resume_approval:type_name -> mecatl.v1.ResumeApproval 84, // 67: mecatl.v1.CancelMcpAuthorizationRequest.cancel:type_name -> mecatl.v1.Cancel 95, // 68: mecatl.v1.CancelMcpAuthorizationResponse.event:type_name -> mecatl.v1.Event - 239, // 69: mecatl.v1.Authorization.expires_at:type_name -> google.protobuf.Timestamp + 241, // 69: mecatl.v1.Authorization.expires_at:type_name -> google.protobuf.Timestamp 109, // 70: mecatl.v1.Event.tool_call:type_name -> mecatl.v1.ToolCall 110, // 71: mecatl.v1.Event.tool_result:type_name -> mecatl.v1.ToolResult 111, // 72: mecatl.v1.Event.ask:type_name -> mecatl.v1.PermissionAsk @@ -20874,9 +21035,9 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 114, // 99: mecatl.v1.Subagent.usage:type_name -> mecatl.v1.Usage 106, // 100: mecatl.v1.Team.roster:type_name -> mecatl.v1.TeamMemberSpec 114, // 101: mecatl.v1.Team.usage:type_name -> mecatl.v1.Usage - 209, // 102: mecatl.v1.Team.tasks:type_name -> mecatl.v1.TeamTask - 210, // 103: mecatl.v1.Team.findings:type_name -> mecatl.v1.TeamFinding - 211, // 104: mecatl.v1.Team.dispositions:type_name -> mecatl.v1.TeamMemberDisposition + 211, // 102: mecatl.v1.Team.tasks:type_name -> mecatl.v1.TeamTask + 212, // 103: mecatl.v1.Team.findings:type_name -> mecatl.v1.TeamFinding + 213, // 104: mecatl.v1.Team.dispositions:type_name -> mecatl.v1.TeamMemberDisposition 114, // 105: mecatl.v1.Parallel.usage:type_name -> mecatl.v1.Usage 80, // 106: mecatl.v1.ToolResult.blocks:type_name -> mecatl.v1.ContentBlock 114, // 107: mecatl.v1.Result.usage:type_name -> mecatl.v1.Usage @@ -20887,72 +21048,72 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 118, // 112: mecatl.v1.ReadMcpResourceResponse.contents:type_name -> mecatl.v1.McpResourceContents 121, // 113: mecatl.v1.McpPrompt.arguments:type_name -> mecatl.v1.McpPromptArgument 122, // 114: mecatl.v1.ListMcpPromptsResponse.prompts:type_name -> mecatl.v1.McpPrompt - 238, // 115: mecatl.v1.GetMcpPromptRequest.arguments:type_name -> mecatl.v1.GetMcpPromptRequest.ArgumentsEntry + 240, // 115: mecatl.v1.GetMcpPromptRequest.arguments:type_name -> mecatl.v1.GetMcpPromptRequest.ArgumentsEntry 126, // 116: mecatl.v1.GetMcpPromptResponse.messages:type_name -> mecatl.v1.McpPromptMessage 128, // 117: mecatl.v1.McpSource.servers:type_name -> mecatl.v1.McpServerInfo 129, // 118: mecatl.v1.ListMcpSourcesResponse.sources:type_name -> mecatl.v1.McpSource - 134, // 119: mecatl.v1.ListAgentsResponse.agents:type_name -> mecatl.v1.AgentInfo - 137, // 120: mecatl.v1.ListCommandsResponse.commands:type_name -> mecatl.v1.Command - 140, // 121: mecatl.v1.ListWorktreesResponse.worktrees:type_name -> mecatl.v1.Worktree - 143, // 122: mecatl.v1.ListSkillsResponse.skills:type_name -> mecatl.v1.SkillInfo + 136, // 119: mecatl.v1.ListAgentsResponse.agents:type_name -> mecatl.v1.AgentInfo + 139, // 120: mecatl.v1.ListCommandsResponse.commands:type_name -> mecatl.v1.Command + 142, // 121: mecatl.v1.ListWorktreesResponse.worktrees:type_name -> mecatl.v1.Worktree + 145, // 122: mecatl.v1.ListSkillsResponse.skills:type_name -> mecatl.v1.SkillInfo 6, // 123: mecatl.v1.SoulInfo.provenance:type_name -> mecatl.v1.SoulProvenance - 146, // 124: mecatl.v1.GetSoulResponse.soul:type_name -> mecatl.v1.SoulInfo - 239, // 125: mecatl.v1.UserModelRevision.updated_at:type_name -> google.protobuf.Timestamp - 151, // 126: mecatl.v1.UserModelDetail.current:type_name -> mecatl.v1.UserModelRevision - 151, // 127: mecatl.v1.UserModelDetail.history:type_name -> mecatl.v1.UserModelRevision - 149, // 128: mecatl.v1.GetUserModelResponse.entries:type_name -> mecatl.v1.UserModelEntry - 152, // 129: mecatl.v1.GetUserModelResponse.detail:type_name -> mecatl.v1.UserModelDetail - 154, // 130: mecatl.v1.ListModelsResponse.models:type_name -> mecatl.v1.ModelInfo - 156, // 131: mecatl.v1.ListModelsResponse.provider_status:type_name -> mecatl.v1.ProviderStatus - 159, // 132: mecatl.v1.ReflectSessionResponse.receipt:type_name -> mecatl.v1.ReflectionReceipt - 239, // 133: mecatl.v1.LearningAttempt.claim_expires_at:type_name -> google.protobuf.Timestamp - 239, // 134: mecatl.v1.LearningAttempt.created_at:type_name -> google.protobuf.Timestamp - 239, // 135: mecatl.v1.LearningAttempt.updated_at:type_name -> google.protobuf.Timestamp - 161, // 136: mecatl.v1.GetLearningAttemptResponse.attempt:type_name -> mecatl.v1.LearningAttempt - 161, // 137: mecatl.v1.ListLearningAttemptsResponse.attempts:type_name -> mecatl.v1.LearningAttempt - 161, // 138: mecatl.v1.MutateLearningAttemptResponse.attempt:type_name -> mecatl.v1.LearningAttempt - 239, // 139: mecatl.v1.LearningDecision.at:type_name -> google.protobuf.Timestamp - 169, // 140: mecatl.v1.LearningProposal.evidence:type_name -> mecatl.v1.LearningEvidenceRef - 170, // 141: mecatl.v1.LearningProposal.decisions:type_name -> mecatl.v1.LearningDecision - 171, // 142: mecatl.v1.LearningProposal.promotion:type_name -> mecatl.v1.LearningPromotionReceipt - 239, // 143: mecatl.v1.LearningProposal.created_at:type_name -> google.protobuf.Timestamp - 239, // 144: mecatl.v1.LearningProposal.updated_at:type_name -> google.protobuf.Timestamp - 172, // 145: mecatl.v1.ListLearningProposalsResponse.proposals:type_name -> mecatl.v1.LearningProposal - 172, // 146: mecatl.v1.GetLearningProposalResponse.proposal:type_name -> mecatl.v1.LearningProposal - 172, // 147: mecatl.v1.DecideLearningProposalResponse.proposal:type_name -> mecatl.v1.LearningProposal - 172, // 148: mecatl.v1.UndoLearningPromotionResponse.proposal:type_name -> mecatl.v1.LearningProposal - 169, // 149: mecatl.v1.LearnedSkillVersion.evidence:type_name -> mecatl.v1.LearningEvidenceRef - 181, // 150: mecatl.v1.LearnedSkillVersion.evaluations:type_name -> mecatl.v1.SkillEvaluation - 182, // 151: mecatl.v1.LearnedSkillVersion.receipts:type_name -> mecatl.v1.SkillChangeReceipt - 239, // 152: mecatl.v1.LearnedSkillVersion.created_at:type_name -> google.protobuf.Timestamp - 239, // 153: mecatl.v1.LearnedSkillVersion.updated_at:type_name -> google.protobuf.Timestamp - 239, // 154: mecatl.v1.SkillEvaluation.at:type_name -> google.protobuf.Timestamp - 239, // 155: mecatl.v1.SkillChangeReceipt.at:type_name -> google.protobuf.Timestamp - 180, // 156: mecatl.v1.ListLearnedSkillsResponse.skills:type_name -> mecatl.v1.LearnedSkillVersion - 180, // 157: mecatl.v1.GetLearnedSkillResponse.skill:type_name -> mecatl.v1.LearnedSkillVersion - 180, // 158: mecatl.v1.MutateLearnedSkillResponse.skill:type_name -> mecatl.v1.LearnedSkillVersion - 182, // 159: mecatl.v1.ListSkillChangesResponse.changes:type_name -> mecatl.v1.SkillChangeReceipt - 196, // 160: mecatl.v1.CreateTeamRequest.members:type_name -> mecatl.v1.TeammateSpec - 208, // 161: mecatl.v1.CreateTeamResponse.members:type_name -> mecatl.v1.TeamMember - 208, // 162: mecatl.v1.SpawnTeammateResponse.member:type_name -> mecatl.v1.TeamMember + 148, // 124: mecatl.v1.GetSoulResponse.soul:type_name -> mecatl.v1.SoulInfo + 241, // 125: mecatl.v1.UserModelRevision.updated_at:type_name -> google.protobuf.Timestamp + 153, // 126: mecatl.v1.UserModelDetail.current:type_name -> mecatl.v1.UserModelRevision + 153, // 127: mecatl.v1.UserModelDetail.history:type_name -> mecatl.v1.UserModelRevision + 151, // 128: mecatl.v1.GetUserModelResponse.entries:type_name -> mecatl.v1.UserModelEntry + 154, // 129: mecatl.v1.GetUserModelResponse.detail:type_name -> mecatl.v1.UserModelDetail + 156, // 130: mecatl.v1.ListModelsResponse.models:type_name -> mecatl.v1.ModelInfo + 158, // 131: mecatl.v1.ListModelsResponse.provider_status:type_name -> mecatl.v1.ProviderStatus + 161, // 132: mecatl.v1.ReflectSessionResponse.receipt:type_name -> mecatl.v1.ReflectionReceipt + 241, // 133: mecatl.v1.LearningAttempt.claim_expires_at:type_name -> google.protobuf.Timestamp + 241, // 134: mecatl.v1.LearningAttempt.created_at:type_name -> google.protobuf.Timestamp + 241, // 135: mecatl.v1.LearningAttempt.updated_at:type_name -> google.protobuf.Timestamp + 163, // 136: mecatl.v1.GetLearningAttemptResponse.attempt:type_name -> mecatl.v1.LearningAttempt + 163, // 137: mecatl.v1.ListLearningAttemptsResponse.attempts:type_name -> mecatl.v1.LearningAttempt + 163, // 138: mecatl.v1.MutateLearningAttemptResponse.attempt:type_name -> mecatl.v1.LearningAttempt + 241, // 139: mecatl.v1.LearningDecision.at:type_name -> google.protobuf.Timestamp + 171, // 140: mecatl.v1.LearningProposal.evidence:type_name -> mecatl.v1.LearningEvidenceRef + 172, // 141: mecatl.v1.LearningProposal.decisions:type_name -> mecatl.v1.LearningDecision + 173, // 142: mecatl.v1.LearningProposal.promotion:type_name -> mecatl.v1.LearningPromotionReceipt + 241, // 143: mecatl.v1.LearningProposal.created_at:type_name -> google.protobuf.Timestamp + 241, // 144: mecatl.v1.LearningProposal.updated_at:type_name -> google.protobuf.Timestamp + 174, // 145: mecatl.v1.ListLearningProposalsResponse.proposals:type_name -> mecatl.v1.LearningProposal + 174, // 146: mecatl.v1.GetLearningProposalResponse.proposal:type_name -> mecatl.v1.LearningProposal + 174, // 147: mecatl.v1.DecideLearningProposalResponse.proposal:type_name -> mecatl.v1.LearningProposal + 174, // 148: mecatl.v1.UndoLearningPromotionResponse.proposal:type_name -> mecatl.v1.LearningProposal + 171, // 149: mecatl.v1.LearnedSkillVersion.evidence:type_name -> mecatl.v1.LearningEvidenceRef + 183, // 150: mecatl.v1.LearnedSkillVersion.evaluations:type_name -> mecatl.v1.SkillEvaluation + 184, // 151: mecatl.v1.LearnedSkillVersion.receipts:type_name -> mecatl.v1.SkillChangeReceipt + 241, // 152: mecatl.v1.LearnedSkillVersion.created_at:type_name -> google.protobuf.Timestamp + 241, // 153: mecatl.v1.LearnedSkillVersion.updated_at:type_name -> google.protobuf.Timestamp + 241, // 154: mecatl.v1.SkillEvaluation.at:type_name -> google.protobuf.Timestamp + 241, // 155: mecatl.v1.SkillChangeReceipt.at:type_name -> google.protobuf.Timestamp + 182, // 156: mecatl.v1.ListLearnedSkillsResponse.skills:type_name -> mecatl.v1.LearnedSkillVersion + 182, // 157: mecatl.v1.GetLearnedSkillResponse.skill:type_name -> mecatl.v1.LearnedSkillVersion + 182, // 158: mecatl.v1.MutateLearnedSkillResponse.skill:type_name -> mecatl.v1.LearnedSkillVersion + 184, // 159: mecatl.v1.ListSkillChangesResponse.changes:type_name -> mecatl.v1.SkillChangeReceipt + 198, // 160: mecatl.v1.CreateTeamRequest.members:type_name -> mecatl.v1.TeammateSpec + 210, // 161: mecatl.v1.CreateTeamResponse.members:type_name -> mecatl.v1.TeamMember + 210, // 162: mecatl.v1.SpawnTeammateResponse.member:type_name -> mecatl.v1.TeamMember 95, // 163: mecatl.v1.TeamEvent.event:type_name -> mecatl.v1.Event - 205, // 164: mecatl.v1.TeamEvent.outcome:type_name -> mecatl.v1.TeamOutcome + 207, // 164: mecatl.v1.TeamEvent.outcome:type_name -> mecatl.v1.TeamOutcome 114, // 165: mecatl.v1.TeamOutcome.usage:type_name -> mecatl.v1.Usage - 211, // 166: mecatl.v1.TeamOutcome.dispositions:type_name -> mecatl.v1.TeamMemberDisposition - 210, // 167: mecatl.v1.TeamOutcome.findings:type_name -> mecatl.v1.TeamFinding - 208, // 168: mecatl.v1.ListTeamResponse.members:type_name -> mecatl.v1.TeamMember - 209, // 169: mecatl.v1.ListTeamResponse.tasks:type_name -> mecatl.v1.TeamTask + 213, // 166: mecatl.v1.TeamOutcome.dispositions:type_name -> mecatl.v1.TeamMemberDisposition + 212, // 167: mecatl.v1.TeamOutcome.findings:type_name -> mecatl.v1.TeamFinding + 210, // 168: mecatl.v1.ListTeamResponse.members:type_name -> mecatl.v1.TeamMember + 211, // 169: mecatl.v1.ListTeamResponse.tasks:type_name -> mecatl.v1.TeamTask 7, // 170: mecatl.v1.TeamMemberDisposition.reason:type_name -> mecatl.v1.TeamMemberStopReason 0, // 171: mecatl.v1.ApprovePlanRequest.target_mode:type_name -> mecatl.v1.PermissionMode - 216, // 172: mecatl.v1.ManualDreamCapabilities.project_memory:type_name -> mecatl.v1.DreamTargetCapability - 216, // 173: mecatl.v1.ManualDreamCapabilities.user_model:type_name -> mecatl.v1.DreamTargetCapability - 221, // 174: mecatl.v1.GenerateDreamPlanResponse.plan:type_name -> mecatl.v1.DreamReviewPlan - 225, // 175: mecatl.v1.DecideDreamPlanResponse.receipt:type_name -> mecatl.v1.DreamReceipt - 239, // 176: mecatl.v1.DreamReviewPlan.expires_at:type_name -> google.protobuf.Timestamp - 222, // 177: mecatl.v1.DreamReviewPlan.operations:type_name -> mecatl.v1.DreamOperation - 223, // 178: mecatl.v1.DreamOperation.survivor:type_name -> mecatl.v1.DreamParticipant - 223, // 179: mecatl.v1.DreamOperation.sources:type_name -> mecatl.v1.DreamParticipant - 224, // 180: mecatl.v1.DreamOperation.replacement:type_name -> mecatl.v1.DreamReplacement + 218, // 172: mecatl.v1.ManualDreamCapabilities.project_memory:type_name -> mecatl.v1.DreamTargetCapability + 218, // 173: mecatl.v1.ManualDreamCapabilities.user_model:type_name -> mecatl.v1.DreamTargetCapability + 223, // 174: mecatl.v1.GenerateDreamPlanResponse.plan:type_name -> mecatl.v1.DreamReviewPlan + 227, // 175: mecatl.v1.DecideDreamPlanResponse.receipt:type_name -> mecatl.v1.DreamReceipt + 241, // 176: mecatl.v1.DreamReviewPlan.expires_at:type_name -> google.protobuf.Timestamp + 224, // 177: mecatl.v1.DreamReviewPlan.operations:type_name -> mecatl.v1.DreamOperation + 225, // 178: mecatl.v1.DreamOperation.survivor:type_name -> mecatl.v1.DreamParticipant + 225, // 179: mecatl.v1.DreamOperation.sources:type_name -> mecatl.v1.DreamParticipant + 226, // 180: mecatl.v1.DreamOperation.replacement:type_name -> mecatl.v1.DreamReplacement 76, // 181: mecatl.v1.SessionSummary.TokenUsageEntry.value:type_name -> mecatl.v1.TokenUsage 76, // 182: mecatl.v1.Session.TokenUsageEntry.value:type_name -> mecatl.v1.TokenUsage 114, // 183: mecatl.v1.TokenUsage.ModelsEntry.value:type_name -> mecatl.v1.Usage @@ -20965,7 +21126,7 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 63, // 190: mecatl.v1.HarnessService.CloseSession:input_type -> mecatl.v1.CloseSessionRequest 65, // 191: mecatl.v1.HarnessService.RenameSession:input_type -> mecatl.v1.RenameSessionRequest 67, // 192: mecatl.v1.HarnessService.DeleteSession:input_type -> mecatl.v1.DeleteSessionRequest - 226, // 193: mecatl.v1.HarnessService.CompactSession:input_type -> mecatl.v1.CompactSessionRequest + 228, // 193: mecatl.v1.HarnessService.CompactSession:input_type -> mecatl.v1.CompactSessionRequest 69, // 194: mecatl.v1.HarnessService.ClearSession:input_type -> mecatl.v1.ClearSessionRequest 71, // 195: mecatl.v1.HarnessService.ForkSession:input_type -> mecatl.v1.ForkSessionRequest 77, // 196: mecatl.v1.HarnessService.Converse:input_type -> mecatl.v1.ConverseRequest @@ -20974,138 +21135,140 @@ var file_mecatl_v1_harness_proto_depIdxs = []int32{ 123, // 199: mecatl.v1.HarnessService.ListMcpPrompts:input_type -> mecatl.v1.ListMcpPromptsRequest 125, // 200: mecatl.v1.HarnessService.GetMcpPrompt:input_type -> mecatl.v1.GetMcpPromptRequest 130, // 201: mecatl.v1.HarnessService.ListMcpSources:input_type -> mecatl.v1.ListMcpSourcesRequest - 18, // 202: mecatl.v1.HarnessService.ListSessionMcpConnectors:input_type -> mecatl.v1.ListSessionMcpConnectorsRequest - 132, // 203: mecatl.v1.HarnessService.ListToolHiveGroups:input_type -> mecatl.v1.ListToolHiveGroupsRequest - 135, // 204: mecatl.v1.HarnessService.ListAgents:input_type -> mecatl.v1.ListAgentsRequest - 138, // 205: mecatl.v1.HarnessService.ListCommands:input_type -> mecatl.v1.ListCommandsRequest - 141, // 206: mecatl.v1.HarnessService.ListWorktrees:input_type -> mecatl.v1.ListWorktreesRequest - 30, // 207: mecatl.v1.HarnessService.StreamSessionEvents:input_type -> mecatl.v1.StreamSessionEventsRequest - 31, // 208: mecatl.v1.HarnessService.StreamSessionLive:input_type -> mecatl.v1.StreamSessionLiveRequest - 32, // 209: mecatl.v1.HarnessService.WatchSessionEvents:input_type -> mecatl.v1.WatchSessionEventsRequest - 88, // 210: mecatl.v1.HarnessService.GetMcpAuthorizationPresentation:input_type -> mecatl.v1.GetMcpAuthorizationPresentationRequest - 90, // 211: mecatl.v1.HarnessService.RecheckMcpAuthorization:input_type -> mecatl.v1.RecheckMcpAuthorizationRequest - 92, // 212: mecatl.v1.HarnessService.CancelMcpAuthorization:input_type -> mecatl.v1.CancelMcpAuthorizationRequest - 34, // 213: mecatl.v1.HarnessService.ListSessions:input_type -> mecatl.v1.ListSessionsRequest - 41, // 214: mecatl.v1.HarnessService.GetStorageHealth:input_type -> mecatl.v1.GetStorageHealthRequest - 44, // 215: mecatl.v1.HarnessService.PlanSessionMigration:input_type -> mecatl.v1.PlanSessionMigrationRequest - 46, // 216: mecatl.v1.HarnessService.ApplySessionMigration:input_type -> mecatl.v1.ApplySessionMigrationRequest - 47, // 217: mecatl.v1.HarnessService.ResumeSessionMigration:input_type -> mecatl.v1.ResumeSessionMigrationRequest - 48, // 218: mecatl.v1.HarnessService.CancelSessionMigration:input_type -> mecatl.v1.CancelSessionMigrationRequest - 49, // 219: mecatl.v1.HarnessService.GetSessionMigrationJob:input_type -> mecatl.v1.GetSessionMigrationJobRequest - 53, // 220: mecatl.v1.HarnessService.PlanSessionCleanup:input_type -> mecatl.v1.PlanSessionCleanupRequest - 55, // 221: mecatl.v1.HarnessService.ApplySessionCleanup:input_type -> mecatl.v1.ApplySessionCleanupRequest - 56, // 222: mecatl.v1.HarnessService.CancelSessionCleanup:input_type -> mecatl.v1.CancelSessionCleanupRequest - 57, // 223: mecatl.v1.HarnessService.GetSessionCleanupJob:input_type -> mecatl.v1.GetSessionCleanupJobRequest - 144, // 224: mecatl.v1.HarnessService.ListSkills:input_type -> mecatl.v1.ListSkillsRequest - 147, // 225: mecatl.v1.HarnessService.GetSoul:input_type -> mecatl.v1.GetSoulRequest - 150, // 226: mecatl.v1.HarnessService.GetUserModel:input_type -> mecatl.v1.GetUserModelRequest - 158, // 227: mecatl.v1.HarnessService.ReflectSession:input_type -> mecatl.v1.ReflectSessionRequest - 162, // 228: mecatl.v1.HarnessService.GetLearningAttempt:input_type -> mecatl.v1.GetLearningAttemptRequest - 164, // 229: mecatl.v1.HarnessService.ListLearningAttempts:input_type -> mecatl.v1.ListLearningAttemptsRequest - 166, // 230: mecatl.v1.HarnessService.RetryLearningAttempt:input_type -> mecatl.v1.MutateLearningAttemptRequest - 166, // 231: mecatl.v1.HarnessService.AbandonLearningAttempt:input_type -> mecatl.v1.MutateLearningAttemptRequest - 217, // 232: mecatl.v1.HarnessService.GenerateDreamPlan:input_type -> mecatl.v1.GenerateDreamPlanRequest - 219, // 233: mecatl.v1.HarnessService.DecideDreamPlan:input_type -> mecatl.v1.DecideDreamPlanRequest - 168, // 234: mecatl.v1.HarnessService.ListLearningProposals:input_type -> mecatl.v1.ListLearningProposalsRequest - 174, // 235: mecatl.v1.HarnessService.GetLearningProposal:input_type -> mecatl.v1.GetLearningProposalRequest - 176, // 236: mecatl.v1.HarnessService.DecideLearningProposal:input_type -> mecatl.v1.DecideLearningProposalRequest - 178, // 237: mecatl.v1.HarnessService.UndoLearningPromotion:input_type -> mecatl.v1.UndoLearningPromotionRequest - 183, // 238: mecatl.v1.HarnessService.ListLearnedSkills:input_type -> mecatl.v1.ListLearnedSkillsRequest - 185, // 239: mecatl.v1.HarnessService.GetLearnedSkill:input_type -> mecatl.v1.GetLearnedSkillRequest - 187, // 240: mecatl.v1.HarnessService.DiffLearnedSkillVersions:input_type -> mecatl.v1.DiffLearnedSkillVersionsRequest - 189, // 241: mecatl.v1.HarnessService.ActivateLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest - 189, // 242: mecatl.v1.HarnessService.RejectLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest - 189, // 243: mecatl.v1.HarnessService.ArchiveLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest - 191, // 244: mecatl.v1.HarnessService.RollbackLearnedSkill:input_type -> mecatl.v1.RollbackLearnedSkillRequest - 192, // 245: mecatl.v1.HarnessService.ListSkillChanges:input_type -> mecatl.v1.ListSkillChangesRequest - 155, // 246: mecatl.v1.HarnessService.ListModels:input_type -> mecatl.v1.ListModelsRequest - 194, // 247: mecatl.v1.HarnessService.CreateTeam:input_type -> mecatl.v1.CreateTeamRequest - 197, // 248: mecatl.v1.HarnessService.SpawnTeammate:input_type -> mecatl.v1.SpawnTeammateRequest - 199, // 249: mecatl.v1.HarnessService.SendTeammateMessage:input_type -> mecatl.v1.SendTeammateMessageRequest - 201, // 250: mecatl.v1.HarnessService.CancelTeammate:input_type -> mecatl.v1.CancelTeammateRequest - 203, // 251: mecatl.v1.HarnessService.RunTeam:input_type -> mecatl.v1.RunTeamRequest - 206, // 252: mecatl.v1.HarnessService.ListTeam:input_type -> mecatl.v1.ListTeamRequest - 212, // 253: mecatl.v1.HarnessService.CleanupTeam:input_type -> mecatl.v1.CleanupTeamRequest - 214, // 254: mecatl.v1.HarnessService.ApprovePlan:input_type -> mecatl.v1.ApprovePlanRequest - 228, // 255: mecatl.v1.HarnessService.ConnectWorkspaceServices:input_type -> mecatl.v1.WorkspaceEnrollmentConnectRequest - 229, // 256: mecatl.v1.HarnessService.RetryWorkspaceEnrollment:input_type -> mecatl.v1.WorkspaceEnrollmentControlRequest - 229, // 257: mecatl.v1.HarnessService.CancelWorkspaceEnrollment:input_type -> mecatl.v1.WorkspaceEnrollmentControlRequest - 16, // 258: mecatl.v1.HarnessService.GetCompatibilityInfo:output_type -> mecatl.v1.GetCompatibilityInfoResponse - 21, // 259: mecatl.v1.HarnessService.CreateSession:output_type -> mecatl.v1.CreateSessionResponse - 14, // 260: mecatl.v1.HarnessService.GetServerInfo:output_type -> mecatl.v1.GetServerInfoResponse - 26, // 261: mecatl.v1.HarnessService.GetSession:output_type -> mecatl.v1.GetSessionResponse - 29, // 262: mecatl.v1.HarnessService.GetSessionTranscript:output_type -> mecatl.v1.GetSessionTranscriptResponse - 62, // 263: mecatl.v1.HarnessService.SetMode:output_type -> mecatl.v1.SetModeResponse - 64, // 264: mecatl.v1.HarnessService.CloseSession:output_type -> mecatl.v1.CloseSessionResponse - 66, // 265: mecatl.v1.HarnessService.RenameSession:output_type -> mecatl.v1.RenameSessionResponse - 68, // 266: mecatl.v1.HarnessService.DeleteSession:output_type -> mecatl.v1.DeleteSessionResponse - 227, // 267: mecatl.v1.HarnessService.CompactSession:output_type -> mecatl.v1.CompactSessionResponse - 70, // 268: mecatl.v1.HarnessService.ClearSession:output_type -> mecatl.v1.ClearSessionResponse - 72, // 269: mecatl.v1.HarnessService.ForkSession:output_type -> mecatl.v1.ForkSessionResponse - 78, // 270: mecatl.v1.HarnessService.Converse:output_type -> mecatl.v1.ConverseResponse - 117, // 271: mecatl.v1.HarnessService.ListMcpResources:output_type -> mecatl.v1.ListMcpResourcesResponse - 120, // 272: mecatl.v1.HarnessService.ReadMcpResource:output_type -> mecatl.v1.ReadMcpResourceResponse - 124, // 273: mecatl.v1.HarnessService.ListMcpPrompts:output_type -> mecatl.v1.ListMcpPromptsResponse - 127, // 274: mecatl.v1.HarnessService.GetMcpPrompt:output_type -> mecatl.v1.GetMcpPromptResponse - 131, // 275: mecatl.v1.HarnessService.ListMcpSources:output_type -> mecatl.v1.ListMcpSourcesResponse - 19, // 276: mecatl.v1.HarnessService.ListSessionMcpConnectors:output_type -> mecatl.v1.ListSessionMcpConnectorsResponse - 133, // 277: mecatl.v1.HarnessService.ListToolHiveGroups:output_type -> mecatl.v1.ListToolHiveGroupsResponse - 136, // 278: mecatl.v1.HarnessService.ListAgents:output_type -> mecatl.v1.ListAgentsResponse - 139, // 279: mecatl.v1.HarnessService.ListCommands:output_type -> mecatl.v1.ListCommandsResponse - 142, // 280: mecatl.v1.HarnessService.ListWorktrees:output_type -> mecatl.v1.ListWorktreesResponse - 95, // 281: mecatl.v1.HarnessService.StreamSessionEvents:output_type -> mecatl.v1.Event - 95, // 282: mecatl.v1.HarnessService.StreamSessionLive:output_type -> mecatl.v1.Event - 33, // 283: mecatl.v1.HarnessService.WatchSessionEvents:output_type -> mecatl.v1.WatchSessionEventsResponse - 89, // 284: mecatl.v1.HarnessService.GetMcpAuthorizationPresentation:output_type -> mecatl.v1.GetMcpAuthorizationPresentationResponse - 91, // 285: mecatl.v1.HarnessService.RecheckMcpAuthorization:output_type -> mecatl.v1.RecheckMcpAuthorizationResponse - 93, // 286: mecatl.v1.HarnessService.CancelMcpAuthorization:output_type -> mecatl.v1.CancelMcpAuthorizationResponse - 40, // 287: mecatl.v1.HarnessService.ListSessions:output_type -> mecatl.v1.ListSessionsResponse - 43, // 288: mecatl.v1.HarnessService.GetStorageHealth:output_type -> mecatl.v1.GetStorageHealthResponse - 45, // 289: mecatl.v1.HarnessService.PlanSessionMigration:output_type -> mecatl.v1.SessionMigrationPlan - 59, // 290: mecatl.v1.HarnessService.ApplySessionMigration:output_type -> mecatl.v1.SessionMigrationJob - 59, // 291: mecatl.v1.HarnessService.ResumeSessionMigration:output_type -> mecatl.v1.SessionMigrationJob - 59, // 292: mecatl.v1.HarnessService.CancelSessionMigration:output_type -> mecatl.v1.SessionMigrationJob - 59, // 293: mecatl.v1.HarnessService.GetSessionMigrationJob:output_type -> mecatl.v1.SessionMigrationJob - 54, // 294: mecatl.v1.HarnessService.PlanSessionCleanup:output_type -> mecatl.v1.PlanSessionCleanupResponse - 60, // 295: mecatl.v1.HarnessService.ApplySessionCleanup:output_type -> mecatl.v1.CleanupJob - 60, // 296: mecatl.v1.HarnessService.CancelSessionCleanup:output_type -> mecatl.v1.CleanupJob - 60, // 297: mecatl.v1.HarnessService.GetSessionCleanupJob:output_type -> mecatl.v1.CleanupJob - 145, // 298: mecatl.v1.HarnessService.ListSkills:output_type -> mecatl.v1.ListSkillsResponse - 148, // 299: mecatl.v1.HarnessService.GetSoul:output_type -> mecatl.v1.GetSoulResponse - 153, // 300: mecatl.v1.HarnessService.GetUserModel:output_type -> mecatl.v1.GetUserModelResponse - 160, // 301: mecatl.v1.HarnessService.ReflectSession:output_type -> mecatl.v1.ReflectSessionResponse - 163, // 302: mecatl.v1.HarnessService.GetLearningAttempt:output_type -> mecatl.v1.GetLearningAttemptResponse - 165, // 303: mecatl.v1.HarnessService.ListLearningAttempts:output_type -> mecatl.v1.ListLearningAttemptsResponse - 167, // 304: mecatl.v1.HarnessService.RetryLearningAttempt:output_type -> mecatl.v1.MutateLearningAttemptResponse - 167, // 305: mecatl.v1.HarnessService.AbandonLearningAttempt:output_type -> mecatl.v1.MutateLearningAttemptResponse - 218, // 306: mecatl.v1.HarnessService.GenerateDreamPlan:output_type -> mecatl.v1.GenerateDreamPlanResponse - 220, // 307: mecatl.v1.HarnessService.DecideDreamPlan:output_type -> mecatl.v1.DecideDreamPlanResponse - 173, // 308: mecatl.v1.HarnessService.ListLearningProposals:output_type -> mecatl.v1.ListLearningProposalsResponse - 175, // 309: mecatl.v1.HarnessService.GetLearningProposal:output_type -> mecatl.v1.GetLearningProposalResponse - 177, // 310: mecatl.v1.HarnessService.DecideLearningProposal:output_type -> mecatl.v1.DecideLearningProposalResponse - 179, // 311: mecatl.v1.HarnessService.UndoLearningPromotion:output_type -> mecatl.v1.UndoLearningPromotionResponse - 184, // 312: mecatl.v1.HarnessService.ListLearnedSkills:output_type -> mecatl.v1.ListLearnedSkillsResponse - 186, // 313: mecatl.v1.HarnessService.GetLearnedSkill:output_type -> mecatl.v1.GetLearnedSkillResponse - 188, // 314: mecatl.v1.HarnessService.DiffLearnedSkillVersions:output_type -> mecatl.v1.DiffLearnedSkillVersionsResponse - 190, // 315: mecatl.v1.HarnessService.ActivateLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse - 190, // 316: mecatl.v1.HarnessService.RejectLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse - 190, // 317: mecatl.v1.HarnessService.ArchiveLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse - 190, // 318: mecatl.v1.HarnessService.RollbackLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse - 193, // 319: mecatl.v1.HarnessService.ListSkillChanges:output_type -> mecatl.v1.ListSkillChangesResponse - 157, // 320: mecatl.v1.HarnessService.ListModels:output_type -> mecatl.v1.ListModelsResponse - 195, // 321: mecatl.v1.HarnessService.CreateTeam:output_type -> mecatl.v1.CreateTeamResponse - 198, // 322: mecatl.v1.HarnessService.SpawnTeammate:output_type -> mecatl.v1.SpawnTeammateResponse - 200, // 323: mecatl.v1.HarnessService.SendTeammateMessage:output_type -> mecatl.v1.SendTeammateMessageResponse - 202, // 324: mecatl.v1.HarnessService.CancelTeammate:output_type -> mecatl.v1.CancelTeammateResponse - 204, // 325: mecatl.v1.HarnessService.RunTeam:output_type -> mecatl.v1.TeamEvent - 207, // 326: mecatl.v1.HarnessService.ListTeam:output_type -> mecatl.v1.ListTeamResponse - 213, // 327: mecatl.v1.HarnessService.CleanupTeam:output_type -> mecatl.v1.CleanupTeamResponse - 95, // 328: mecatl.v1.HarnessService.ApprovePlan:output_type -> mecatl.v1.Event - 230, // 329: mecatl.v1.HarnessService.ConnectWorkspaceServices:output_type -> mecatl.v1.WorkspaceEnrollment - 230, // 330: mecatl.v1.HarnessService.RetryWorkspaceEnrollment:output_type -> mecatl.v1.WorkspaceEnrollment - 230, // 331: mecatl.v1.HarnessService.CancelWorkspaceEnrollment:output_type -> mecatl.v1.WorkspaceEnrollment - 258, // [258:332] is the sub-list for method output_type - 184, // [184:258] is the sub-list for method input_type + 132, // 202: mecatl.v1.HarnessService.RefreshMcpSources:input_type -> mecatl.v1.RefreshMcpSourcesRequest + 18, // 203: mecatl.v1.HarnessService.ListSessionMcpConnectors:input_type -> mecatl.v1.ListSessionMcpConnectorsRequest + 134, // 204: mecatl.v1.HarnessService.ListToolHiveGroups:input_type -> mecatl.v1.ListToolHiveGroupsRequest + 137, // 205: mecatl.v1.HarnessService.ListAgents:input_type -> mecatl.v1.ListAgentsRequest + 140, // 206: mecatl.v1.HarnessService.ListCommands:input_type -> mecatl.v1.ListCommandsRequest + 143, // 207: mecatl.v1.HarnessService.ListWorktrees:input_type -> mecatl.v1.ListWorktreesRequest + 30, // 208: mecatl.v1.HarnessService.StreamSessionEvents:input_type -> mecatl.v1.StreamSessionEventsRequest + 31, // 209: mecatl.v1.HarnessService.StreamSessionLive:input_type -> mecatl.v1.StreamSessionLiveRequest + 32, // 210: mecatl.v1.HarnessService.WatchSessionEvents:input_type -> mecatl.v1.WatchSessionEventsRequest + 88, // 211: mecatl.v1.HarnessService.GetMcpAuthorizationPresentation:input_type -> mecatl.v1.GetMcpAuthorizationPresentationRequest + 90, // 212: mecatl.v1.HarnessService.RecheckMcpAuthorization:input_type -> mecatl.v1.RecheckMcpAuthorizationRequest + 92, // 213: mecatl.v1.HarnessService.CancelMcpAuthorization:input_type -> mecatl.v1.CancelMcpAuthorizationRequest + 34, // 214: mecatl.v1.HarnessService.ListSessions:input_type -> mecatl.v1.ListSessionsRequest + 41, // 215: mecatl.v1.HarnessService.GetStorageHealth:input_type -> mecatl.v1.GetStorageHealthRequest + 44, // 216: mecatl.v1.HarnessService.PlanSessionMigration:input_type -> mecatl.v1.PlanSessionMigrationRequest + 46, // 217: mecatl.v1.HarnessService.ApplySessionMigration:input_type -> mecatl.v1.ApplySessionMigrationRequest + 47, // 218: mecatl.v1.HarnessService.ResumeSessionMigration:input_type -> mecatl.v1.ResumeSessionMigrationRequest + 48, // 219: mecatl.v1.HarnessService.CancelSessionMigration:input_type -> mecatl.v1.CancelSessionMigrationRequest + 49, // 220: mecatl.v1.HarnessService.GetSessionMigrationJob:input_type -> mecatl.v1.GetSessionMigrationJobRequest + 53, // 221: mecatl.v1.HarnessService.PlanSessionCleanup:input_type -> mecatl.v1.PlanSessionCleanupRequest + 55, // 222: mecatl.v1.HarnessService.ApplySessionCleanup:input_type -> mecatl.v1.ApplySessionCleanupRequest + 56, // 223: mecatl.v1.HarnessService.CancelSessionCleanup:input_type -> mecatl.v1.CancelSessionCleanupRequest + 57, // 224: mecatl.v1.HarnessService.GetSessionCleanupJob:input_type -> mecatl.v1.GetSessionCleanupJobRequest + 146, // 225: mecatl.v1.HarnessService.ListSkills:input_type -> mecatl.v1.ListSkillsRequest + 149, // 226: mecatl.v1.HarnessService.GetSoul:input_type -> mecatl.v1.GetSoulRequest + 152, // 227: mecatl.v1.HarnessService.GetUserModel:input_type -> mecatl.v1.GetUserModelRequest + 160, // 228: mecatl.v1.HarnessService.ReflectSession:input_type -> mecatl.v1.ReflectSessionRequest + 164, // 229: mecatl.v1.HarnessService.GetLearningAttempt:input_type -> mecatl.v1.GetLearningAttemptRequest + 166, // 230: mecatl.v1.HarnessService.ListLearningAttempts:input_type -> mecatl.v1.ListLearningAttemptsRequest + 168, // 231: mecatl.v1.HarnessService.RetryLearningAttempt:input_type -> mecatl.v1.MutateLearningAttemptRequest + 168, // 232: mecatl.v1.HarnessService.AbandonLearningAttempt:input_type -> mecatl.v1.MutateLearningAttemptRequest + 219, // 233: mecatl.v1.HarnessService.GenerateDreamPlan:input_type -> mecatl.v1.GenerateDreamPlanRequest + 221, // 234: mecatl.v1.HarnessService.DecideDreamPlan:input_type -> mecatl.v1.DecideDreamPlanRequest + 170, // 235: mecatl.v1.HarnessService.ListLearningProposals:input_type -> mecatl.v1.ListLearningProposalsRequest + 176, // 236: mecatl.v1.HarnessService.GetLearningProposal:input_type -> mecatl.v1.GetLearningProposalRequest + 178, // 237: mecatl.v1.HarnessService.DecideLearningProposal:input_type -> mecatl.v1.DecideLearningProposalRequest + 180, // 238: mecatl.v1.HarnessService.UndoLearningPromotion:input_type -> mecatl.v1.UndoLearningPromotionRequest + 185, // 239: mecatl.v1.HarnessService.ListLearnedSkills:input_type -> mecatl.v1.ListLearnedSkillsRequest + 187, // 240: mecatl.v1.HarnessService.GetLearnedSkill:input_type -> mecatl.v1.GetLearnedSkillRequest + 189, // 241: mecatl.v1.HarnessService.DiffLearnedSkillVersions:input_type -> mecatl.v1.DiffLearnedSkillVersionsRequest + 191, // 242: mecatl.v1.HarnessService.ActivateLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest + 191, // 243: mecatl.v1.HarnessService.RejectLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest + 191, // 244: mecatl.v1.HarnessService.ArchiveLearnedSkill:input_type -> mecatl.v1.MutateLearnedSkillRequest + 193, // 245: mecatl.v1.HarnessService.RollbackLearnedSkill:input_type -> mecatl.v1.RollbackLearnedSkillRequest + 194, // 246: mecatl.v1.HarnessService.ListSkillChanges:input_type -> mecatl.v1.ListSkillChangesRequest + 157, // 247: mecatl.v1.HarnessService.ListModels:input_type -> mecatl.v1.ListModelsRequest + 196, // 248: mecatl.v1.HarnessService.CreateTeam:input_type -> mecatl.v1.CreateTeamRequest + 199, // 249: mecatl.v1.HarnessService.SpawnTeammate:input_type -> mecatl.v1.SpawnTeammateRequest + 201, // 250: mecatl.v1.HarnessService.SendTeammateMessage:input_type -> mecatl.v1.SendTeammateMessageRequest + 203, // 251: mecatl.v1.HarnessService.CancelTeammate:input_type -> mecatl.v1.CancelTeammateRequest + 205, // 252: mecatl.v1.HarnessService.RunTeam:input_type -> mecatl.v1.RunTeamRequest + 208, // 253: mecatl.v1.HarnessService.ListTeam:input_type -> mecatl.v1.ListTeamRequest + 214, // 254: mecatl.v1.HarnessService.CleanupTeam:input_type -> mecatl.v1.CleanupTeamRequest + 216, // 255: mecatl.v1.HarnessService.ApprovePlan:input_type -> mecatl.v1.ApprovePlanRequest + 230, // 256: mecatl.v1.HarnessService.ConnectWorkspaceServices:input_type -> mecatl.v1.WorkspaceEnrollmentConnectRequest + 231, // 257: mecatl.v1.HarnessService.RetryWorkspaceEnrollment:input_type -> mecatl.v1.WorkspaceEnrollmentControlRequest + 231, // 258: mecatl.v1.HarnessService.CancelWorkspaceEnrollment:input_type -> mecatl.v1.WorkspaceEnrollmentControlRequest + 16, // 259: mecatl.v1.HarnessService.GetCompatibilityInfo:output_type -> mecatl.v1.GetCompatibilityInfoResponse + 21, // 260: mecatl.v1.HarnessService.CreateSession:output_type -> mecatl.v1.CreateSessionResponse + 14, // 261: mecatl.v1.HarnessService.GetServerInfo:output_type -> mecatl.v1.GetServerInfoResponse + 26, // 262: mecatl.v1.HarnessService.GetSession:output_type -> mecatl.v1.GetSessionResponse + 29, // 263: mecatl.v1.HarnessService.GetSessionTranscript:output_type -> mecatl.v1.GetSessionTranscriptResponse + 62, // 264: mecatl.v1.HarnessService.SetMode:output_type -> mecatl.v1.SetModeResponse + 64, // 265: mecatl.v1.HarnessService.CloseSession:output_type -> mecatl.v1.CloseSessionResponse + 66, // 266: mecatl.v1.HarnessService.RenameSession:output_type -> mecatl.v1.RenameSessionResponse + 68, // 267: mecatl.v1.HarnessService.DeleteSession:output_type -> mecatl.v1.DeleteSessionResponse + 229, // 268: mecatl.v1.HarnessService.CompactSession:output_type -> mecatl.v1.CompactSessionResponse + 70, // 269: mecatl.v1.HarnessService.ClearSession:output_type -> mecatl.v1.ClearSessionResponse + 72, // 270: mecatl.v1.HarnessService.ForkSession:output_type -> mecatl.v1.ForkSessionResponse + 78, // 271: mecatl.v1.HarnessService.Converse:output_type -> mecatl.v1.ConverseResponse + 117, // 272: mecatl.v1.HarnessService.ListMcpResources:output_type -> mecatl.v1.ListMcpResourcesResponse + 120, // 273: mecatl.v1.HarnessService.ReadMcpResource:output_type -> mecatl.v1.ReadMcpResourceResponse + 124, // 274: mecatl.v1.HarnessService.ListMcpPrompts:output_type -> mecatl.v1.ListMcpPromptsResponse + 127, // 275: mecatl.v1.HarnessService.GetMcpPrompt:output_type -> mecatl.v1.GetMcpPromptResponse + 131, // 276: mecatl.v1.HarnessService.ListMcpSources:output_type -> mecatl.v1.ListMcpSourcesResponse + 133, // 277: mecatl.v1.HarnessService.RefreshMcpSources:output_type -> mecatl.v1.RefreshMcpSourcesResponse + 19, // 278: mecatl.v1.HarnessService.ListSessionMcpConnectors:output_type -> mecatl.v1.ListSessionMcpConnectorsResponse + 135, // 279: mecatl.v1.HarnessService.ListToolHiveGroups:output_type -> mecatl.v1.ListToolHiveGroupsResponse + 138, // 280: mecatl.v1.HarnessService.ListAgents:output_type -> mecatl.v1.ListAgentsResponse + 141, // 281: mecatl.v1.HarnessService.ListCommands:output_type -> mecatl.v1.ListCommandsResponse + 144, // 282: mecatl.v1.HarnessService.ListWorktrees:output_type -> mecatl.v1.ListWorktreesResponse + 95, // 283: mecatl.v1.HarnessService.StreamSessionEvents:output_type -> mecatl.v1.Event + 95, // 284: mecatl.v1.HarnessService.StreamSessionLive:output_type -> mecatl.v1.Event + 33, // 285: mecatl.v1.HarnessService.WatchSessionEvents:output_type -> mecatl.v1.WatchSessionEventsResponse + 89, // 286: mecatl.v1.HarnessService.GetMcpAuthorizationPresentation:output_type -> mecatl.v1.GetMcpAuthorizationPresentationResponse + 91, // 287: mecatl.v1.HarnessService.RecheckMcpAuthorization:output_type -> mecatl.v1.RecheckMcpAuthorizationResponse + 93, // 288: mecatl.v1.HarnessService.CancelMcpAuthorization:output_type -> mecatl.v1.CancelMcpAuthorizationResponse + 40, // 289: mecatl.v1.HarnessService.ListSessions:output_type -> mecatl.v1.ListSessionsResponse + 43, // 290: mecatl.v1.HarnessService.GetStorageHealth:output_type -> mecatl.v1.GetStorageHealthResponse + 45, // 291: mecatl.v1.HarnessService.PlanSessionMigration:output_type -> mecatl.v1.SessionMigrationPlan + 59, // 292: mecatl.v1.HarnessService.ApplySessionMigration:output_type -> mecatl.v1.SessionMigrationJob + 59, // 293: mecatl.v1.HarnessService.ResumeSessionMigration:output_type -> mecatl.v1.SessionMigrationJob + 59, // 294: mecatl.v1.HarnessService.CancelSessionMigration:output_type -> mecatl.v1.SessionMigrationJob + 59, // 295: mecatl.v1.HarnessService.GetSessionMigrationJob:output_type -> mecatl.v1.SessionMigrationJob + 54, // 296: mecatl.v1.HarnessService.PlanSessionCleanup:output_type -> mecatl.v1.PlanSessionCleanupResponse + 60, // 297: mecatl.v1.HarnessService.ApplySessionCleanup:output_type -> mecatl.v1.CleanupJob + 60, // 298: mecatl.v1.HarnessService.CancelSessionCleanup:output_type -> mecatl.v1.CleanupJob + 60, // 299: mecatl.v1.HarnessService.GetSessionCleanupJob:output_type -> mecatl.v1.CleanupJob + 147, // 300: mecatl.v1.HarnessService.ListSkills:output_type -> mecatl.v1.ListSkillsResponse + 150, // 301: mecatl.v1.HarnessService.GetSoul:output_type -> mecatl.v1.GetSoulResponse + 155, // 302: mecatl.v1.HarnessService.GetUserModel:output_type -> mecatl.v1.GetUserModelResponse + 162, // 303: mecatl.v1.HarnessService.ReflectSession:output_type -> mecatl.v1.ReflectSessionResponse + 165, // 304: mecatl.v1.HarnessService.GetLearningAttempt:output_type -> mecatl.v1.GetLearningAttemptResponse + 167, // 305: mecatl.v1.HarnessService.ListLearningAttempts:output_type -> mecatl.v1.ListLearningAttemptsResponse + 169, // 306: mecatl.v1.HarnessService.RetryLearningAttempt:output_type -> mecatl.v1.MutateLearningAttemptResponse + 169, // 307: mecatl.v1.HarnessService.AbandonLearningAttempt:output_type -> mecatl.v1.MutateLearningAttemptResponse + 220, // 308: mecatl.v1.HarnessService.GenerateDreamPlan:output_type -> mecatl.v1.GenerateDreamPlanResponse + 222, // 309: mecatl.v1.HarnessService.DecideDreamPlan:output_type -> mecatl.v1.DecideDreamPlanResponse + 175, // 310: mecatl.v1.HarnessService.ListLearningProposals:output_type -> mecatl.v1.ListLearningProposalsResponse + 177, // 311: mecatl.v1.HarnessService.GetLearningProposal:output_type -> mecatl.v1.GetLearningProposalResponse + 179, // 312: mecatl.v1.HarnessService.DecideLearningProposal:output_type -> mecatl.v1.DecideLearningProposalResponse + 181, // 313: mecatl.v1.HarnessService.UndoLearningPromotion:output_type -> mecatl.v1.UndoLearningPromotionResponse + 186, // 314: mecatl.v1.HarnessService.ListLearnedSkills:output_type -> mecatl.v1.ListLearnedSkillsResponse + 188, // 315: mecatl.v1.HarnessService.GetLearnedSkill:output_type -> mecatl.v1.GetLearnedSkillResponse + 190, // 316: mecatl.v1.HarnessService.DiffLearnedSkillVersions:output_type -> mecatl.v1.DiffLearnedSkillVersionsResponse + 192, // 317: mecatl.v1.HarnessService.ActivateLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse + 192, // 318: mecatl.v1.HarnessService.RejectLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse + 192, // 319: mecatl.v1.HarnessService.ArchiveLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse + 192, // 320: mecatl.v1.HarnessService.RollbackLearnedSkill:output_type -> mecatl.v1.MutateLearnedSkillResponse + 195, // 321: mecatl.v1.HarnessService.ListSkillChanges:output_type -> mecatl.v1.ListSkillChangesResponse + 159, // 322: mecatl.v1.HarnessService.ListModels:output_type -> mecatl.v1.ListModelsResponse + 197, // 323: mecatl.v1.HarnessService.CreateTeam:output_type -> mecatl.v1.CreateTeamResponse + 200, // 324: mecatl.v1.HarnessService.SpawnTeammate:output_type -> mecatl.v1.SpawnTeammateResponse + 202, // 325: mecatl.v1.HarnessService.SendTeammateMessage:output_type -> mecatl.v1.SendTeammateMessageResponse + 204, // 326: mecatl.v1.HarnessService.CancelTeammate:output_type -> mecatl.v1.CancelTeammateResponse + 206, // 327: mecatl.v1.HarnessService.RunTeam:output_type -> mecatl.v1.TeamEvent + 209, // 328: mecatl.v1.HarnessService.ListTeam:output_type -> mecatl.v1.ListTeamResponse + 215, // 329: mecatl.v1.HarnessService.CleanupTeam:output_type -> mecatl.v1.CleanupTeamResponse + 95, // 330: mecatl.v1.HarnessService.ApprovePlan:output_type -> mecatl.v1.Event + 232, // 331: mecatl.v1.HarnessService.ConnectWorkspaceServices:output_type -> mecatl.v1.WorkspaceEnrollment + 232, // 332: mecatl.v1.HarnessService.RetryWorkspaceEnrollment:output_type -> mecatl.v1.WorkspaceEnrollment + 232, // 333: mecatl.v1.HarnessService.CancelWorkspaceEnrollment:output_type -> mecatl.v1.WorkspaceEnrollment + 259, // [259:334] is the sub-list for method output_type + 184, // [184:259] is the sub-list for method input_type 184, // [184:184] is the sub-list for extension type_name 184, // [184:184] is the sub-list for extension extendee 0, // [0:184] is the sub-list for field type_name @@ -21143,7 +21306,7 @@ func file_mecatl_v1_harness_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_mecatl_v1_harness_proto_rawDesc), len(file_mecatl_v1_harness_proto_rawDesc)), NumEnums: 10, - NumMessages: 229, + NumMessages: 231, NumExtensions: 0, NumServices: 1, }, diff --git a/contracts/gen/go/mecatl/v1/harness_grpc.pb.go b/contracts/gen/go/mecatl/v1/harness_grpc.pb.go index eee3d099eb..d9d1f7e7ff 100644 --- a/contracts/gen/go/mecatl/v1/harness_grpc.pb.go +++ b/contracts/gen/go/mecatl/v1/harness_grpc.pb.go @@ -60,6 +60,7 @@ const ( HarnessService_ListMcpPrompts_FullMethodName = "/mecatl.v1.HarnessService/ListMcpPrompts" HarnessService_GetMcpPrompt_FullMethodName = "/mecatl.v1.HarnessService/GetMcpPrompt" HarnessService_ListMcpSources_FullMethodName = "/mecatl.v1.HarnessService/ListMcpSources" + HarnessService_RefreshMcpSources_FullMethodName = "/mecatl.v1.HarnessService/RefreshMcpSources" HarnessService_ListSessionMcpConnectors_FullMethodName = "/mecatl.v1.HarnessService/ListSessionMcpConnectors" HarnessService_ListToolHiveGroups_FullMethodName = "/mecatl.v1.HarnessService/ListToolHiveGroups" HarnessService_ListAgents_FullMethodName = "/mecatl.v1.HarnessService/ListAgents" @@ -197,11 +198,12 @@ type HarnessServiceClient interface { // GetMcpPrompt expands a named prompt with the given arguments on the named // server and returns the rendered messages. GetMcpPrompt(ctx context.Context, in *GetMcpPromptRequest, opts ...grpc.CallOption) (*GetMcpPromptResponse, error) - // ListMcpSources returns the resolved MCP source inventory snapshot: each - // configured source (static / ToolHive), the servers it contributed, and any - // diagnostics it raised. Derived from the resolution snapshot taken at - // startup; it performs no live discovery. + // ListMcpSources returns the cached published/pre-shadow source inventory and + // reconciler status. It performs no independent upstream probe. ListMcpSources(ctx context.Context, in *ListMcpSourcesRequest, opts ...grpc.CallOption) (*ListMcpSourcesResponse, error) + // RefreshMcpSources explicitly reconciles direct MCP sources for an owned + // eligible ordinary-root session and unions newly active direct names. + RefreshMcpSources(ctx context.Context, in *RefreshMcpSourcesRequest, opts ...grpc.CallOption) (*RefreshMcpSourcesResponse, error) // ListSessionMcpConnectors inspects the owned session's broker-local catalogue. // This read neither probes upstreams nor progresses enrollment. ListSessionMcpConnectors(ctx context.Context, in *ListSessionMcpConnectorsRequest, opts ...grpc.CallOption) (*ListSessionMcpConnectorsResponse, error) @@ -702,6 +704,16 @@ func (c *harnessServiceClient) ListMcpSources(ctx context.Context, in *ListMcpSo return out, nil } +func (c *harnessServiceClient) RefreshMcpSources(ctx context.Context, in *RefreshMcpSourcesRequest, opts ...grpc.CallOption) (*RefreshMcpSourcesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RefreshMcpSourcesResponse) + err := c.cc.Invoke(ctx, HarnessService_RefreshMcpSources_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *harnessServiceClient) ListSessionMcpConnectors(ctx context.Context, in *ListSessionMcpConnectorsRequest, opts ...grpc.CallOption) (*ListSessionMcpConnectorsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListSessionMcpConnectorsResponse) @@ -1392,11 +1404,12 @@ type HarnessServiceServer interface { // GetMcpPrompt expands a named prompt with the given arguments on the named // server and returns the rendered messages. GetMcpPrompt(context.Context, *GetMcpPromptRequest) (*GetMcpPromptResponse, error) - // ListMcpSources returns the resolved MCP source inventory snapshot: each - // configured source (static / ToolHive), the servers it contributed, and any - // diagnostics it raised. Derived from the resolution snapshot taken at - // startup; it performs no live discovery. + // ListMcpSources returns the cached published/pre-shadow source inventory and + // reconciler status. It performs no independent upstream probe. ListMcpSources(context.Context, *ListMcpSourcesRequest) (*ListMcpSourcesResponse, error) + // RefreshMcpSources explicitly reconciles direct MCP sources for an owned + // eligible ordinary-root session and unions newly active direct names. + RefreshMcpSources(context.Context, *RefreshMcpSourcesRequest) (*RefreshMcpSourcesResponse, error) // ListSessionMcpConnectors inspects the owned session's broker-local catalogue. // This read neither probes upstreams nor progresses enrollment. ListSessionMcpConnectors(context.Context, *ListSessionMcpConnectorsRequest) (*ListSessionMcpConnectorsResponse, error) @@ -1768,6 +1781,9 @@ func (UnimplementedHarnessServiceServer) GetMcpPrompt(context.Context, *GetMcpPr func (UnimplementedHarnessServiceServer) ListMcpSources(context.Context, *ListMcpSourcesRequest) (*ListMcpSourcesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMcpSources not implemented") } +func (UnimplementedHarnessServiceServer) RefreshMcpSources(context.Context, *RefreshMcpSourcesRequest) (*RefreshMcpSourcesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RefreshMcpSources not implemented") +} func (UnimplementedHarnessServiceServer) ListSessionMcpConnectors(context.Context, *ListSessionMcpConnectorsRequest) (*ListSessionMcpConnectorsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListSessionMcpConnectors not implemented") } @@ -2270,6 +2286,24 @@ func _HarnessService_ListMcpSources_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _HarnessService_RefreshMcpSources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RefreshMcpSourcesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HarnessServiceServer).RefreshMcpSources(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: HarnessService_RefreshMcpSources_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HarnessServiceServer).RefreshMcpSources(ctx, req.(*RefreshMcpSourcesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _HarnessService_ListSessionMcpConnectors_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListSessionMcpConnectorsRequest) if err := dec(in); err != nil { @@ -3296,6 +3330,10 @@ var HarnessService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListMcpSources", Handler: _HarnessService_ListMcpSources_Handler, }, + { + MethodName: "RefreshMcpSources", + Handler: _HarnessService_RefreshMcpSources_Handler, + }, { MethodName: "ListSessionMcpConnectors", Handler: _HarnessService_ListSessionMcpConnectors_Handler, diff --git a/contracts/proto/mecatl/v1/harness.proto b/contracts/proto/mecatl/v1/harness.proto index b6cf16c9a8..88bc075c99 100644 --- a/contracts/proto/mecatl/v1/harness.proto +++ b/contracts/proto/mecatl/v1/harness.proto @@ -120,12 +120,14 @@ service HarnessService { // server and returns the rendered messages. rpc GetMcpPrompt(GetMcpPromptRequest) returns (GetMcpPromptResponse); - // ListMcpSources returns the resolved MCP source inventory snapshot: each - // configured source (static / ToolHive), the servers it contributed, and any - // diagnostics it raised. Derived from the resolution snapshot taken at - // startup; it performs no live discovery. + // ListMcpSources returns the cached published/pre-shadow source inventory and + // reconciler status. It performs no independent upstream probe. rpc ListMcpSources(ListMcpSourcesRequest) returns (ListMcpSourcesResponse); + // RefreshMcpSources explicitly reconciles direct MCP sources for an owned + // eligible ordinary-root session and unions newly active direct names. + rpc RefreshMcpSources(RefreshMcpSourcesRequest) returns (RefreshMcpSourcesResponse); + // ListSessionMcpConnectors inspects the owned session's broker-local catalogue. // This read neither probes upstreams nor progresses enrollment. rpc ListSessionMcpConnectors(ListSessionMcpConnectorsRequest) returns (ListSessionMcpConnectorsResponse); @@ -795,6 +797,9 @@ message ServerCapabilities { // mcp_connector_status requires a wired broker inspector, enforced ownership // and a verified caller. It does not enable direct MCP resources or prompts. bool mcp_connector_status = 29; + // mcp_refresh is true when direct/global MCP source reconciliation is wired. + // It is mutually exclusive with workspace_enrollment in a valid deployment. + bool mcp_refresh = 30; } // ListSessionMcpConnectorsRequest names an owned, broker-bound session. @@ -2769,6 +2774,24 @@ message ListMcpSourcesRequest {} message ListMcpSourcesResponse { // sources are the (possibly empty) resolved sources. repeated McpSource sources = 1; + // revision is the current published direct-runtime revision. + uint64 revision = 2; + // stale is true when source or candidate degradation retained an older runtime. + bool stale = 3; + // reconciling is true while the shared reconciler is processing a cycle. + bool reconciling = 4; +} + +// RefreshMcpSourcesRequest names the owned session whose direct-name authority +// may be widened after reconciliation. +message RefreshMcpSourcesRequest { + string session_id = 1 [(buf.validate.field).string.min_len = 1]; +} + +// RefreshMcpSourcesResponse identifies the request-pinned runtime snapshot. +message RefreshMcpSourcesResponse { + uint64 revision = 1; + bool changed = 2; } // ListToolHiveGroupsRequest requests the distinct ToolHive groups in the diff --git a/docs/adr/0027-cloud-native.md b/docs/adr/0027-cloud-native.md index 06129fcdd9..7e1144dd46 100644 --- a/docs/adr/0027-cloud-native.md +++ b/docs/adr/0027-cloud-native.md @@ -783,6 +783,14 @@ to durable proposal state; row 30 records that materialization accounting and ev pre-admission operation reset by design. Cancellation or close before admission leaves no queue, singleflight, receipt, reservation, provider, repository, or proposal state. +**Direct MCP reconciliation re-audit (ADR 0345).** List 1 row 64 inventories the +Build-owned worker, timer, coalescing state, source LKG/status, immutable current +and retiring runtimes, revision-tagged caches, and run/operation pins. Explicit +refresh adds no outlives-a-call resource: it borrows the existing run-entry lock, +mutation lease, and guarded SessionStore save. The exact-name authority union is +persisted in the existing session snapshot; runtime revisions and cached source +status reset and reconstruct from configured sources on restart. + ## List 1: resource inventory Every resource the harness allocates whose lifecycle outlives a single tool call, diff --git a/docs/adr/README.md b/docs/adr/README.md index 6802a74cf9..105ae4249e 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -192,7 +192,7 @@ Documentation/citation conventions are in [`docs/design/README.md`](../design/RE ### MCP - [0056 — MCP client reconnect](./0056-mcp-client-reconnect.md) -- [0057 — MCP server notifications](./0057-mcp-server-notifications.md) *(deferred “no live catalog mutation” decision proposed to be superseded by 0345; notification transport, bounded lazy-list, reconnect, and teardown decisions retained)* +- [0057 — MCP server notifications](./0057-mcp-server-notifications.md) *(notification transport, bounded lazy-list, reconnect, and teardown decisions retained; 0345 supersedes only the deferred “no live catalog mutation” decision)* - [0345 — Reconcile stale direct MCP source snapshots](./0345-mcp-source-reconciliation.md) *(proposed; preserves exact-name authority and supersedes 0057 only for its deferred “no live catalog mutation” decision)* - [0063 — MCP structured results: fail-closed + CallMcpWithQuery](./0063-mcp-structured-failclosed-callmcpwithquery.md) - [0078 — MCP typed tool results](./0078-mcp-typed-tool-results.md) diff --git a/docs/architecture.md b/docs/architecture.md index 5cbb9f3c46..593c14ffc1 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -199,7 +199,18 @@ session's authenticated membership, descriptions, schemas, and read-only hints. omitted by live discovery disappears; an undeclared live tool appears. The resulting catalogue is frozen for the session, so later runs and token refreshes do not rediscover it. Initial enrollment performs a fresh discovery; an explicit owner-controlled refresh may perform the same whole-bundle discovery after a completed turn or after broker -process loss. A failure admits no mixed or partial catalogue. In a broker-only +process loss. A failure admits no mixed or partial catalogue. + +Direct/global MCP uses a separate Build-owned reconciler. ToolHive-only bounded +polling, current-runtime list notifications, and explicit refresh build complete +immutable runtime candidates and publish one revision atomically. Root runs, +direct teams, and resource/prompt operations pin one revision. Automatic cycles +update availability without widening durable authority; an explicit owned-session +refresh stable-unions missing active direct names. `ListMcpSources` reads cached +published/pre-shadow inventory and revision, stale, and reconciling status without +probing. + +In a broker-only session with eligible frozen tools, `CallMcpWithQuery` is attachment-bound: it invokes the same frozen route and authorization transaction, applies bounded in-memory jq before normal result rendering, and never opens a direct upstream connection or exposes the raw successful diff --git a/docs/architecture/extensibility.md b/docs/architecture/extensibility.md index 300b6f2e2a..d5e1c24d55 100644 --- a/docs/architecture/extensibility.md +++ b/docs/architecture/extensibility.md @@ -54,9 +54,23 @@ and the operation is never replayed automatically. See [ADR 0223](../adr/0223-mcp-sdk-transport-error-semantics.md), and [ADR 0309](../adr/0309-mcp-ambiguous-closed-idle-post.md). The client also holds the **standalone SSE GET stream** open per connected server, so server-initiated -`notifications/{tools,prompts,resources}/list_changed` invalidate the cached -snapshots (lazily re-listed on the next read); live catalog refresh is -deferred to a later phase — see [ADR 0057](../adr/0057-mcp-server-notifications.md). +`notifications/{tools,prompts,resources}/list_changed` enter the same serialized, +bounded reconciler as explicit refresh and ToolHive-only jittered polling. The +reconciler retains source last-known-good state, builds complete immutable +candidates, and atomically publishes one runtime revision. Root operations pin +that revision; displaced runtimes close after their pins drain. See +[ADR 0057](../adr/0057-mcp-server-notifications.md) and +[ADR 0345](../adr/0345-mcp-source-reconciliation.md). + +Automatic reconciliation changes current availability but never widens durable +session authority. `Service.RefreshMcpSources` owner-checks an eligible idle or +quiescent completed ordinary root, requests shared reconciliation, and +stable-unions only missing active direct names. A no-op takes no mutation lease +and performs no save. A widening refresh saves one detached candidate and +confirms an ambiguous save by bounded authoritative reload while the run-entry +and mutation exclusions remain held. `ListMcpSources` reports the cached +published/pre-shadow inventory, revision, stale state, and active reconciliation +without probing a source. A dedicated debug session can borrow only direct tools from explicitly named, already connected server-global MCP servers. It persists the names and the exact initial tool-name diff --git a/docs/design/IMPLEMENTATION-NOTES.md b/docs/design/IMPLEMENTATION-NOTES.md index 4bc791425a..c2944b3046 100644 --- a/docs/design/IMPLEMENTATION-NOTES.md +++ b/docs/design/IMPLEMENTATION-NOTES.md @@ -6018,6 +6018,20 @@ Build shutdown first drains Service operations, then rejects new reconciler wait cancels and joins the worker, and closes all remaining runtime managers. Caller cancellation only abandons that caller's reconciliation wait. +`server.Service.RefreshMcpSources` is the explicit direct control over that shared +reconciler. It owner-preflights before reconciliation, then takes `runEntryMu` and +admits only quiescent idle or completed ordinary roots with no broker binding. +The request uses the returned candidate's exact revision and active direct tool +names even if a successor publishes before delivery. Existing names are a zero-write +no-op with no mutation lease. Additions trigger a fresh authoritative load under +the real mutation lease, one `Session.GrantToolAuthority` stable union, and at most +one cancel-detached bounded save. A save error is confirmed by a bounded detached +reload under the same exclusion: exact candidate succeeds, exact old state fails, +and mismatch or unavailable reload is uncertain and fails closed. Completed state +is never reopened. `MCPSourceStatus` projects the reconciler's cached +published/pre-shadow inventory, revision, stale, and reconciling values; list calls +never consult a source. + **Server-global MCP on every session (bug #3 fix, `sessionEngineFactory`):** the per-session catalog mounts the SERVER-GLOBAL MCP tools (`cfg.MCPServers` + ToolHive — the same tools the build-time `buildCatalog`→`connectMCP`+`assembleCatalog` path mounts on the main engine), NOT just core + client diff --git a/internal/adapter/server/classification.go b/internal/adapter/server/classification.go index 4a00f79331..764fc84e9f 100644 --- a/internal/adapter/server/classification.go +++ b/internal/adapter/server/classification.go @@ -310,6 +310,7 @@ var serviceAccessTable = map[string]ClassificationEntry{ "ConnectWorkspaceServices": {KindCallerOwned, "authorizes and locks the owned pre-prompt session before beginning or observing its broker enrollment"}, "RetryWorkspaceEnrollment": {KindCallerOwned, "authorizes and locks the owned pre-prompt session before replacing the exact enrollment correlation"}, "CancelWorkspaceEnrollment": {KindCallerOwned, "authorizes and locks the owned pre-prompt session before cancelling the exact enrollment correlation"}, + "RefreshMcpSources": {KindCallerOwned, "owner preflight precedes shared reconciliation; run-entry and mutation lease guard any exact-name authority union"}, // --- caller-owned: schedules --- "CreateSchedule": {KindCallerOwned, "the schedule manager binds the verified context principal as owner atomically with visibility"}, @@ -355,7 +356,7 @@ var serviceAccessTable = map[string]ClassificationEntry{ "ReadMcpResource": {KindSharedInfrastructure, "reads a resource off a process-wide MCP server registration, not a caller-owned record"}, "ListMcpPrompts": {KindSharedInfrastructure, "reads prompt snapshots off a process-wide MCP server registration"}, "GetMcpPrompt": {KindSharedInfrastructure, "expands a prompt on a process-wide MCP server registration"}, - "ListMcpSources": {KindSharedInfrastructure, "the deployment-wide MCP source inventory, identical for every caller"}, + "ListMcpSources": {KindSharedInfrastructure, "the cached deployment-wide MCP source inventory, identical for every caller and never an independent probe"}, "ListToolHiveGroups": {KindSharedInfrastructure, "derives group names from the same deployment-wide MCP source inventory as ListMcpSources"}, "ListAgents": {KindSharedInfrastructure, "the deployment's configured agent-definition catalog, identical for every caller"}, "ListSkills": {KindSharedInfrastructure, "the deployment's configured skill catalog, identical for every caller"}, diff --git a/internal/adapter/server/grpc.go b/internal/adapter/server/grpc.go index 9cea4af91f..8f944a34d6 100644 --- a/internal/adapter/server/grpc.go +++ b/internal/adapter/server/grpc.go @@ -5,6 +5,7 @@ package server import ( "context" "errors" + "fmt" "io" "strings" "sync" @@ -1135,12 +1136,24 @@ func (h *HarnessServer) GetCompatibilityInfo(ctx context.Context, _ *mecatlv1.Ge // ListMcpSources returns the resolved MCP source inventory snapshot. func (h *HarnessServer) ListMcpSources(ctx context.Context, _ *mecatlv1.ListMcpSourcesRequest) (*mecatlv1.ListMcpSourcesResponse, error) { - infos := h.svc.ListMcpSources(ctx) - out := make([]*mecatlv1.McpSource, 0, len(infos)) - for _, s := range infos { + cached := h.svc.ListMcpSources(ctx) + out := make([]*mecatlv1.McpSource, 0, len(cached.Sources)) + for _, s := range cached.Sources { out = append(out, toProtoMcpSource(s)) } - return &mecatlv1.ListMcpSourcesResponse{Sources: out}, nil + return &mecatlv1.ListMcpSourcesResponse{Sources: out, Revision: cached.Revision, Stale: cached.Stale, Reconciling: cached.Reconciling}, nil +} + +// RefreshMcpSources reconciles direct MCP and grants additions to an eligible owned root. +func (h *HarnessServer) RefreshMcpSources(ctx context.Context, req *mecatlv1.RefreshMcpSourcesRequest) (*mecatlv1.RefreshMcpSourcesResponse, error) { + if req == nil || req.GetSessionId() == "" { + return nil, toStatus(fmt.Errorf("%w: session_id is required", ErrInvalidArgument)) + } + result, err := h.svc.RefreshMcpSources(ctx, session.SessionID(req.GetSessionId())) + if err != nil { + return nil, toStatus(err) + } + return &mecatlv1.RefreshMcpSourcesResponse{Revision: result.Revision, Changed: result.Changed}, nil } // ListToolHiveGroups returns the distinct, non-empty ToolHive groups derived diff --git a/internal/adapter/server/http.go b/internal/adapter/server/http.go index ade426bc34..6c4bc89716 100644 --- a/internal/adapter/server/http.go +++ b/internal/adapter/server/http.go @@ -73,6 +73,7 @@ func NewHTTPHandler(svc *Service) *HTTPHandler { {"POST /v1/sessions/{id}/rename", h.renameSession}, {"POST /v1/sessions/{id}/delete", h.deleteSession}, {"POST /v1/sessions/{id}/compact", h.compactSession}, + {"POST /v1/sessions/{id}/mcp-refresh", h.refreshMcpSources}, {"GET /v1/sessions/{id}/mcp-authorizations/{authorization_id}/presentation", h.mcpAuthorizationPresentation}, {"POST /v1/sessions/{id}/mcp-authorizations/{authorization_id}/recheck", h.recheckMCPAuthorization}, {"POST /v1/sessions/{id}/mcp-authorizations/{authorization_id}/cancel", h.cancelMCPAuthorization}, @@ -358,6 +359,7 @@ func resolvedModelToJSON(rm ResolvedModel) *resolvedModelJSON { // surfaces cannot drift. type serverCapabilitiesJSON struct { MCPConnectorStatus bool `json:"mcp_connector_status"` + MCPRefresh bool `json:"mcp_refresh"` MCP bool `json:"mcp"` SlashCommands bool `json:"slash_commands"` Memory bool `json:"memory"` @@ -388,6 +390,7 @@ func capabilitiesJSON(c *mecatlv1.ServerCapabilities) *serverCapabilitiesJSON { } return &serverCapabilitiesJSON{ MCPConnectorStatus: c.GetMcpConnectorStatus(), + MCPRefresh: c.GetMcpRefresh(), MCP: c.GetMcp(), SlashCommands: c.GetSlashCommands(), Memory: c.GetMemory(), @@ -1420,6 +1423,26 @@ func (h *HTTPHandler) compactSession(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, &mecatlv1.CompactSessionResponse{Compacted: result.Changed}) } +// refreshMcpSources handles bodyless POST /v1/sessions/{id}/mcp-refresh. +func (h *HTTPHandler) refreshMcpSources(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + if id == "" { + writeError(w, http.StatusBadRequest, "session_id is required") + return + } + body, err := io.ReadAll(io.LimitReader(r.Body, 2)) + if err != nil || len(body) != 0 { + writeError(w, http.StatusBadRequest, "request body must be empty") + return + } + result, err := h.svc.RefreshMcpSources(r.Context(), session.SessionID(id)) + if err != nil { + writeServiceError(w, err) + return + } + writeJSON(w, http.StatusOK, &mecatlv1.RefreshMcpSourcesResponse{Revision: result.Revision, Changed: result.Changed}) +} + // cancelBody is the OPTIONAL JSON body of POST /v1/sessions/{id}/cancel. // // The endpoint predates it and must keep accepting an empty body, so decoding is @@ -2122,12 +2145,12 @@ func (h *HTTPHandler) listSessionMcpConnectors(w http.ResponseWriter, r *http.Re // listMcpSources handles GET /v1/mcp/sources. func (h *HTTPHandler) listMcpSources(w http.ResponseWriter, r *http.Request) { - infos := h.svc.ListMcpSources(r.Context()) - out := make([]*mecatlv1.McpSource, 0, len(infos)) - for _, s := range infos { + cached := h.svc.ListMcpSources(r.Context()) + out := make([]*mecatlv1.McpSource, 0, len(cached.Sources)) + for _, s := range cached.Sources { out = append(out, toProtoMcpSource(s)) } - writeJSON(w, http.StatusOK, &mecatlv1.ListMcpSourcesResponse{Sources: out}) + writeJSON(w, http.StatusOK, &mecatlv1.ListMcpSourcesResponse{Sources: out, Revision: cached.Revision, Stale: cached.Stale, Reconciling: cached.Reconciling}) } // listToolHiveGroups handles GET /v1/mcp/toolhive/groups. diff --git a/internal/adapter/server/mcp_refresh.go b/internal/adapter/server/mcp_refresh.go new file mode 100644 index 0000000000..b7a2584ce7 --- /dev/null +++ b/internal/adapter/server/mcp_refresh.go @@ -0,0 +1,202 @@ +package server + +import ( + "context" + "fmt" + "reflect" + "time" + + "github.com/stacklok/mecatl/engine/adapter/sessnap" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/mcp/source" +) + +const ( + maxMCPRefreshGrantNames = 1_024 + maxMCPHistoricalGrantedNames = 16_384 + mcpRefreshSaveTimeout = 5 * time.Second + mcpRefreshConfirmTimeout = 5 * time.Second +) + +// MCPRefreshSnapshot is the immutable direct-runtime snapshot considered by one +// explicit refresh request. ToolNames are active direct names only. +type MCPRefreshSnapshot struct { + Revision uint64 + Changed bool + ToolNames []string +} + +// MCPSourceStatus is the reconciler's cached public status. Sources are the +// published/pre-shadow inventory and are never populated by a status-time probe. +type MCPSourceStatus struct { + Sources []source.SourceInfo + Revision uint64 + Stale bool + Reconciling bool +} + +// MCPRefreshResult reports the exact runtime revision considered by this +// request and whether that cycle published a runtime or added authority. +type MCPRefreshResult struct { + Revision uint64 + Changed bool +} + +// RefreshMcpSources reconciles direct MCP sources and stable-unions missing +// active direct names into one eligible owner-controlled ordinary root. +// +//nolint:gocyclo // the ordered ownership, lifecycle, lease, cancellation, save, and confirmation gates are the contract. +func (s *Service) RefreshMcpSources(ctx context.Context, id session.SessionID) (MCPRefreshResult, error) { + if s.cfg.MCPRefresh == nil { + return MCPRefreshResult{}, fmt.Errorf("%w: direct MCP refresh is unavailable", ErrFailedPrecondition) + } + absent, err := s.managementOwnershipPreflight(ctx, id, false) + if err != nil { + return MCPRefreshResult{}, err + } + if absent { + return MCPRefreshResult{}, fmt.Errorf("%w: %q", ErrNotFound, id) + } + + snapshot, reconcileErr := s.cfg.MCPRefresh(ctx) + unlock := s.runEntryMu.lock(id) + defer unlock() + if reconcileErr != nil { + return MCPRefreshResult{}, reconcileErr + } + result := MCPRefreshResult{Revision: snapshot.Revision, Changed: snapshot.Changed} + if len(snapshot.ToolNames) > maxMCPRefreshGrantNames { + return MCPRefreshResult{}, fmt.Errorf("%w: direct MCP grant count exceeds limit", ErrFailedPrecondition) + } + names := append([]string(nil), snapshot.ToolNames...) + + current, err := s.mcpRefreshTarget(ctx, id) + if err != nil { + return MCPRefreshResult{}, err + } + additions, err := mcpRefreshAdditions(current, names) + if err != nil { + return MCPRefreshResult{}, err + } + if len(additions) == 0 { + return result, nil + } + + release, err := s.acquireMutationLease(ctx, id) + if err != nil { + return MCPRefreshResult{}, err + } + defer release() + + old, err := s.mcpRefreshTarget(ctx, id) + if err != nil { + return MCPRefreshResult{}, err + } + additions, err = mcpRefreshAdditions(old, names) + if err != nil { + return MCPRefreshResult{}, err + } + if len(additions) == 0 { + return result, nil + } + if err := ctx.Err(); err != nil { + return MCPRefreshResult{}, err + } + + oldSnapshot, err := sessnap.Of(old) + if err != nil { + return MCPRefreshResult{}, fmt.Errorf("%w: snapshot direct MCP authority candidate: %v", ErrInternal, err) + } + candidate, err := oldSnapshot.Restore() + if err != nil { + return MCPRefreshResult{}, fmt.Errorf("%w: restore direct MCP authority candidate: %v", ErrInternal, err) + } + if err := candidate.GrantToolAuthority(additions); err != nil { + return MCPRefreshResult{}, fmt.Errorf("%w: grant direct MCP authority: %v", ErrFailedPrecondition, err) + } + result.Changed = true + + // The final caller-cancellation check above is the save-start boundary. Once + // Save begins, it and any ambiguous-commit confirmation are detached and + // bounded while the same run-entry and mutation exclusions remain held. + saveParent, saveCancel := context.WithTimeout(context.WithoutCancel(ctx), mcpRefreshSaveTimeout) + saveCtx, stopSave, leaseHeld := s.mutationLeaseContext(saveParent, id) + saveErr := s.saveSession(saveCtx, candidate) + stopSave() + saveCancel() + if !leaseHeld() { + return MCPRefreshResult{}, fmt.Errorf("%w: session lease was lost during MCP refresh", ErrSessionLeasedElsewhere) + } + if saveErr == nil { + if err := ctx.Err(); err != nil { + return MCPRefreshResult{}, err + } + return result, nil + } + + confirmCtx, confirmCancel := context.WithTimeout(context.WithoutCancel(ctx), mcpRefreshConfirmTimeout) + confirmed, confirmErr := s.cfg.Store.Load(confirmCtx, id) + confirmCancel() + if confirmErr != nil || confirmed == nil || confirmed.ID != id { + return MCPRefreshResult{}, fmt.Errorf("%w: MCP refresh save outcome is uncertain", ErrUnavailable) + } + if reflect.DeepEqual(confirmed, candidate) { + if err := ctx.Err(); err != nil { + return MCPRefreshResult{}, err + } + return result, nil + } + if reflect.DeepEqual(confirmed, old) { + return MCPRefreshResult{}, fmt.Errorf("%w: persist MCP authority: %v", ErrInternal, saveErr) + } + return MCPRefreshResult{}, fmt.Errorf("%w: MCP refresh save outcome is uncertain", ErrUnavailable) +} + +func (s *Service) mcpRefreshTarget(ctx context.Context, id session.SessionID) (*session.Session, error) { + sess, absent, err := s.managementSession(ctx, id, false) + if err != nil { + return nil, err + } + if absent { + return nil, fmt.Errorf("%w: %q", ErrNotFound, id) + } + if sess.State != session.StateIdle && sess.State != session.StateCompleted { + return nil, fmt.Errorf("%w: session is not idle or completed", ErrFailedPrecondition) + } + if s.IsLive(id) { + return nil, fmt.Errorf("%w: session has a local active run", ErrFailedPrecondition) + } + if sess.ExternalBinding != "" { + return nil, fmt.Errorf("%w: broker-bound sessions use workspace enrollment", ErrFailedPrecondition) + } + if _, ok := sess.BoundAuthority(); !ok { + return nil, fmt.Errorf("%w: session authority is not bound", ErrFailedPrecondition) + } + return sess, nil +} + +func mcpRefreshAdditions(sess *session.Session, names []string) ([]string, error) { + authority, bound := sess.BoundAuthority() + if !bound { + return nil, fmt.Errorf("%w: session authority is not bound", ErrFailedPrecondition) + } + if len(authority.CapabilitySet.Tools) > maxMCPHistoricalGrantedNames { + return nil, fmt.Errorf("%w: historical tool authority exceeds limit", ErrFailedPrecondition) + } + seen := make(map[string]struct{}, len(authority.CapabilitySet.Tools)+len(names)) + for _, name := range authority.CapabilitySet.Tools { + seen[name] = struct{}{} + } + additions := make([]string, 0, len(names)) + for _, name := range names { + if _, exists := seen[name]; exists { + continue + } + seen[name] = struct{}{} + additions = append(additions, name) + } + if len(authority.CapabilitySet.Tools)+len(additions) > maxMCPHistoricalGrantedNames { + return nil, fmt.Errorf("%w: historical tool authority exceeds limit", ErrFailedPrecondition) + } + return additions, nil +} diff --git a/internal/adapter/server/mcp_refresh_test.go b/internal/adapter/server/mcp_refresh_test.go new file mode 100644 index 0000000000..68bfc3f9fa --- /dev/null +++ b/internal/adapter/server/mcp_refresh_test.go @@ -0,0 +1,321 @@ +package server_test + +import ( + "context" + "errors" + "sync" + "testing" + "time" + + "github.com/stacklok/mecatl/engine/adapter/memstore" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/adapter/permpolicy" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/governance" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +type refreshStore struct { + *memstore.Store + mu sync.Mutex + saves int + saveErr error + commitOnError bool + confirmMode string + saveStarted chan struct{} + releaseSave chan struct{} +} + +func (s *refreshStore) Save(ctx context.Context, candidate *session.Session) error { + s.mu.Lock() + s.saves++ + err := s.saveErr + commit := err == nil || s.commitOnError + s.mu.Unlock() + if s.saveStarted != nil { + close(s.saveStarted) + } + if s.releaseSave != nil { + <-s.releaseSave + } + if commit { + if saveErr := s.Store.Save(ctx, candidate); saveErr != nil { + return saveErr + } + } + return err +} + +func (s *refreshStore) Load(ctx context.Context, id session.SessionID) (*session.Session, error) { + s.mu.Lock() + confirm := s.saves > 0 && s.saveErr != nil + mode := s.confirmMode + s.mu.Unlock() + if confirm && mode == "unavailable" { + return nil, port.NewSessionLoadFailure(port.SessionLoadFailureStore, errors.New("unavailable")) + } + loaded, err := s.Store.Load(ctx, id) + if err != nil { + return nil, err + } + if confirm && mode == "mismatch" { + if err := loaded.RenameTitle("concurrent value"); err != nil { + return nil, err + } + } + return loaded, nil +} + +func (s *refreshStore) saveCount() int { + s.mu.Lock() + defer s.mu.Unlock() + return s.saves +} + +func TestMCPSourceReconciliation_Scenario4_ServiceRefreshMutationMatrix(t *testing.T) { + owner := &session.Principal{Issuer: "https://issuer.example.com", Subject: "alice"} + ownerCtx := session.WithPrincipal(context.Background(), owner) + foreignCtx := session.WithPrincipal(context.Background(), &session.Principal{Issuer: owner.Issuer, Subject: "bob"}) + + newFixture := func(t *testing.T, names []string, saveErr error, commitOnError bool, onRefresh func(), leases ...port.SessionLease) (*server.Service, *refreshStore, session.SessionID) { + t.Helper() + var lease port.SessionLease + if len(leases) > 0 { + lease = leases[0] + } + store := &refreshStore{Store: memstore.New(), saveErr: saveErr, commitOnError: commitOnError} + eng := agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), Model: "test"}) + svc, err := newPlacementTestService(server.Config{ + Engine: eng, Store: store, OwnershipEnforced: true, + SessionLease: lease, LeaseOwner: "test", LeaseTTL: time.Hour, LeaseRenewInterval: time.Hour, + RootAuthority: func(session.SessionKind) session.Authority { + return session.Authority{CapabilitySet: governance.CapabilitySet{Tools: []string{"Read"}}, Provenance: "test"} + }, + MCPRefresh: func(context.Context) (server.MCPRefreshSnapshot, error) { + if onRefresh != nil { + onRefresh() + } + return server.MCPRefreshSnapshot{Revision: 7, ToolNames: append([]string(nil), names...)}, nil + }, + }) + if err != nil { + t.Fatalf("NewService: %v", err) + } + sess, err := svc.CreateSession(ownerCtx, session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + store.mu.Lock() + store.saves = 0 + store.mu.Unlock() + return svc, store, sess.ID + } + + t.Run("no-op-zero-write-no-mutation-capability", func(t *testing.T) { + testLease := &mutationLease{} + svc, store, id := newFixture(t, []string{"Read"}, nil, false, nil, testLease) + got, err := svc.RefreshMcpSources(ownerCtx, id) + if err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + acquires, _ := testLease.counts() + if got.Revision != 7 || got.Changed || store.saveCount() != 0 || acquires != 0 { + t.Fatalf("result=%+v saves=%d lease acquires=%d", got, store.saveCount(), acquires) + } + }) + + t.Run("addition-acquires-mutation-authority", func(t *testing.T) { + testLease := &mutationLease{} + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil, testLease) + if _, err := svc.RefreshMcpSources(ownerCtx, id); err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + acquires, releases := testLease.counts() + if store.saveCount() != 1 || acquires != 1 || releases != 1 { + t.Fatalf("saves=%d lease=%d/%d", store.saveCount(), acquires, releases) + } + }) + + for _, tc := range []struct { + name string + saveErr error + commitOnError bool + confirmMode string + wantErr bool + wantUncertain bool + }{ + {name: "save-direct-success"}, + {name: "save-error-reload-exact-candidate", saveErr: errors.New("ambiguous"), commitOnError: true}, + {name: "save-error-reload-exact-old", saveErr: errors.New("rejected"), wantErr: true}, + {name: "save-error-reload-mismatch-uncertain", saveErr: errors.New("ambiguous"), confirmMode: "mismatch", wantErr: true, wantUncertain: true}, + {name: "save-error-reload-unavailable-uncertain", saveErr: errors.New("ambiguous"), confirmMode: "unavailable", wantErr: true, wantUncertain: true}, + } { + t.Run(tc.name, func(t *testing.T) { + svc, store, id := newFixture(t, []string{"Read", "mcp__new__call"}, tc.saveErr, tc.commitOnError, nil) + store.confirmMode = tc.confirmMode + got, err := svc.RefreshMcpSources(ownerCtx, id) + if (err != nil) != tc.wantErr { + t.Fatalf("err=%v wantErr=%v", err, tc.wantErr) + } + if tc.wantUncertain && !errors.Is(err, server.ErrUnavailable) { + t.Fatalf("err=%v want uncertain ErrUnavailable", err) + } + if store.saveCount() != 1 { + t.Fatalf("save count=%d want 1", store.saveCount()) + } + persisted, loadErr := store.Store.Load(context.Background(), id) + if loadErr != nil { + t.Fatalf("Load: %v", loadErr) + } + auth, _ := persisted.BoundAuthority() + hasNew := auth.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__new__call"}}) + if !tc.wantErr && (!hasNew || !got.Changed || got.Revision != 7) { + t.Fatalf("result=%+v authority=%+v", got, auth) + } + if tc.wantErr && hasNew { + t.Fatalf("failed save widened authority: %+v", auth) + } + }) + } + + t.Run("cancel-before-save", func(t *testing.T) { + ctx, cancel := context.WithCancel(ownerCtx) + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, cancel) + _, err := svc.RefreshMcpSources(ctx, id) + if !errors.Is(err, context.Canceled) || store.saveCount() != 0 { + t.Fatalf("err=%v saves=%d", err, store.saveCount()) + } + }) + + t.Run("cancel-after-save-start", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + store.saveStarted = make(chan struct{}) + store.releaseSave = make(chan struct{}) + ctx, cancel := context.WithCancel(ownerCtx) + done := make(chan error, 1) + go func() { + _, err := svc.RefreshMcpSources(ctx, id) + done <- err + }() + <-store.saveStarted + cancel() + close(store.releaseSave) + if err := <-done; !errors.Is(err, context.Canceled) { + t.Fatalf("err=%v want context.Canceled", err) + } + persisted, err := store.Store.Load(context.Background(), id) + if err != nil { + t.Fatalf("Load: %v", err) + } + auth, _ := persisted.BoundAuthority() + if !auth.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__new__call"}}) { + t.Fatalf("post-start cancellation rolled back committed authority: %+v", auth) + } + }) + + t.Run("completed-state-preserved", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + sess, err := store.Store.Load(context.Background(), id) + if err != nil { + t.Fatal(err) + } + if err := sess.BeginTurn(); err != nil { + t.Fatal(err) + } + if err := sess.Complete(); err != nil { + t.Fatal(err) + } + if err := store.Store.Save(context.Background(), sess); err != nil { + t.Fatal(err) + } + if _, err := svc.RefreshMcpSources(ownerCtx, id); err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + persisted, _ := store.Store.Load(context.Background(), id) + if persisted.State != session.StateCompleted { + t.Fatalf("completed refresh reopened state: %s", persisted.State) + } + }) + + t.Run("ineligible-state-and-taxonomy", func(t *testing.T) { + cases := []struct { + name string + mutate func(*session.Session) error + }{ + {"running", func(s *session.Session) error { return s.BeginTurn() }}, + {"awaiting", func(s *session.Session) error { + if err := s.BeginTurn(); err != nil { + return err + } + return s.PauseForApproval(session.PendingAsk{AskID: "ask"}) + }}, + {"failed", func(s *session.Session) error { + if err := s.BeginTurn(); err != nil { + return err + } + return s.Fail() + }}, + {"cancelled", func(s *session.Session) error { + if err := s.BeginTurn(); err != nil { + return err + } + return s.Cancel() + }}, + {"child", func(s *session.Session) error { + return s.RestoreSessionMetadata(session.SessionKindSubagent, session.SessionRelationship{ParentSessionID: "parent", CallID: "call"}) + }}, + {"schedule", func(s *session.Session) error { + return s.RestoreSessionMetadata(session.SessionKindScheduled, session.SessionRelationship{ScheduleName: "nightly"}) + }}, + {"debug", func(s *session.Session) error { + return s.RestoreSessionMetadata(session.SessionKindDebug, session.SessionRelationship{DebugTargetID: "target"}) + }}, + {"broker-conflicting", func(s *session.Session) error { s.ExternalBinding = "broker"; return nil }}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + sess, err := store.Store.Load(context.Background(), id) + if err != nil { + t.Fatal(err) + } + if err := tc.mutate(sess); err != nil { + t.Fatalf("mutate: %v", err) + } + if err := store.Store.Save(context.Background(), sess); err != nil { + t.Fatalf("save fixture: %v", err) + } + if _, err := svc.RefreshMcpSources(ownerCtx, id); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("err=%v want ErrFailedPrecondition", err) + } + if store.saveCount() != 0 { + t.Fatalf("refresh persisted ineligible session %d times", store.saveCount()) + } + }) + } + }) + + t.Run("stable-union-retry-converges", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + if _, err := svc.RefreshMcpSources(ownerCtx, id); err != nil { + t.Fatal(err) + } + if _, err := svc.RefreshMcpSources(ownerCtx, id); err != nil { + t.Fatal(err) + } + if store.saveCount() != 1 { + t.Fatalf("converged refresh saves=%d want 1", store.saveCount()) + } + }) + + t.Run("owner-concealment", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + _, err := svc.RefreshMcpSources(foreignCtx, id) + if !errors.Is(err, server.ErrNotFound) || store.saveCount() != 0 { + t.Fatalf("foreign refresh err=%v saves=%d", err, store.saveCount()) + } + }) +} diff --git a/internal/adapter/server/mcp_refresh_transport_test.go b/internal/adapter/server/mcp_refresh_transport_test.go new file mode 100644 index 0000000000..8c726eaa3f --- /dev/null +++ b/internal/adapter/server/mcp_refresh_transport_test.go @@ -0,0 +1,106 @@ +package server_test + +import ( + "bytes" + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + mecatlv1 "github.com/stacklok/mecatl/contracts/gen/go/mecatl/v1" + "github.com/stacklok/mecatl/engine/adapter/memstore" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/adapter/permpolicy" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/governance" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/mcp/source" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +func TestMCPSourceReconciliation_Scenario4_DirectTransportStatusMatrix(t *testing.T) { + var refreshCalls int + statusSnapshot := server.MCPSourceStatus{ + Sources: []source.SourceInfo{{Name: "static", Kind: "static", Enabled: true}}, + Revision: 41, Stale: true, Reconciling: true, + } + eng := agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), Model: "test"}) + svc, err := newPlacementTestService(server.Config{ + Engine: eng, Store: memstore.New(), + RootAuthority: func(session.SessionKind) session.Authority { + return session.Authority{CapabilitySet: governance.CapabilitySet{Tools: []string{"Read"}}, Provenance: "test"} + }, + MCPRefresh: func(context.Context) (server.MCPRefreshSnapshot, error) { + refreshCalls++ + statusSnapshot.Revision = 99 // a coalesced successor may publish before delivery + return server.MCPRefreshSnapshot{Revision: 42, Changed: refreshCalls == 1, ToolNames: []string{"Read"}}, nil + }, + MCPStatus: func() server.MCPSourceStatus { return statusSnapshot }, + }) + if err != nil { + t.Fatalf("NewService: %v", err) + } + sess, err := svc.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatalf("CreateSession: %v", err) + } + + client, cleanup := dialGRPC(t, svc) + defer cleanup() + compat, err := client.GetCompatibilityInfo(context.Background(), &mecatlv1.GetCompatibilityInfoRequest{}) + if err != nil || !compat.GetCapabilities().GetMcpRefresh() || compat.GetCapabilities().GetWorkspaceEnrollment() { + t.Fatalf("direct refresh capabilities=%+v err=%v", compat.GetCapabilities(), err) + } + listed, err := client.ListMcpSources(context.Background(), &mecatlv1.ListMcpSourcesRequest{}) + if err != nil { + t.Fatalf("ListMcpSources: %v", err) + } + if listed.GetRevision() != 41 || !listed.GetStale() || !listed.GetReconciling() || len(listed.GetSources()) != 1 || refreshCalls != 0 { + t.Fatalf("cached list=%+v refreshCalls=%d", listed, refreshCalls) + } + refreshed, err := client.RefreshMcpSources(context.Background(), &mecatlv1.RefreshMcpSourcesRequest{SessionId: string(sess.ID)}) + if err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + if refreshed.GetRevision() != 42 || !refreshed.GetChanged() || refreshCalls != 1 { + t.Fatalf("refresh=%+v refreshCalls=%d", refreshed, refreshCalls) + } + + httpSrv := httptest.NewServer(server.NewHTTPHandler(svc)) + defer httpSrv.Close() + req, err := http.NewRequest(http.MethodPost, httpSrv.URL+"/v1/sessions/"+string(sess.ID)+"/mcp-refresh", nil) + if err != nil { + t.Fatal(err) + } + resp, err := httpSrv.Client().Do(req) + if err != nil { + t.Fatalf("POST refresh: %v", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + t.Fatalf("POST refresh status=%d", resp.StatusCode) + } + var body mecatlv1.RefreshMcpSourcesResponse + if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { + t.Fatalf("decode refresh: %v", err) + } + if body.GetRevision() != 42 || body.GetChanged() { + t.Fatalf("second no-op refresh revision=%d changed=%v", body.GetRevision(), body.GetChanged()) + } + + badReq, err := http.NewRequest(http.MethodPost, httpSrv.URL+"/v1/sessions/"+string(sess.ID)+"/mcp-refresh", bytes.NewBufferString(`{"ignored":true}`)) + if err != nil { + t.Fatal(err) + } + badReq.Header.Set("Content-Type", "application/json") + badResp, err := httpSrv.Client().Do(badReq) + if err != nil { + t.Fatalf("POST body: %v", err) + } + defer badResp.Body.Close() + if badResp.StatusCode != http.StatusBadRequest { + t.Fatalf("nonempty body status=%d want 400", badResp.StatusCode) + } +} diff --git a/internal/adapter/server/mcp_test.go b/internal/adapter/server/mcp_test.go index 023413e4e5..40eff01f1f 100644 --- a/internal/adapter/server/mcp_test.go +++ b/internal/adapter/server/mcp_test.go @@ -320,20 +320,14 @@ func TestGRPCListToolHiveGroups(t *testing.T) { } } -// TestServiceMcpSourceProberReflectsLiveStatus asserts that when a MCPSourceProber -// is configured, ListMcpSources/ListToolHiveGroups re-consult it on every call — -// so a source whose status changed since startup (a server reconnected, a new -// group appeared) is reflected, not the cached startup snapshot. -func TestServiceMcpSourceProberReflectsLiveStatus(t *testing.T) { - startup := cannedSources() - // The "live" inventory differs: the toolhive(default) diagnostic cleared and a - // brand-new toolhive group ("staging") appeared. - live := []source.SourceInfo{ +// TestServiceMcpSourceStatusIsCached proves listing reads the reconciler cache and +// performs no independent source probe. +func TestServiceMcpSourceStatusIsCached(t *testing.T) { + cached := []source.SourceInfo{ {Name: "static", Kind: "static", Enabled: true, Servers: []source.ServerInfo{{Name: "alpha", URL: "http://a", Transport: "streamable-http"}}}, {Name: "toolhive(default)", Kind: "toolhive", Enabled: true, Group: "default", Servers: []source.ServerInfo{{Name: "beta", URL: "http://b", Transport: "streamable-http", Group: "default"}}}, {Name: "toolhive(staging)", Kind: "toolhive", Enabled: true, Group: "staging"}, } - var probeCalls int engine := agent.NewEngine(agent.Deps{ LLM: mockllm.New(), Catalog: tool.NewCatalog(), @@ -343,37 +337,26 @@ func TestServiceMcpSourceProberReflectsLiveStatus(t *testing.T) { svc, err := newPlacementTestService(server.Config{ Engine: engine, Store: memstore.New(), - - Now: func() time.Time { return time.Unix(0, 0) }, - MCPSources: startup, // cached fallback - MCPSourceProber: func(_ context.Context) []source.SourceInfo { - probeCalls++ - return live + Now: func() time.Time { return time.Unix(0, 0) }, + MCPStatus: func() server.MCPSourceStatus { + return server.MCPSourceStatus{Sources: cached, Revision: 3, Stale: true} }, }) if err != nil { t.Fatalf("new service: %v", err) } - got := svc.ListMcpSources(context.Background()) - if len(got) != 3 { - t.Fatalf("live sources = %d, want 3 (prober result, not the 5-source snapshot)", len(got)) - } - if len(got[1].Diagnostics) != 0 { - t.Fatalf("toolhive diagnostic not cleared on re-probe: %#v", got[1].Diagnostics) - } groups := svc.ListToolHiveGroups(context.Background()) - if len(groups) != 2 || groups[0] != "default" || groups[1] != "staging" { - t.Fatalf("live groups = %v, want [default staging]", groups) + if len(got.Sources) != 3 || len(groups) != 2 || groups[0] != "default" || groups[1] != "staging" || got.Revision != 3 || !got.Stale { + t.Fatalf("sources=%d groups=%v status=%+v", len(got.Sources), groups, got) } - if probeCalls != 2 { // once per List call — re-consulted every time - t.Fatalf("prober called %d times, want 2", probeCalls) + got.Sources[0].Name = "mutated" + if again := svc.ListMcpSources(context.Background()); again.Sources[0].Name != "static" { + t.Fatalf("cached status was aliased: %+v", again.Sources[0]) } } -// TestServiceMcpSourceProberFailSoft asserts a prober that returns nil (a failed -// re-probe) falls back to the cached startup snapshot, so the panel still renders. -func TestServiceMcpSourceProberFailSoft(t *testing.T) { +func TestServiceMcpSourceStatusFallsBackToStartupSnapshot(t *testing.T) { engine := agent.NewEngine(agent.Deps{ LLM: mockllm.New(), Catalog: tool.NewCatalog(), @@ -381,18 +364,16 @@ func TestServiceMcpSourceProberFailSoft(t *testing.T) { Model: "test-model", }) svc, err := newPlacementTestService(server.Config{ - Engine: engine, - Store: memstore.New(), - - Now: func() time.Time { return time.Unix(0, 0) }, - MCPSources: cannedSources(), - MCPSourceProber: func(_ context.Context) []source.SourceInfo { return nil }, + Engine: engine, + Store: memstore.New(), + Now: func() time.Time { return time.Unix(0, 0) }, + MCPSources: cannedSources(), }) if err != nil { t.Fatalf("new service: %v", err) } - if got := svc.ListMcpSources(context.Background()); len(got) != 5 { - t.Fatalf("fail-soft sources = %d, want 5 (cached snapshot)", len(got)) + if got := svc.ListMcpSources(context.Background()); len(got.Sources) != 5 { + t.Fatalf("fallback sources = %d, want 5", len(got.Sources)) } } diff --git a/internal/adapter/server/sdk_typescript_release_test.go b/internal/adapter/server/sdk_typescript_release_test.go index 105712c965..b21bec3f67 100644 --- a/internal/adapter/server/sdk_typescript_release_test.go +++ b/internal/adapter/server/sdk_typescript_release_test.go @@ -56,8 +56,8 @@ func TestSDKTypescriptRelease_Scenario1_RPCTransportCatalogParity(t *testing.T) t.Fatalf("stale generated mecatl.v1 service catalog/exclusion decision: %v", missing) } - wantCounts := map[string]int{"HarnessService": 74, "ScheduleService": 10} - wantKeys := make(map[string]struct{}, 84) + wantCounts := map[string]int{"HarnessService": 75, "ScheduleService": 10} + wantKeys := make(map[string]struct{}, 85) for service := range targetServices { methods := descriptorsByService[service] if len(methods) != wantCounts[service] { diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index 9a209b4f41..54bbc378ae 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -355,22 +355,16 @@ type Config struct { // catalog-level inspection RPCs. Optional and nil-safe: when nil, the list // RPCs return empty and the read/get RPCs return ErrNoMCPProvider. MCPProvider mcp.Provider - // MCPSources is the resolved MCP source inventory snapshot taken at startup. - // It backs ListMcpSources and ListToolHiveGroups when MCPSourceProber is nil; - // in that case both derive purely from this snapshot and perform no live - // discovery. May be empty. + // MCPSources is the startup inventory fallback used only when MCPStatus is nil. + // Production direct MCP composition supplies the reconciler's cached status. MCPSources []source.SourceInfo - // MCPSourceProber, when non-nil, re-consults the resolved MCP sources on each - // ListMcpSources/ListToolHiveGroups call and returns a FRESH inventory — so a - // client refresh reflects CURRENT source status/diagnostics (e.g. a ToolHive - // workload that crashed or appeared after startup), not the startup snapshot. - // It is the live-discovery seam: the composition root supplies a prober that - // closes over the resolved []source.Source and re-runs source.InspectSources. - // When nil, ListMcpSources falls back to the cached MCPSources snapshot. The - // prober is read-only (streaming-HTTP / container queries only; never spawns a - // process) and fail-soft: on any failure the Service falls back to the cached - // snapshot so the panel always renders. - MCPSourceProber func(ctx context.Context) []source.SourceInfo + // MCPRefresh reconciles direct MCP sources and returns the exact immutable + // runtime snapshot considered by this request. It is nil when direct refresh + // is unavailable. Shared reconciliation outlives caller cancellation. + MCPRefresh func(ctx context.Context) (MCPRefreshSnapshot, error) + // MCPStatus returns the reconciler's cached publication/source status without + // consulting an upstream source. It is nil when direct MCP is unavailable. + MCPStatus func() MCPSourceStatus // Commands lists the available slash commands for a workspace, backing the // ListCommands RPC (the client's in-input command palette). It is the // composition-injected discovery seam: the composition root (internal/app) @@ -2614,6 +2608,7 @@ func (s *Service) capabilities() *mecatlv1.ServerCapabilities { SessionDebug: s.cfg.DebugSessionEngine != nil, DebugMcp: s.cfg.DebugMCP, WorkspaceEnrollment: s.cfg.WorkspaceEnrollment, + McpRefresh: s.cfg.MCPRefresh != nil, } } @@ -7663,37 +7658,34 @@ func classifyMCPError(err error) error { return fmt.Errorf("%w: %v", ErrInternal, err) } -// ListMcpSources returns the MCP source inventory (possibly empty). When a -// MCPSourceProber is configured it RE-CONSULTS the resolved sources for live -// status/diagnostics on every call (so a client refresh reflects current state, -// not the startup snapshot); on a prober that returns nil it falls back to the -// cached startup snapshot so the panel always renders. With no prober it is a -// pure read of the injected snapshot (no live discovery). -func (s *Service) ListMcpSources(ctx context.Context) []source.SourceInfo { - return s.liveSources(ctx) +// ListMcpSources returns a detached cached published/pre-shadow inventory and +// reconciler status. It never consults an upstream source. +func (s *Service) ListMcpSources(_ context.Context) MCPSourceStatus { + if s.cfg.MCPStatus != nil { + cached := s.cfg.MCPStatus() + cached.Sources = cloneMCPSourceInfos(cached.Sources) + return cached + } + return MCPSourceStatus{Sources: cloneMCPSourceInfos(s.cfg.MCPSources)} } -// liveSources returns the freshest inventory available: the prober's result when -// it is configured and yields anything, otherwise the cached startup snapshot. -// Centralising this keeps ListMcpSources and ListToolHiveGroups consistent — a -// refresh that re-probes sources is reflected in both the panel and the groups. -func (s *Service) liveSources(ctx context.Context) []source.SourceInfo { - if s.cfg.MCPSourceProber != nil { - if probed := s.cfg.MCPSourceProber(ctx); probed != nil { - return probed - } +func cloneMCPSourceInfos(in []source.SourceInfo) []source.SourceInfo { + out := make([]source.SourceInfo, len(in)) + for i := range in { + out[i] = in[i] + out[i].Servers = append([]source.ServerInfo(nil), in[i].Servers...) + out[i].Diagnostics = append([]string(nil), in[i].Diagnostics...) } - return s.cfg.MCPSources + return out } // ListToolHiveGroups derives the distinct, non-empty ToolHive groups from the -// inventory (the live re-probe when a MCPSourceProber is set, else the startup -// snapshot — see liveSources). It considers only sources whose Kind is -// "toolhive". Output is sorted for deterministic results. +// same cached inventory as ListMcpSources. It considers only sources whose Kind +// is "toolhive". Output is sorted for deterministic results. func (s *Service) ListToolHiveGroups(ctx context.Context) []string { seen := make(map[string]struct{}) var groups []string - for _, src := range s.liveSources(ctx) { + for _, src := range s.ListMcpSources(ctx).Sources { if src.Kind != "toolhive" || src.Group == "" { continue } diff --git a/internal/adapter/server/session_affinity_grpc_test.go b/internal/adapter/server/session_affinity_grpc_test.go index 6fb9023d11..06aaa6573e 100644 --- a/internal/adapter/server/session_affinity_grpc_test.go +++ b/internal/adapter/server/session_affinity_grpc_test.go @@ -71,6 +71,7 @@ func TestADR_0294_NewSessionBoundRPCsRequireAffinityClassification(t *testing.T) "GetMcpAuthorizationPresentation": true, "RecheckMcpAuthorization": true, "CancelMcpAuthorization": true, "ListSessionMcpConnectors": true, "ConnectWorkspaceServices": true, "RetryWorkspaceEnrollment": true, "CancelWorkspaceEnrollment": true, + "RefreshMcpSources": true, } service := mecatlv1.File_mecatl_v1_harness_proto.Services().ByName("HarnessService") for i := range service.Methods().Len() { diff --git a/internal/app/build.go b/internal/app/build.go index 6ebe8a31ee..a4ffa7310f 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -2163,6 +2163,26 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { } modelsRefreshState := &refreshStaleModelsState{} var modelSwap modelSwapper + var mcpRefresh func(context.Context) (server.MCPRefreshSnapshot, error) + var mcpStatus func() server.MCPSourceStatus + if assets.mcpReconciler != nil { + mcpRefresh = func(ctx context.Context) (server.MCPRefreshSnapshot, error) { + result, err := assets.mcpReconciler.Reconcile(ctx) + if err != nil { + return server.MCPRefreshSnapshot{}, err + } + snapshot := server.MCPRefreshSnapshot{Changed: result.changed} + if result.candidate != nil { + snapshot.Revision = result.candidate.generation + snapshot.ToolNames = make([]string, 0, len(result.candidate.tools)) + for _, meta := range result.candidate.tools { + snapshot.ToolNames = append(snapshot.ToolNames, meta.Name) + } + } + return snapshot, nil + } + mcpStatus = assets.mcpReconciler.statusSnapshot + } svcCfg := server.Config{ BuildID: buildinfo.BuildID, ServerImplementation: cfg.ServerImplementation, @@ -2228,12 +2248,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { // it. nil when the store backs no ScheduleStore (the honest // no-scheduling path). ScheduleManager: scheduleMgr, - // Live re-probe: ListMcpSources re-consults the resolved sources on each call - // so a TUI panel refresh (ctrl+o → ctrl+r) reflects CURRENT source status, - // not just this startup snapshot. nil when MCP is unconfigured (keeps the - // empty snapshot). Resolution is idempotent + read-only, like the agent - // registry re-resolution below. - MCPSourceProber: mcpSourceProber(cfg), + // Cached reconciler status and explicit owner refresh. Listing never probes. + MCPRefresh: mcpRefresh, + MCPStatus: mcpStatus, // ListAgents snapshot: project the ONE registry resolved by // resolveAgentSeam above (never a second resolution — the per-session // drift class) into the proto form; the snapshot stays a pure read at @@ -5435,7 +5452,7 @@ func buildCatalog(ctx context.Context, cfg Config, reg *providerRegistry, provid // buildSubagentTool can (a) pull a REFERENCED main server's tools out of this manager // and (b) connect their own INLINE servers. mainMgr is nil when no main servers are // configured (reference entries then resolve to a clear "unknown server" diagnostic). - mainMgr, mcpProvider, mcpInventory, mcpRuntimes, mcpClose := connectMCP(ctx, cfg) + mainMgr, mcpProvider, mcpInventory, mcpRuntimes, mcpReconciler, mcpClose := connectMCP(ctx, cfg) // Per-project memory store: opt-in via MemoryStoreURL (a remote gRPC driver; // Phase B) or MemoryDir (the flocked reference adapter, opened ONCE here — @@ -5659,6 +5676,7 @@ func buildCatalog(ctx context.Context, cfg Config, reg *providerRegistry, provid assets := catalogAssets{ globalMgr: mainMgr, mcpRuntimes: mcpRuntimes, + mcpReconciler: mcpReconciler, agentReg: agentReg, memStore: memStore, userModelStore: userModelStore, @@ -5768,25 +5786,6 @@ func mcpResolveOptions(cfg Config) mcpsource.ResolveOptions { } } -// mcpSourceProber builds the live-inventory prober wired into the server.Service. -// It re-runs source.InspectSources over the SAME resolved sources on every call, -// so a client refresh reflects CURRENT source status/diagnostics (a ToolHive -// workload that crashed or appeared after startup), not the startup snapshot. -// Resolution is read-only (the ToolHive source queries the container runtime; the -// static source is in-memory) and fail-soft, matching the rest of MCP wiring. It -// returns nil when MCP is not configured (no static servers, ToolHive off) so the -// Service simply keeps using the (empty) startup snapshot. -func mcpSourceProber(cfg Config) func(ctx context.Context) []mcpsource.SourceInfo { - opts := mcpResolveOptions(cfg) - if len(opts.StaticServers) == 0 && !opts.ToolHiveEnabled { - return nil - } - sources := mcpsource.ResolveSources(opts) - return func(ctx context.Context) []mcpsource.SourceInfo { - return mcpsource.InspectSources(ctx, sources, opts) - } -} - // connectMCP RESOLVES the MCP server inventory from the pluggable source list // (static MCPServers entries first, then the live ToolHive workload source when // ToolHiveEnabled) and connects the merged set. It is non-fatal end to end: @@ -5798,12 +5797,12 @@ func mcpSourceProber(cfg Config) func(ctx context.Context) []mcpsource.SourceInf // the concrete *mcp.Manager (nil when no servers connect) so the per-agent-def // wiring can pull a REFERENCED main server's tools out of it; the same value is // the mcp.Provider used for resources/prompts. -func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, []mcpsource.SourceInfo, *mcpRuntimeSet, func()) { +func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, []mcpsource.SourceInfo, *mcpRuntimeSet, *mcpSourceReconciler, func()) { opts := mcpResolveOptions(cfg) if len(opts.StaticServers) == 0 && !opts.ToolHiveEnabled { _, inventory, _ := mcpsource.Resolve(ctx, mcpsource.ResolveSources(opts)) cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", "toolhive", false, "static", 0) - return nil, nil, inventory, nil, func() {} + return nil, nil, inventory, nil, nil, func() {} } runtimes := newMCPRuntimeSet(nil) reconciler := newMCPSourceReconciler(mcpReconcilerOptions{ @@ -5829,11 +5828,11 @@ func connectMCP(ctx context.Context, cfg Config) (*mcp.Manager, mcp.Provider, [] cfg.diag().Log(ctx, port.LevelInfo, "MCP DISABLED (no servers resolved from any source)", "toolhive", cfg.ToolHiveEnabled, "static", len(cfg.MCPServers)) } - return nil, runtimes, result.inventory, runtimes, closeRuntime + return nil, runtimes, result.inventory, runtimes, reconciler, closeRuntime } mgr := result.candidate.manager cfg.diag().Log(ctx, port.LevelInfo, "MCP servers connected", "servers", len(result.candidate.configs), "tools", len(mgr.Tools())) - return mgr, runtimes, result.inventory, runtimes, closeRuntime + return mgr, runtimes, result.inventory, runtimes, reconciler, closeRuntime } func logMCPReconcileConnectError(ctx context.Context, cfg Config, configs []mcp.ServerConfig, err error) { diff --git a/internal/app/catalog.go b/internal/app/catalog.go index 5876628ca9..c15f59b2cf 100644 --- a/internal/app/catalog.go +++ b/internal/app/catalog.go @@ -77,6 +77,7 @@ type catalogAssets struct { // Catalog copies select the operation-pinned manager before assembly; cached // engines retain only the returned revision tag. mcpRuntimes *mcpRuntimeSet + mcpReconciler *mcpSourceReconciler agentReg *agents.Registry memStore tool.MemoryStore userModelStore tool.MemoryStore diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go index 451e1a4c66..c740b15a51 100644 --- a/internal/app/mcp_reconciler.go +++ b/internal/app/mcp_reconciler.go @@ -17,6 +17,7 @@ import ( "github.com/stacklok/mecatl/engine/tool" "github.com/stacklok/mecatl/internal/adapter/mcp" mcpsource "github.com/stacklok/mecatl/internal/adapter/mcp/source" + serveradapter "github.com/stacklok/mecatl/internal/adapter/server" ) const ( @@ -118,6 +119,7 @@ type mcpSourceReconciler struct { waiters []chan mcpReconcileReply lkg map[string]mcpSourceSnapshot current *mcpReconcileCandidate + status serveradapter.MCPSourceStatus closed bool cyclesDone atomic.Int64 @@ -143,6 +145,14 @@ func newMCPSourceReconciler(opts mcpReconcilerOptions) *mcpSourceReconciler { func (r *mcpSourceReconciler) polling() bool { return r.toolHive } func (r *mcpSourceReconciler) cycles() int64 { return r.cyclesDone.Load() } +func (r *mcpSourceReconciler) statusSnapshot() serveradapter.MCPSourceStatus { + r.mu.Lock() + defer r.mu.Unlock() + status := r.status + status.Sources = cloneMCPInventory(status.Sources) + return status +} + func (r *mcpSourceReconciler) Reconcile(ctx context.Context) (mcpReconcileResult, error) { reply := make(chan mcpReconcileReply, 1) r.mu.Lock() @@ -184,7 +194,18 @@ func (r *mcpSourceReconciler) loop() { poll = r.after(mcpPollDelay()) case <-r.trigger: waiters := r.takeWaiters() + r.mu.Lock() + r.status.Reconciling = true + r.mu.Unlock() result, err := r.cycle() + r.mu.Lock() + r.status.Sources = cloneMCPInventory(result.inventory) + r.status.Stale = result.stale + r.status.Reconciling = false + if result.candidate != nil { + r.status.Revision = result.candidate.generation + } + r.mu.Unlock() r.cyclesDone.Add(1) replyMCPWaiters(waiters, result, err) } @@ -304,7 +325,7 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { old.close() } result.candidate = candidate - result.changed = old != nil + result.changed = true return result, nil } diff --git a/sdk/typescript/etc/mecatl-sdk-deno.api.md b/sdk/typescript/etc/mecatl-sdk-deno.api.md index 44ac1835aa..1c1825edb9 100644 --- a/sdk/typescript/etc/mecatl-sdk-deno.api.md +++ b/sdk/typescript/etc/mecatl-sdk-deno.api.md @@ -632,6 +632,9 @@ export interface McpInventory { // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceRequest" needs to be exported by the entry point deno.d.ts // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceResponse" needs to be exported by the entry point deno.d.ts readResource(request: ReadMcpResourceRequest, options?: RequestOptions): Promise; + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesRequest" needs to be exported by the entry point deno.d.ts + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesResponse" needs to be exported by the entry point deno.d.ts + refresh(request: RefreshMcpSourcesRequest, options?: RequestOptions): Promise; } // @public diff --git a/sdk/typescript/etc/mecatl-sdk-node.api.md b/sdk/typescript/etc/mecatl-sdk-node.api.md index 8f3f00c7fa..d03233b2a4 100644 --- a/sdk/typescript/etc/mecatl-sdk-node.api.md +++ b/sdk/typescript/etc/mecatl-sdk-node.api.md @@ -653,6 +653,9 @@ export interface McpInventory { // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceRequest" needs to be exported by the entry point node.d.ts // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceResponse" needs to be exported by the entry point node.d.ts readResource(request: ReadMcpResourceRequest, options?: RequestOptions): Promise; + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesRequest" needs to be exported by the entry point node.d.ts + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesResponse" needs to be exported by the entry point node.d.ts + refresh(request: RefreshMcpSourcesRequest, options?: RequestOptions): Promise; } // @public diff --git a/sdk/typescript/etc/mecatl-sdk.api.md b/sdk/typescript/etc/mecatl-sdk.api.md index 57b7f6e9e6..a6b42606c2 100644 --- a/sdk/typescript/etc/mecatl-sdk.api.md +++ b/sdk/typescript/etc/mecatl-sdk.api.md @@ -617,6 +617,9 @@ export interface McpInventory { // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceRequest" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "ReadMcpResourceResponse" needs to be exported by the entry point index.d.ts readResource(request: ReadMcpResourceRequest, options?: RequestOptions): Promise; + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesRequest" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "RefreshMcpSourcesResponse" needs to be exported by the entry point index.d.ts + refresh(request: RefreshMcpSourcesRequest, options?: RequestOptions): Promise; } // @public diff --git a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts index 4d36606fbe..5871db19a2 100644 --- a/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts +++ b/sdk/typescript/src/gen/mecatl/v1/harness_pb.ts @@ -36,7 +36,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file mecatl/v1/harness.proto. */ export const file_mecatl_v1_harness: GenFile = /*@__PURE__*/ - fileDesc("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIskCChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSDwoHcHJvZmlsZRgGIAEoCRIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWNKBAgBEAJKBAgIEAlSCXdvcmtzcGFjZVIRc291cmNlX3Nlc3Npb25faWQisQEKDU1jcFNlcnZlclNwZWMSDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSDAoEdHlwZRgDIAEoCRIPCgdjb21tYW5kGAQgASgJEjYKB2hlYWRlcnMYBSADKAsyJS5tZWNhdGwudjEuTWNwU2VydmVyU3BlYy5IZWFkZXJzRW50cnkaLgoMSGVhZGVyc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiKwoUR2V0U2VydmVySW5mb1JlcXVlc3QSEwoLcHJvdmlkZXJfaWQYASABKAkibwoVR2V0U2VydmVySW5mb1Jlc3BvbnNlEhAKCGJ1aWxkX2lkGAEgASgJEh0KFXNlcnZlcl9pbXBsZW1lbnRhdGlvbhgCIAEoCRIlCh1sbG1fcHJvdmlkZXJfZGlzcGxheV9lbmRwb2ludBgDIAEoCSIdChtHZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QijAEKHEdldENvbXBhdGliaWxpdHlJbmZvUmVzcG9uc2USEQoJYXBpX21ham9yGAEgASgFEjMKDGNhcGFiaWxpdGllcxgCIAEoCzIdLm1lY2F0bC52MS5TZXJ2ZXJDYXBhYmlsaXRpZXMSEAoIZmVhdHVyZXMYAyADKAkSEgoKZGVwbG95bWVudBgEIAEoCSKMBQoSU2VydmVyQ2FwYWJpbGl0aWVzEgsKA21jcBgBIAEoCBIWCg5zbGFzaF9jb21tYW5kcxgCIAEoCBIOCgZtZW1vcnkYAyABKAgSDgoGc2tpbGxzGAQgASgIEg0KBXRlYW1zGAUgASgIEgwKBGJhc2gYBiABKAgSDQoFaW1hZ2UYByABKAgSDQoFYXVkaW8YCCABKAgSDgoGYWdlbnRzGAkgASgIEgwKBHNvdWwYCiABKAgSEgoKdXNlcl9tb2RlbBgLIAEoCBIXCg9tb2RlbF9zZWxlY3Rpb24YDCABKAgSDwoHcG9zdHVyZRgNIAEoCRIRCgl3b3JrdHJlZXMYDiABKAgSEgoKc2NoZWR1bGluZxgPIAEoCBISCgpyZWZsZWN0aW9uGBAgASgIEhoKEmxlYXJuaW5nX3Byb3Bvc2FscxgRIAEoCBIWCg5sZWFybmVkX3NraWxscxgSIAEoCBIZChFzdG9yYWdlX21pZ3JhdGlvbhgVIAEoCBIXCg9zdG9yYWdlX2NsZWFudXAYFiABKAgSOAoMbWFudWFsX2RyZWFtGBMgASgLMiIubWVjYXRsLnYxLk1hbnVhbERyZWFtQ2FwYWJpbGl0aWVzEhYKDnN0b3JhZ2VfaGVhbHRoGBcgASgIEg0KBXN0ZWVyGBggASgIEhkKEW1hbnVhbF9jb21wYWN0aW9uGBkgASgIEhUKDXNlc3Npb25fZGVidWcYGiABKAgSEQoJZGVidWdfbWNwGBsgASgIEhwKFHdvcmtzcGFjZV9lbnJvbGxtZW50GBwgASgIEhwKFG1jcF9jb25uZWN0b3Jfc3RhdHVzGB0gASgISgQIFBAVUg9sZWdhY3lfYWRvcHRpb24iNQofTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJIrIBCiBMaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXNwb25zZRIUCgxhdmFpbGFiaWxpdHkYASABKAkSGAoQZW5yb2xsbWVudF9zdGF0ZRgCIAEoCRIxCgpjb25uZWN0b3JzGAMgAygLMh0ubWVjYXRsLnYxLk1jcENvbm5lY3RvclN0YXR1cxIYChB0b3RhbF9jb25uZWN0b3JzGAQgASgNEhEKCXRydW5jYXRlZBgFIAEoCCJPChJNY3BDb25uZWN0b3JTdGF0dXMSDAoEbmFtZRgBIAEoCRIXCg9jYXRhbG9ndWVfc3RhdGUYAiABKAkSEgoKdG9vbF9jb3VudBgDIAEoDSKBAgoVQ3JlYXRlU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSMwoMY2FwYWJpbGl0aWVzGAIgASgLMh0ubWVjYXRsLnYxLlNlcnZlckNhcGFiaWxpdGllcxI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgDIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEjAKDnJlc29sdmVkX21vZGVsGAQgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSLwoJcGxhY2VtZW50GAUgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIlIKEVBsYWNlbWVudE1ldGFkYXRhEgwKBGtpbmQYASABKAkSDQoFbGFiZWwYAiABKAkSDgoGYnJhbmNoGAMgASgJEhAKCHJldmlzaW9uGAQgASgJImgKDVJlc29sdmVkTW9kZWwSEwoLcHJvdmlkZXJfaWQYASABKAkSEAoIbW9kZWxfaWQYAiABKAkSFgoOY29udGV4dF93aW5kb3cYAyABKAMSGAoQcmVhc29uaW5nX2VmZm9ydBgEIAEoCSIzChNTZXNzaW9uQ2FwYWJpbGl0aWVzEg0KBWltYWdlGAEgASgIEg0KBWF1ZGlvGAIgASgIIjAKEUdldFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiOQoSR2V0U2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiI6ChtHZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJSChRBY3Rpdml0eVJlcGxheVN0YXR1cxIRCglhdmFpbGFibGUYASABKAgSEAoIY29tcGxldGUYAiABKAgSFQoNYXV0aG9yaXRhdGl2ZRgDIAEoCCLtAQocR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjAKCG1lc3NhZ2VzGAIgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2USEAoIY29tcGxldGUYAyABKAgSMQoIYWN0aXZpdHkYBCABKAsyHy5tZWNhdGwudjEuQWN0aXZpdHlSZXBsYXlTdGF0dXMSDAoEa2luZBgFIAEoCRI0CgxyZWxhdGlvbnNoaXAYBiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcCI5ChpTdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjcKGFN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIlgKGVdhdGNoU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIOCgZjdXJzb3IYAiABKAkSDgoGcnVuX2lkGAMgASgJIlwKGldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50Eg4KBmN1cnNvchgCIAEoCRINCgVwaGFzZRgDIAEoCSI4ChNMaXN0U2Vzc2lvbnNSZXF1ZXN0EhEKCXBhZ2Vfc2l6ZRgBIAEoBRIOCgZjdXJzb3IYAiABKAkiTgoJUHJpbmNpcGFsEg4KBmlzc3VlchgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEhIKCmdyYW50X3R5cGUYAyABKAkSDAoEbmFtZRgEIAEoCSKKBQoOU2Vzc2lvblN1bW1hcnkSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAIgASgDEg0KBXN0YXRlGAMgASgJEg0KBXR1cm5zGAQgASgFEhAKCG1vZGVsX2lkGAUgASgJEhcKD2NyZWF0ZWRfYXRfdW5peBgGIAEoAxIRCgV0aXRsZRgHIAEoCUICGAESIwoFb3duZXIYCCABKAsyFC5tZWNhdGwudjEuUHJpbmNpcGFsEgwKBGtpbmQYCSABKAkSNAoMcmVsYXRpb25zaGlwGAogASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASPQoMY2FwYWJpbGl0aWVzGAsgASgLMicubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcmVhc29uX2NvZGUYDCABKAkSHAoQdGl0bGVfcHJvdmVuYW5jZRgOIAEoCUICGAESLwoJcGxhY2VtZW50GA8gASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBAgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI+Cgt0b2tlbl91c2FnZRgRIAMoCzIpLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeS5Ub2tlblVzYWdlRW50cnkSFgoOYWN0aXZpdHlfc3RhdGUYEiABKAkaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECA0QDlIJd29ya3NwYWNlIuYBChNTZXNzaW9uUmVsYXRpb25zaGlwEhkKEXBhcmVudF9zZXNzaW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSGQoMYnJhbmNoX2luZGV4GAMgASgFSACIAQESFQoNc2NoZWR1bGVfbmFtZRgEIAEoCRIZChFvcmlnaW5fc2Vzc2lvbl9pZBgFIAEoCRIPCgd0ZWFtX2lkGAYgASgJEhMKC21lbWJlcl9uYW1lGAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAggASgJQg8KDV9icmFuY2hfaW5kZXgikgIKHFNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcHVibGljX2NoYXQYASABKAgSDwoHaW5zcGVjdBgCIAEoCBIgChhhdXRob3JpdGF0aXZlX3RyYW5zY3JpcHQYAyABKAgSFwoPYWN0aXZpdHlfcmVwbGF5GAQgASgIEg8KB2NvcHlfaWQYBSABKAgSFwoPdmlld190cmFuc2NyaXB0GAYgASgIEgwKBGZvcmsYByABKAgSDgoGcmVuYW1lGAggASgIEg4KBmRlbGV0ZRgJIAEoCBI5CgdyZWFzb25zGAogASgLMigubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlBY3Rpb25SZWFzb25zIp0BCh1TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucxITCgtwdWJsaWNfY2hhdBgBIAEoCRIPCgdpbnNwZWN0GAIgASgJEg8KB2NvcHlfaWQYAyABKAkSFwoPdmlld190cmFuc2NyaXB0GAQgASgJEgwKBGZvcmsYBSABKAkSDgoGcmVuYW1lGAYgASgJEg4KBmRlbGV0ZRgHIAEoCSJtChRMaXN0U2Vzc2lvbnNSZXNwb25zZRIrCghzZXNzaW9ucxgBIAMoCzIZLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeRITCgtuZXh0X2N1cnNvchgCIAEoCRITCgt0b3RhbF9jb3VudBgDIAEoBSIZChdHZXRTdG9yYWdlSGVhbHRoUmVxdWVzdCLeAQoPUmV0ZW50aW9uUG9saWN5EhwKFG1haW5fbWF4X2FnZV9zZWNvbmRzGAEgASgDEhYKDm1haW5fbWF4X2NvdW50GAIgASgFEh0KFWNoaWxkX21heF9hZ2Vfc2Vjb25kcxgDIAEoAxIXCg9jaGlsZF9tYXhfY291bnQYBCABKAUSIQoZc2NoZWR1bGVkX21heF9hZ2Vfc2Vjb25kcxgFIAEoAxIbChNzY2hlZHVsZWRfbWF4X2NvdW50GAYgASgFEh0KFXN3ZWVwX2NhZGVuY2Vfc2Vjb25kcxgHIAEoAyLJBwoYR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEhEKCWF2YWlsYWJsZRgBIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAiABKAkSFQoNY3VycmVudF9ieXRlcxgDIAEoAxIfChdjdXJyZW50X2J5dGVzX2F2YWlsYWJsZRgEIAEoCBIZChFyZWNsYWltYWJsZV9ieXRlcxgFIAEoAxIjChtyZWNsYWltYWJsZV9ieXRlc19hdmFpbGFibGUYBiABKAgSFQoNc2Vzc2lvbl9jb3VudBgHIAEoAxISCgpmaWxlX2NvdW50GAggASgDEhAKCHYxX2NvdW50GAkgASgDEhAKCHYyX2NvdW50GAogASgDEhIKCm1haW5fY291bnQYCyABKAMSEwoLY2hpbGRfY291bnQYDCABKAMSFwoPc2NoZWR1bGVkX2NvdW50GA0gASgDEhUKDXVua25vd25fY291bnQYDiABKAMSFQoNY29ycnVwdF9jb3VudBgPIAEoAxIqCgZwb2xpY3kYECABKAsyGi5tZWNhdGwudjEuUmV0ZW50aW9uUG9saWN5EhcKD2xhc3Rfc3dlZXBfdW5peBgRIAEoAxIcChRsYXN0X3N3ZWVwX2F2YWlsYWJsZRgSIAEoCBIXCg9uZXh0X3N3ZWVwX3VuaXgYEyABKAMSHAoUbmV4dF9zd2VlcF9hdmFpbGFibGUYFCABKAgSEgoKYWN0aXZlX2pvYhgVIAEoCRIUCgxsYXN0X2ZhaWx1cmUYFiABKAkSJAocb3duZXJsZXNzX3Nlc3Npb25zX2F2YWlsYWJsZRgXIAEoCBItCiVvd25lcmxlc3Nfc2Vzc2lvbnNfdW5hdmFpbGFibGVfcmVhc29uGBggASgJEh8KF293bmVybGVzc19zZXNzaW9uX2NvdW50GBkgASgDEh0KFW93bmVybGVzc19zZXNzaW9uX2lkcxgaIAMoCRInCh9vd25lcmxlc3Nfc2Vzc2lvbl9pZHNfdHJ1bmNhdGVkGBsgASgIEiUKHW93bmVybGVzc19zY2hlZHVsZXNfYXZhaWxhYmxlGBwgASgIEi4KJm93bmVybGVzc19zY2hlZHVsZXNfdW5hdmFpbGFibGVfcmVhc29uGB0gASgJEiAKGG93bmVybGVzc19zY2hlZHVsZV9jb3VudBgeIAEoAxIgChhvd25lcmxlc3Nfc2NoZWR1bGVfbmFtZXMYHyADKAkSKgoib3duZXJsZXNzX3NjaGVkdWxlX25hbWVzX3RydW5jYXRlZBggIAEoCCIdChtQbGFuU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3Qi/wEKFFNlc3Npb25NaWdyYXRpb25QbGFuEg8KB3BsYW5faWQYASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRITCgt2MV9mYW1pbGllcxgEIAEoAxITCgt2Ml9mYW1pbGllcxgFIAEoAxIYChBpbnZhbGlkX2ZhbWlsaWVzGAYgASgDEhgKEHNraXBwZWRfZmFtaWxpZXMYByABKAMSFQoNY3VycmVudF9ieXRlcxgIIAEoAxIZChFyZWNsYWltYWJsZV9ieXRlcxgJIAEoAxIXCg90ZW1wb3JhcnlfYnl0ZXMYCiABKAMiTAocQXBwbHlTZXNzaW9uTWlncmF0aW9uUmVxdWVzdBIYCgdwbGFuX2lkGAEgASgJQge6SARyAhABEhIKCmJhdGNoX3NpemUYAiABKAUiTAodUmVzdW1lU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABEhIKCmJhdGNoX3NpemUYAiABKAUiOAodQ2FuY2VsU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjgKHUdldFNlc3Npb25NaWdyYXRpb25Kb2JSZXF1ZXN0EhcKBmpvYl9pZBgBIAEoCUIHukgEcgIQASJWChlTZXNzaW9uTWlncmF0aW9uSXRlbUVycm9yEhMKC2l0ZW1faGFuZGxlGAEgASgJEhMKC3JlYXNvbl9jb2RlGAIgASgJEg8KB21lc3NhZ2UYAyABKAki2QIKDUNsZWFudXBDb3VudHMSDQoFdG90YWwYASABKAUSNQoHYnlfa2luZBgCIAMoCzIkLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5S2luZEVudHJ5EjcKCGJ5X3N0YXRlGAMgAygLMiUubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlTdGF0ZUVudHJ5EjkKCWJ5X3JlYXNvbhgEIAMoCzImLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5UmVhc29uRW50cnkaLQoLQnlLaW5kRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARouCgxCeVN0YXRlRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARovCg1CeVJlYXNvbkVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEihgEKEENsZWFudXBDYW5kaWRhdGUSEgoKc2Vzc2lvbl9pZBgBIAEoCRIMCgRraW5kGAIgASgJEg0KBXN0YXRlGAMgASgJEg4KBnJlYXNvbhgEIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAUgASgDEhcKD2VzdGltYXRlZF9ieXRlcxgGIAEoAyIqChlQbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0Eg0KBWtpbmRzGAEgAygJItMCChpQbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRIaChJjb25maXJtYXRpb25fdG9rZW4YASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRISCgpnZW5lcmF0aW9uGAQgASgJEhYKDnBvbGljeV92ZXJzaW9uGAUgASgJEi0KCGVsaWdpYmxlGAYgAygLMhsubWVjYXRsLnYxLkNsZWFudXBDYW5kaWRhdGUSKwoJcHJvdGVjdGVkGAcgASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMSFwoPZXN0aW1hdGVkX2J5dGVzGAggASgDEhYKDnBsYW5uZWRfam9iX2lkGAkgASgJEjEKD2VsaWdpYmxlX2NvdW50cxgKIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzIkEKGkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0EiMKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCUIHukgEcgIQASI2ChtDYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjYKG0dldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiTQoQQ2xlYW51cEl0ZW1FcnJvchITCgtpdGVtX2hhbmRsZRgBIAEoCRITCgtyZWFzb25fY29kZRgCIAEoCRIPCgdtZXNzYWdlGAMgASgJIsgCChNTZXNzaW9uTWlncmF0aW9uSm9iEg4KBmpvYl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRITCgt2MV9mYW1pbGllcxgDIAEoAxITCgt2Ml9mYW1pbGllcxgEIAEoAxIYChBpbnZhbGlkX2ZhbWlsaWVzGAUgASgDEhgKEHNraXBwZWRfZmFtaWxpZXMYBiABKAMSFQoNY3VycmVudF9ieXRlcxgHIAEoAxIZChFyZWNsYWltYWJsZV9ieXRlcxgIIAEoAxIXCg90ZW1wb3JhcnlfYnl0ZXMYCSABKAMSEQoJcHJvY2Vzc2VkGAogASgDEhAKCG1pZ3JhdGVkGAsgASgDEg4KBmZhaWxlZBgMIAEoAxI0CgZlcnJvcnMYDSADKAsyJC5tZWNhdGwudjEuU2Vzc2lvbk1pZ3JhdGlvbkl0ZW1FcnJvciKsAQoKQ2xlYW51cEpvYhIOCgZqb2JfaWQYASABKAkSDQoFc3RhdGUYAiABKAkSEQoJcHJvY2Vzc2VkGAMgASgFEg8KB2RlbGV0ZWQYBCABKAUSDwoHc2tpcHBlZBgFIAEoBRINCgVzdGFsZRgGIAEoBRIOCgZmYWlsZWQYByABKAUSKwoGZXJyb3JzGAggAygLMhsubWVjYXRsLnYxLkNsZWFudXBJdGVtRXJyb3IiVgoOU2V0TW9kZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlIjYKD1NldE1vZGVSZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iMgoTQ2xvc2VTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhYKFENsb3NlU2Vzc2lvblJlc3BvbnNlIksKFFJlbmFtZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESFgoFdGl0bGUYAiABKAlCB7pIBHICEAEiPAoVUmVuYW1lU2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIzChREZWxldGVTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhcKFURlbGV0ZVNlc3Npb25SZXNwb25zZSJvChNDbGVhclNlc3Npb25SZXF1ZXN0EiIKEXNvdXJjZV9zZXNzaW9uX2lkGAEgASgJQge6SARyAhABEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAIgASgJSACIAQFCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIlsKFENsZWFyU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIr4BChJGb3JrU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESDQoFdGl0bGUYAiABKAkSGAoQcmVhc29uaW5nX2VmZm9ydBgDIAEoCRIeChF3b3JrdHJlZV9zZWxlY3RvchgEIAEoCUgAiAEBEhMKC3Byb3ZpZGVyX2lkGAUgASgJEhAKCG1vZGVsX2lkGAYgASgJQhQKEl93b3JrdHJlZV9zZWxlY3RvciJaChNGb3JrU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIpoGCgdTZXNzaW9uEhIKCnNlc3Npb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkSJwoEbW9kZRgDIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIhCgZsaW1pdHMYBSABKAsyES5tZWNhdGwudjEuTGltaXRzEg0KBXR1cm5zGAYgASgFEhIKCnRvb2xfY2FsbHMYByABKAUSFwoPY3JlYXRlZF9hdF91bml4GAggASgDEjAKDnJlc29sdmVkX21vZGVsGAkgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSEQoFdGl0bGUYCiABKAlCAhgBEhwKEHRpdGxlX3Byb3ZlbmFuY2UYDCABKAlCAhgBEjMKDGNhcGFiaWxpdGllcxgLIAEoCzIdLm1lY2F0bC52MS5TZXJ2ZXJDYXBhYmlsaXRpZXMSDAoEa2luZBgOIAEoCRI0CgxyZWxhdGlvbnNoaXAYDyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFkZWJ1Z19tY3Bfc2VydmVycxgQIAMoCRIXCg9kZWJ1Z19tY3BfdG9vbHMYESADKAkSLwoJcGxhY2VtZW50GBIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBMgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI3Cgt0b2tlbl91c2FnZRgUIAMoCzIiLm1lY2F0bC52MS5TZXNzaW9uLlRva2VuVXNhZ2VFbnRyeRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgVIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzGkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgEEAVKBAgNEA5SCXdvcmtzcGFjZVIaYWRvcHRpb25fc291cmNlX3Nlc3Npb25faWQilQEKDFNlc3Npb25UaXRsZRINCgV0aXRsZRgBIAEoCRISCgpwcm92ZW5hbmNlGAIgASgJEhgKEGdlbmVyYXRpb25fc3RhdGUYAyABKAkSNgoObGF0ZXN0X2F0dGVtcHQYBCABKAsyHi5tZWNhdGwudjEuVGl0bGVBdHRlbXB0U3VtbWFyeRIQCghyZXZpc2lvbhgFIAEoBCI4ChNUaXRsZUF0dGVtcHRTdW1tYXJ5EgoKAmlkGAEgASgJEg8KB291dGNvbWUYAiABKAlKBAgDEAQioQEKClRva2VuVXNhZ2USHwoFdG90YWwYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USMQoGbW9kZWxzGAIgAygLMiEubWVjYXRsLnYxLlRva2VuVXNhZ2UuTW9kZWxzRW50cnkaPwoLTW9kZWxzRW50cnkSCwoDa2V5GAEgASgJEh8KBXZhbHVlGAIgASgLMhAubWVjYXRsLnYxLlVzYWdlOgI4ASLEAgoPQ29udmVyc2VSZXF1ZXN0EiMKBnByb21wdBgBIAEoCzIRLm1lY2F0bC52MS5Qcm9tcHRIABImCgVyZXRyeRgCIAEoCzIVLm1lY2F0bC52MS5SZXRyeVN0YXJ0SAASNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAEi4KDGNhbmNlbF9jaGlsZBgMIAEoCzIWLm1lY2F0bC52MS5DYW5jZWxDaGlsZEgAEiEKBXN0ZWVyGA0gASgLMhAubWVjYXRsLnYxLlN0ZWVySAASLgoMc3RlZXJfY2FuY2VsGA4gASgLMhYubWVjYXRsLnYxLlN0ZWVyQ2FuY2VsSABCBgoEa2luZCIzChBDb252ZXJzZVJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpwBCgdDb250ZW50EiUKBGtpbmQYASABKA4yFy5tZWNhdGwudjEuQ29udGVudC5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCSI8CgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABIOCgpLSU5EX0lNQUdFEAESDgoKS0lORF9BVURJTxACIpADCgxDb250ZW50QmxvY2sSKgoEa2luZBgBIAEoDjIcLm1lY2F0bC52MS5Db250ZW50QmxvY2suS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkSDAoEdGV4dBgFIAEoCRIMCgRuYW1lGAYgASgJEg0KBXRpdGxlGAcgASgJEhMKC2Rlc2NyaXB0aW9uGAggASgJEgwKBHNpemUYCSABKAMSEAoIYXVkaWVuY2UYCiADKAkSEAoIcHJpb3JpdHkYCyABKAESFQoNbGFzdF9tb2RpZmllZBgMIAEoCSKcAQoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDQoJS0lORF9URVhUEAESDgoKS0lORF9JTUFHRRACEg4KCktJTkRfQVVESU8QAxIWChJLSU5EX1JFU09VUkNFX0xJTksQBBIaChZLSU5EX0VNQkVEREVEX1JFU09VUkNFEAUSGwoXS0lORF9TVFJVQ1RVUkVEX0NPTlRFTlQQBiIpCgpSZXRyeVN0YXJ0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiVgoGUHJvbXB0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEdGV4dBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50In4KDlJlc3VtZUFwcHJvdmFsEhcKBmFza19pZBgBIAEoCUIHukgEcgIQARINCgVhbGxvdxgCIAEoCBIrCgd2ZXJkaWN0GAMgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiIQoGQ2FuY2VsEhcKD2V4cGVjdGVkX3J1bl9pZBgBIAEoCSIoCgtDYW5jZWxDaGlsZBIZCghjaGlsZF9pZBgBIAEoCUIHukgEcgIQASJlCgVTdGVlchIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiOgoLU3RlZXJDYW5jZWwSEgoKbWVzc2FnZV9pZBgBIAEoCRIXCg9leHBlY3RlZF9ydW5faWQYAiABKAkiaAomR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIhChBhdXRob3JpemF0aW9uX2lkGAIgASgJQge6SARyAhABIjYKJ0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRILCgN1cmwYASABKAkitAEKHlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhgKEGF1dGhvcml6YXRpb25faWQYAiABKAkSNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAQgkKB2NvbnRyb2wiQgofUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKzAQodQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkEKHkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKQAQoNQXV0aG9yaXphdGlvbhIYChBhdXRob3JpemF0aW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGc3RhdHVzGAQgASgJEhQKDGRpc3BsYXlfbmFtZRgFIAEoCSLQBgoFRXZlbnQSDAoEdHlwZRgBIAEoCRILCgNzZXEYAiABKAMSDAoEdHVybhgDIAEoBRIMCgR0ZXh0GAQgASgJEiYKCXRvb2xfY2FsbBgFIAEoCzITLm1lY2F0bC52MS5Ub29sQ2FsbBIqCgt0b29sX3Jlc3VsdBgGIAEoCzIVLm1lY2F0bC52MS5Ub29sUmVzdWx0EiUKA2FzaxgHIAEoCzIYLm1lY2F0bC52MS5QZXJtaXNzaW9uQXNrEiEKBnJlc3VsdBgIIAEoCzIRLm1lY2F0bC52MS5SZXN1bHQSHwoFdXNhZ2UYCSABKAsyEC5tZWNhdGwudjEuVXNhZ2USJAoIdHVybl9lbmQYCiABKAsyEi5tZWNhdGwudjEuVHVybkVuZBIdCgRob29rGAsgASgLMg8ubWVjYXRsLnYxLkhvb2sSJQoIc3ViYWdlbnQYDCABKAsyEy5tZWNhdGwudjEuU3ViYWdlbnQSHQoEdGVhbRgNIAEoCzIPLm1lY2F0bC52MS5UZWFtEiUKCHBhcmFsbGVsGA4gASgLMhMubWVjYXRsLnYxLlBhcmFsbGVsEiwKCHNjaGVkdWxlGA8gASgLMhoubWVjYXRsLnYxLlNjaGVkdWxlUGF5bG9hZBIlCghhcHByb3ZhbBgQIAEoCzITLm1lY2F0bC52MS5BcHByb3ZhbBIqCgt1c2VyX3Byb21wdBgRIAEoCzIVLm1lY2F0bC52MS5Vc2VyUHJvbXB0EjgKEmNvbXBhY3Rpb25fYXJjaGl2ZRgSIAEoCzIcLm1lY2F0bC52MS5Db21wYWN0aW9uQXJjaGl2ZRIjCgVzdGVlchgTIAEoCzIULm1lY2F0bC52MS5TdGVlckVjaG8SKgoNc3RlZXJfb3V0Y29tZRgUIAEoCzITLm1lY2F0bC52MS5TdGVlckFjaxIqCgttb2RlbF9yZXRyeRgVIAEoCzIVLm1lY2F0bC52MS5Nb2RlbFJldHJ5Eg4KBnJ1bl9pZBgWIAEoCRImCgV0aXRsZRgXIAEoCzIXLm1lY2F0bC52MS5TZXNzaW9uVGl0bGUSLwoNYXV0aG9yaXphdGlvbhgYIAEoCzIYLm1lY2F0bC52MS5BdXRob3JpemF0aW9uIngKCk1vZGVsUmV0cnkSNgoRcmV0cnlfZGlzcG9zaXRpb24YASABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbhIyCg9zdHJlYW1fcHJvZ3Jlc3MYAiABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3MiUAoJU3RlZXJFY2hvEgwKBHRleHQYASABKAkSEgoKbWVzc2FnZV9pZBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50ImgKCFN0ZWVyQWNrEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEgwKBHRleHQYAiABKAkSEAoIcHJvbW90ZWQYAyABKAgSEgoKbWVzc2FnZV9pZBgEIAEoCSJgCghBcHByb3ZhbBIOCgZhc2tfaWQYASABKAkSDwoHdmVyZGljdBgCIAEoCRIMCgR0b29sGAMgASgJEg8KB2NhbGxfaWQYBCABKAkSFAoMYWxsb3dfYWx3YXlzGAUgASgIIlAKClVzZXJQcm9tcHQSDAoEdGV4dBgBIAEoCRIhCgVwYXJ0cxgCIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhEKCXN5bnRoZXRpYxgDIAEoCCJFChFDb21wYWN0aW9uQXJjaGl2ZRIwCghyZXBsYWNlZBgBIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlIu8BChNDb252ZXJzYXRpb25NZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCRInCgp0b29sX2NhbGxzGAMgAygLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAQgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSEQoJcmVhc29uaW5nGAUgASgJEhYKDnByb3ZpZGVyX3BoYXNlGAYgASgJEiEKBXBhcnRzGAcgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSGQoRcmVhc29uaW5nX2l0ZW1faWQYCCABKAkidgoPU2NoZWR1bGVQYXlsb2FkEhUKDXNjaGVkdWxlX25hbWUYASABKAkSDwoHZmlyZV9pZBgCIAEoCRISCgpzZXNzaW9uX2lkGAMgASgJEgwKBGtpbmQYBCABKAkSDAoEc3RvcBgFIAEoCRILCgNlcnIYBiABKAkiXwoESG9vaxINCgVwaGFzZRgBIAEoCRIMCgR0b29sGAIgASgJEikKCGRlY2lzaW9uGAMgASgOMhcubWVjYXRsLnYxLkhvb2tEZWNpc2lvbhIPCgdjYWxsX2lkGAQgASgJIuoCCghTdWJhZ2VudBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIQCghjaGlsZF9pZBgCIAEoCRIMCgRnb2FsGAMgASgJEhEKCXRvb2xfbmFtZRgEIAEoCRIQCghpc19lcnJvchgFIAEoCBISCgp0b29sX2NvdW50GAYgASgFEh8KBXVzYWdlGAcgASgLMhAubWVjYXRsLnYxLlVzYWdlEgwKBHN0b3AYCCABKAkSEwoLZHVyYXRpb25fbXMYCSABKAMSEgoKYmFja2dyb3VuZBgKIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYCyABKAkSFAoMcm91dGVkX21vZGVsGAwgASgJEg0KBW1vZGVsGA0gASgJEhIKCmlubmVyX2tpbmQYDiABKAkSDAoEdGV4dBgPIAEoCRIOCgZkZXRhaWwYECABKAkSDQoFY2F1c2UYESABKAkSFgoOcm91dGluZ19yZWFzb24YEiABKAkiogEKDlRlYW1NZW1iZXJTcGVjEgwKBG5hbWUYASABKAkSDAoEcm9sZRgCIAEoCRIQCghtdXRhdGluZxgDIAEoCBIMCgRsZWFkGAQgASgIEhcKD3JvdXRlZF9jYXRlZ29yeRgFIAEoCRIUCgxyb3V0ZWRfbW9kZWwYBiABKAkSDQoFbW9kZWwYByABKAkSFgoOcm91dGluZ19yZWFzb24YCCABKAki3gMKBFRlYW0SFgoOcGFyZW50X2NhbGxfaWQYASABKAkSDwoHdGVhbV9pZBgCIAEoCRIpCgZyb3N0ZXIYAyADKAsyGS5tZWNhdGwudjEuVGVhbU1lbWJlclNwZWMSDgoGbWVtYmVyGAQgASgJEhIKCmlubmVyX2tpbmQYBSABKAkSDAoEdGV4dBgGIAEoCRIRCgl0b29sX25hbWUYByABKAkSDgoGZGV0YWlsGAggASgJEhAKCGlzX2Vycm9yGAkgASgIEg4KBnJvdW5kcxgKIAEoBRIMCgRzdG9wGAsgASgJEh8KBXVzYWdlGAwgASgLMhAubWVjYXRsLnYxLlVzYWdlEhQKDGNvbnRleHRfdXNlZBgNIAEoAxIWCg5jb250ZXh0X3dpbmRvdxgOIAEoAxIiCgV0YXNrcxgPIAMoCzITLm1lY2F0bC52MS5UZWFtVGFzaxIoCghmaW5kaW5ncxgQIAMoCzIWLm1lY2F0bC52MS5UZWFtRmluZGluZxI2CgxkaXNwb3NpdGlvbnMYESADKAsyIC5tZWNhdGwudjEuVGVhbU1lbWJlckRpc3Bvc2l0aW9uEhkKEW1lbWJlcl9zZXNzaW9uX2lkGBIgASgJEg0KBWNhdXNlGBMgASgJIu4DCghQYXJhbGxlbBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIMCgRraW5kGAIgASgJEgwKBGpvaW4YAyABKAkSFAoMYnJhbmNoX2NvdW50GAQgASgFEhQKDGJyYW5jaF9pbmRleBgFIAEoBRIUCgxicmFuY2hfbGFiZWwYBiABKAkSDAoEZ29hbBgHIAEoCRIRCgl0b29sX25hbWUYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSEgoKdG9vbF9jb3VudBgKIAEoBRIOCgZmYWlsZWQYCyABKAgSDAoEc3RvcBgNIAEoCRIfCgV1c2FnZRgOIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgPIAEoAxIOCgZ3aW5uZXIYECABKAUSEAoIY2hpbGRfaWQYEiABKAkSFwoPcm91dGVkX2NhdGVnb3J5GBMgASgJEhQKDHJvdXRlZF9tb2RlbBgUIAEoCRINCgVtb2RlbBgVIAEoCRISCgppbm5lcl9raW5kGBYgASgJEgwKBHRleHQYFyABKAkSDgoGZGV0YWlsGBggASgJEhYKDnJvdXRpbmdfcmVhc29uGBkgASgJSgQIDBANSgQIERASUgl3b3Jrc3BhY2VSEHdpbm5lcl93b3Jrc3BhY2UiMgoIVG9vbENhbGwSCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRhcmdzGAMgASgJIoUBCgpUb29sUmVzdWx0Eg8KB2NhbGxfaWQYASABKAkSDwoHY29udGVudBgCIAEoCRIQCghpc19lcnJvchgDIAEoCBInCgZibG9ja3MYBCADKAsyFy5tZWNhdGwudjEuQ29udGVudEJsb2NrEhoKEnN0cnVjdHVyZWRfY29udGVudBgFIAEoCSJLCg1QZXJtaXNzaW9uQXNrEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAIgASgJEgwKBGFyZ3MYAyABKAkSDgoGcmVhc29uGAQgASgJIocCCgZSZXN1bHQSDAoEc3RvcBgBIAEoCRIMCgR0ZXh0GAIgASgJEh8KBXVzYWdlGAMgASgLMhAubWVjYXRsLnYxLlVzYWdlEg0KBWVycm9yGAQgASgJEhEKCXBlcm1hbmVudBgFIAEoCBI7ChFyZXRyeV9kaXNwb3NpdGlvbhgGIAEoDjIbLm1lY2F0bC52MS5SZXRyeURpc3Bvc2l0aW9uSACIAQESNwoPc3RyZWFtX3Byb2dyZXNzGAcgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzSAGIAQFCFAoSX3JldHJ5X2Rpc3Bvc2l0aW9uQhIKEF9zdHJlYW1fcHJvZ3Jlc3MiPwoHVHVybkVuZBIfCgV1c2FnZRgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgCIAEoAyKFAQoFVXNhZ2USFAoMaW5wdXRfdG9rZW5zGAEgASgDEhUKDW91dHB1dF90b2tlbnMYAiABKAMSGQoRY2FjaGVfcmVhZF90b2tlbnMYAyABKAMSGgoSY2FjaGVfd3JpdGVfdG9rZW5zGAQgASgDEhgKEHJlYXNvbmluZ190b2tlbnMYBSABKAMikAEKC01jcFJlc291cmNlEg4KBnNlcnZlchgBIAEoCRILCgN1cmkYAiABKAkSDAoEbmFtZRgDIAEoCRINCgV0aXRsZRgEIAEoCRITCgtkZXNjcmlwdGlvbhgFIAEoCRIRCgltaW1lX3R5cGUYBiABKAkSDAoEc2l6ZRgHIAEoAxIRCglyZWFkX29ubHkYCCABKAgiKQoXTGlzdE1jcFJlc291cmNlc1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIkUKGExpc3RNY3BSZXNvdXJjZXNSZXNwb25zZRIpCglyZXNvdXJjZXMYASADKAsyFi5tZWNhdGwudjEuTWNwUmVzb3VyY2UiUQoTTWNwUmVzb3VyY2VDb250ZW50cxILCgN1cmkYASABKAkSEQoJbWltZV90eXBlGAIgASgJEgwKBHRleHQYAyABKAkSDAoEYmxvYhgEIAEoDCJHChZSZWFkTWNwUmVzb3VyY2VSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIUCgN1cmkYAiABKAlCB7pIBHICEAEiSwoXUmVhZE1jcFJlc291cmNlUmVzcG9uc2USMAoIY29udGVudHMYASADKAsyHi5tZWNhdGwudjEuTWNwUmVzb3VyY2VDb250ZW50cyJXChFNY3BQcm9tcHRBcmd1bWVudBIMCgRuYW1lGAEgASgJEg0KBXRpdGxlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEhAKCHJlcXVpcmVkGAQgASgIIn4KCU1jcFByb21wdBIOCgZzZXJ2ZXIYASABKAkSDAoEbmFtZRgCIAEoCRINCgV0aXRsZRgDIAEoCRITCgtkZXNjcmlwdGlvbhgEIAEoCRIvCglhcmd1bWVudHMYBSADKAsyHC5tZWNhdGwudjEuTWNwUHJvbXB0QXJndW1lbnQiJwoVTGlzdE1jcFByb21wdHNSZXF1ZXN0Eg4KBnNlcnZlchgBIAEoCSI/ChZMaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEiUKB3Byb21wdHMYASADKAsyFC5tZWNhdGwudjEuTWNwUHJvbXB0IrkBChNHZXRNY3BQcm9tcHRSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIVCgRuYW1lGAIgASgJQge6SARyAhABEkAKCWFyZ3VtZW50cxgDIAMoCzItLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0LkFyZ3VtZW50c0VudHJ5GjAKDkFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiLgoQTWNwUHJvbXB0TWVzc2FnZRIMCgRyb2xlGAEgASgJEgwKBHRleHQYAiABKAkiWgoUR2V0TWNwUHJvbXB0UmVzcG9uc2USEwoLZGVzY3JpcHRpb24YASABKAkSLQoIbWVzc2FnZXMYAiADKAsyGy5tZWNhdGwudjEuTWNwUHJvbXB0TWVzc2FnZSJMCg1NY3BTZXJ2ZXJJbmZvEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEhEKCXRyYW5zcG9ydBgDIAEoCRINCgVncm91cBgEIAEoCSKHAQoJTWNwU291cmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCRIPCgdlbmFibGVkGAMgASgIEg0KBWdyb3VwGAQgASgJEikKB3NlcnZlcnMYBSADKAsyGC5tZWNhdGwudjEuTWNwU2VydmVySW5mbxITCgtkaWFnbm9zdGljcxgGIAMoCSIXChVMaXN0TWNwU291cmNlc1JlcXVlc3QiPwoWTGlzdE1jcFNvdXJjZXNSZXNwb25zZRIlCgdzb3VyY2VzGAEgAygLMhQubWVjYXRsLnYxLk1jcFNvdXJjZSIbChlMaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0IiwKGkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEg4KBmdyb3VwcxgBIAMoCSJ0CglBZ2VudEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVtb2RlbBgDIAEoCRINCgV0b29scxgEIAMoCRIXCg9wZXJtaXNzaW9uX21vZGUYBSABKAkSDQoFY29sb3IYBiABKAkiEwoRTGlzdEFnZW50c1JlcXVlc3QiOgoSTGlzdEFnZW50c1Jlc3BvbnNlEiQKBmFnZW50cxgBIAMoCzIULm1lY2F0bC52MS5BZ2VudEluZm8iLAoHQ29tbWFuZBIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIjIKE0xpc3RDb21tYW5kc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI8ChRMaXN0Q29tbWFuZHNSZXNwb25zZRIkCghjb21tYW5kcxgBIAMoCzISLm1lY2F0bC52MS5Db21tYW5kImkKCFdvcmt0cmVlEhAKCHNlbGVjdG9yGAEgASgJEgwKBGtpbmQYAiABKAkSDQoFbGFiZWwYAyABKAkSDgoGYnJhbmNoGAQgASgJEhAKCHJldmlzaW9uGAUgASgJEgwKBGJhcmUYBiABKAgiMwoUTGlzdFdvcmt0cmVlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI/ChVMaXN0V29ya3RyZWVzUmVzcG9uc2USJgoJd29ya3RyZWVzGAEgAygLMhMubWVjYXRsLnYxLldvcmt0cmVlInAKCVNraWxsSW5mbxIMCgRuYW1lGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEhMKC2FnZW50X293bmVkGAMgASgIEhMKC293bmVyX2FnZW50GAQgASgJEhYKDmFjdGl2ZV92ZXJzaW9uGAUgASgJIhMKEUxpc3RTa2lsbHNSZXF1ZXN0IjoKEkxpc3RTa2lsbHNSZXNwb25zZRIkCgZza2lsbHMYASADKAsyFC5tZWNhdGwudjEuU2tpbGxJbmZvIqEBCghTb3VsSW5mbxIPCgdjb250ZW50GAEgASgJEhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEg8KB3ByZXNlbnQYBCABKAgSLQoKcHJvdmVuYW5jZRgFIAEoDjIZLm1lY2F0bC52MS5Tb3VsUHJvdmVuYW5jZRIPCgd0cnVzdGVkGAYgASgIEg8KB2RyaWZ0ZWQYByABKAgiEAoOR2V0U291bFJlcXVlc3QiNAoPR2V0U291bFJlc3BvbnNlEiEKBHNvdWwYASABKAsyEy5tZWNhdGwudjEuU291bEluZm8iMgoOVXNlck1vZGVsRW50cnkSCwoDa2V5GAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJIiIKE0dldFVzZXJNb2RlbFJlcXVlc3QSCwoDa2V5GAEgASgJIpYCChFVc2VyTW9kZWxSZXZpc2lvbhILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIOCgZzdGF0dXMYBSABKAkSDgoGd3JpdGVyGAYgASgJEg4KBm9yaWdpbhgHIAEoCRIZChFzb3VyY2Vfc2Vzc2lvbl9pZBgIIAEoCRIaChJzb3VyY2VfcHJvcG9zYWxfaWQYCSABKAkSLgoKdXBkYXRlZF9hdBgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBKBAgKEAtSD3NvdXJjZV9ldmVudF9pZFIRc291cmNlX21lc3NhZ2VfaWQiigEKD1VzZXJNb2RlbERldGFpbBItCgdjdXJyZW50GAEgASgLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEi0KB2hpc3RvcnkYAiADKAsyHC5tZWNhdGwudjEuVXNlck1vZGVsUmV2aXNpb24SGQoRaGlzdG9yeV9hdmFpbGFibGUYAyABKAgikgEKFEdldFVzZXJNb2RlbFJlc3BvbnNlEioKB2VudHJpZXMYASADKAsyGS5tZWNhdGwudjEuVXNlck1vZGVsRW50cnkSEgoKc2l6ZV9ieXRlcxgCIAEoAxIOCgZzaGEyNTYYAyABKAkSKgoGZGV0YWlsGAQgASgLMhoubWVjYXRsLnYxLlVzZXJNb2RlbERldGFpbCJ7CglNb2RlbEluZm8SCgoCaWQYASABKAkSEwoLcHJvdmlkZXJfaWQYAiABKAkSFAoMZGlzcGxheV9uYW1lGAMgASgJEg0KBWltYWdlGAQgASgIEhEKCXJlYXNvbmluZxgFIAEoCBIVCg1jb250ZXh0X2xpbWl0GAYgASgDIhMKEUxpc3RNb2RlbHNSZXF1ZXN0IpsBCg5Qcm92aWRlclN0YXR1cxITCgtwcm92aWRlcl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRIMCgRoaW50GAMgASgJEiMKG2RlZmF1bHRfbW9kZWxfYXV0b19zZWxlY3RlZBgEIAEoCBITCgttb2RlbF9jb3VudBgFIAEoBRIdChVhdmFpbGFibGVfbm90X2RlZmF1bHQYBiABKAgibgoSTGlzdE1vZGVsc1Jlc3BvbnNlEiQKBm1vZGVscxgBIAMoCzIULm1lY2F0bC52MS5Nb2RlbEluZm8SMgoPcHJvdmlkZXJfc3RhdHVzGAIgAygLMhkubWVjYXRsLnYxLlByb3ZpZGVyU3RhdHVzIkEKFVJlZmxlY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABSgQIAhADUgVhc3luYyK5AQoRUmVmbGVjdGlvblJlY2VpcHQSFQoNcmVmbGVjdGlvbl9pZBgBIAEoCRITCgtkaXNwb3NpdGlvbhgCIAEoCRIOCgZxdWV1ZWQYAyABKAUSEQoJYWJzdGFpbmVkGAQgASgIEg4KBnN0YWdlZBgFIAEoBRIQCghwcm9tb3RlZBgGIAEoBRISCgpjb25mbGljdGVkGAcgASgFEg4KBnJlYXNvbhgIIAEoCRIPCgdtZXNzYWdlGAkgASgJIkcKFlJlZmxlY3RTZXNzaW9uUmVzcG9uc2USLQoHcmVjZWlwdBgBIAEoCzIcLm1lY2F0bC52MS5SZWZsZWN0aW9uUmVjZWlwdCLxAgoPTGVhcm5pbmdBdHRlbXB0EgoKAmlkGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSDwoHb3V0Y29tZRgEIAEoCRIUCgxmYWlsdXJlX2NvZGUYBSABKAkSGgoSYXR0ZW1wdF9nZW5lcmF0aW9uGAYgASgEEhgKEGNsYWltX2dlbmVyYXRpb24YByABKAQSNAoQY2xhaW1fZXhwaXJlc19hdBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGAoQY2hlY2twb2ludF9zdGFnZRgJIAEoCRITCgtwcm9wb3NhbF9pZBgKIAEoCRIQCghza2lsbF9pZBgLIAEoCRIuCgpjcmVhdGVkX2F0GAwgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA0gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCIwChlHZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIkkKGkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0IksKG0xpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBINCgVzdGF0ZRgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUiYQocTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRIsCghhdHRlbXB0cxgBIAMoCzIaLm1lY2F0bC52MS5MZWFybmluZ0F0dGVtcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkiVgocTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABIkwKHU11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEisKB2F0dGVtcHQYASABKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0Il4KHExpc3RMZWFybmluZ1Byb3Bvc2Fsc1JlcXVlc3QSDgoGc3RhdHVzGAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRIPCgdwcm9qZWN0GAQgASgJIr4BChNMZWFybmluZ0V2aWRlbmNlUmVmEhIKCnNlc3Npb25faWQYASABKAkSDwoHbG9jYXRvchgCIAEoCRIPCgdvcmRpbmFsGAMgASgFEhEKCWV2ZW50X3NlcRgEIAEoAxIUCgx0b29sX2NhbGxfaWQYBSABKAkSDgoGZGlnZXN0GAYgASgJEhEKCWF2YWlsYWJsZRgHIAEoCBIUCgxhdmFpbGFiaWxpdHkYCCABKAkSDwoHcHJldmlldxgJIAEoCSJnChBMZWFybmluZ0RlY2lzaW9uEgwKBGtpbmQYASABKAkSDQoFYWN0b3IYAiABKAkSDgoGcmVhc29uGAMgASgJEiYKAmF0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCJ5ChhMZWFybmluZ1Byb21vdGlvblJlY2VpcHQSEgoKbWVtb3J5X2tleRgBIAEoCRIXCg9wcmV2aW91c19leGlzdHMYAiABKAgSGAoQcHJldmlvdXNfdmVyc2lvbhgDIAEoCRIWCg5yZXN1bHRfdmVyc2lvbhgEIAEoCSKcBAoQTGVhcm5pbmdQcm9wb3NhbBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg4KBnN0YXR1cxgDIAEoCRIMCgRraW5kGAQgASgJEgsKA2tleRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRINCgV0aXRsZRgIIAEoCRIMCgRib2R5GAkgASgJEjAKCGV2aWRlbmNlGAogAygLMh4ubWVjYXRsLnYxLkxlYXJuaW5nRXZpZGVuY2VSZWYSEAoIdHJpZ2dlcnMYCyADKAkSLgoJZGVjaXNpb25zGAwgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nRGVjaXNpb24SNgoJcHJvbW90aW9uGA0gASgLMiMubWVjYXRsLnYxLkxlYXJuaW5nUHJvbW90aW9uUmVjZWlwdBIuCgpjcmVhdGVkX2F0GA4gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIuCgp1cGRhdGVkX2F0GA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIWCg5wcm9qZWN0X3Njb3BlZBgQIAEoCBIbChNwcm9tb3Rpb25fYXZhaWxhYmxlGBEgASgIEiQKHHByb21vdGlvbl91bmF2YWlsYWJsZV9yZWFzb24YEiABKAkSGAoQbGVhcm5lZF9za2lsbF9pZBgTIAEoCSJkCh1MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRIuCglwcm9wb3NhbHMYASADKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbBITCgtuZXh0X2N1cnNvchgCIAEoCSJCChpHZXRMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAIgASgJIkwKG0dldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIpMBCh1EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIhChBleHBlY3RlZF92ZXJzaW9uGAIgASgJQge6SARyAhABEhkKCGRlY2lzaW9uGAMgASgJQge6SARyAhABEg4KBnJlYXNvbhgEIAEoCRIPCgdwcm9qZWN0GAUgASgJIk8KHkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsImcKHFVuZG9MZWFybmluZ1Byb21vdGlvblJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIPCgdwcm9qZWN0GAMgASgJIk4KHVVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEi0KCHByb3Bvc2FsGAEgASgLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwi7AMKE0xlYXJuZWRTa2lsbFZlcnNpb24SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIPCgd2ZXJzaW9uGAMgASgJEhAKCHJldmlzaW9uGAQgASgJEg0KBXN0YXRlGAUgASgJEhMKC293bmVyX2FnZW50GAYgASgJEhMKC2Rlc2NyaXB0aW9uGAcgASgJEgwKBGJvZHkYCCABKAkSEgoKc3VwZXJzZWRlcxgJIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgKIAEoBRIwCghldmlkZW5jZRgLIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEi8KC2V2YWx1YXRpb25zGAwgAygLMhoubWVjYXRsLnYxLlNraWxsRXZhbHVhdGlvbhIvCghyZWNlaXB0cxgNIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgilAEKD1NraWxsRXZhbHVhdGlvbhIPCgd2ZXJkaWN0GAEgASgJEhMKC2ZpeHR1cmVfaWRzGAIgAygJEhAKCGJhc2VsaW5lGAMgASgJEhEKCXRyZWF0bWVudBgEIAEoCRIOCgZyZWFzb24YBSABKAkSJgoCYXQYBiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIoIDChJTa2lsbENoYW5nZVJlY2VpcHQSCgoCaWQYASABKAkSEAoIc2tpbGxfaWQYAiABKAkSDAoEbmFtZRgDIAEoCRIPCgd2ZXJzaW9uGAQgASgJEhEKCW9wZXJhdGlvbhgFIAEoCRISCgpmcm9tX3N0YXRlGAYgASgJEhAKCHRvX3N0YXRlGAcgASgJEhYKDmV2aWRlbmNlX2NvdW50GAggASgFEhoKEnNvdXJjZV9zZXNzaW9uX2lkcxgJIAMoCRIcChRzb3VyY2VfdG9vbF9jYWxsX2lkcxgKIAMoCRIPCgd2ZXJkaWN0GAsgASgJEhMKC2ZpeHR1cmVfaWRzGAwgAygJEhAKCGJhc2VsaW5lGA0gASgJEhEKCXRyZWF0bWVudBgOIAEoCRImCgJhdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGQoRaW5zcGVjdF9hdmFpbGFibGUYECABKAgSFgoOdW5kb19hdmFpbGFibGUYESABKAgibgoYTGlzdExlYXJuZWRTa2lsbHNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFEg0KBXN0YXRlGAQgASgJEhMKC293bmVyX2FnZW50GAUgASgJIoUBChlMaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlEi4KBnNraWxscxgBIAMoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhMKC25leHRfY3Vyc29yGAIgASgJEhIKCmdlbmVyYXRpb24YAyABKAQSDwoHcHJvamVjdBgEIAEoCSJtChZHZXRMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESDwoHdmVyc2lvbhgEIAEoCSJtChdHZXRMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCSKhAQofRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh0KDGZyb21fdmVyc2lvbhgEIAEoCUIHukgEcgIQARIbCgp0b192ZXJzaW9uGAUgASgJQge6SARyAhABIpEBCiBEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRIMCgRkaWZmGAEgASgJEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIQCghza2lsbF9pZBgEIAEoCRIUCgxmcm9tX3ZlcnNpb24YBSABKAkSEgoKdG9fdmVyc2lvbhgGIAEoCSKdAQoZTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEhgKB3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEipwEKGk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEi0KBXNraWxsGAEgASgLMh4ubWVjYXRsLnYxLkxlYXJuZWRTa2lsbFZlcnNpb24SEgoKZ2VuZXJhdGlvbhgCIAEoBBIPCgdwcm9qZWN0GAMgASgJEhoKEnB1YmxpY2F0aW9uX3N0YXR1cxgEIAEoCRIZChFwdWJsaWNhdGlvbl9lcnJvchgFIAEoCSKmAQobUm9sbGJhY2tMZWFybmVkU2tpbGxSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSHAoLb3duZXJfYWdlbnQYAiABKAlCB7pIBHICEAESEwoCaWQYAyABKAlCB7pIBHICEAESHwoOdGFyZ2V0X3ZlcnNpb24YBCABKAlCB7pIBHICEAESIgoRZXhwZWN0ZWRfcmV2aXNpb24YBSABKAlCB7pIBHICEAEiSQoXTGlzdFNraWxsQ2hhbmdlc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUihAEKGExpc3RTa2lsbENoYW5nZXNSZXNwb25zZRIuCgdjaGFuZ2VzGAEgAygLMh0ubWVjYXRsLnYxLlNraWxsQ2hhbmdlUmVjZWlwdBITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkijwEKEUNyZWF0ZVRlYW1SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEbmFtZRgCIAEoCRIoCgdtZW1iZXJzGAMgAygLMhcubWVjYXRsLnYxLlRlYW1tYXRlU3BlYxIMCgRnb2FsGAQgASgJEhcKD21heF90ZWFtX3Rva2VucxgFIAEoBSJNChJDcmVhdGVUZWFtUmVzcG9uc2USDwoHdGVhbV9pZBgBIAEoCRImCgdtZW1iZXJzGAIgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicQoMVGVhbW1hdGVTcGVjEhUKBG5hbWUYASABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgCIAEoCRIMCgRsZWFkGAMgASgIEhAKCG11dGF0aW5nGAQgASgIEhYKDmluaXRpYWxfcHJvbXB0GAUgASgJIpMBChRTcGF3blRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhUKBG5hbWUYAiABKAlCB7pIBHICEAESEgoKYWdlbnRfdHlwZRgDIAEoCRIMCgRsZWFkGAQgASgIEhAKCG11dGF0aW5nGAUgASgIEhYKDmluaXRpYWxfcHJvbXB0GAYgASgJIj4KFVNwYXduVGVhbW1hdGVSZXNwb25zZRIlCgZtZW1iZXIYASABKAsyFS5tZWNhdGwudjEuVGVhbU1lbWJlciJwChpTZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhMKAnRvGAIgASgJQge6SARyAhABEgwKBGZyb20YAyABKAkSFQoEYm9keRgEIAEoCUIHukgEcgIQASIdChtTZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2UiSgoVQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAESFwoGbWVtYmVyGAIgASgJQge6SARyAhABIhgKFkNhbmNlbFRlYW1tYXRlUmVzcG9uc2UiKgoOUnVuVGVhbVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQASJlCglUZWFtRXZlbnQSDgoGbWVtYmVyGAEgASgJEh8KBWV2ZW50GAIgASgLMhAubWVjYXRsLnYxLkV2ZW50EicKB291dGNvbWUYAyABKAsyFi5tZWNhdGwudjEuVGVhbU91dGNvbWUi2wEKC1RlYW1PdXRjb21lEg4KBnJvdW5kcxgBIAEoBRIRCglxdWllc2NlbnQYAiABKAgSGAoQYnVkZ2V0X2V4aGF1c3RlZBgDIAEoCBIMCgRzdG9wGAQgASgJEh8KBXVzYWdlGAUgASgLMhAubWVjYXRsLnYxLlVzYWdlEjYKDGRpc3Bvc2l0aW9ucxgGIAMoCzIgLm1lY2F0bC52MS5UZWFtTWVtYmVyRGlzcG9zaXRpb24SKAoIZmluZGluZ3MYByADKAsyFi5tZWNhdGwudjEuVGVhbUZpbmRpbmciKwoPTGlzdFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEicQoQTGlzdFRlYW1SZXNwb25zZRImCgdtZW1iZXJzGAEgAygLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXISIgoFdGFza3MYAiADKAsyEy5tZWNhdGwudjEuVGVhbVRhc2sSEQoJcXVpZXNjZW50GAMgASgIIlEKClRlYW1NZW1iZXISDAoEbmFtZRgBIAEoCRISCgphZ2VudF90eXBlGAIgASgJEg0KBXN0YXRlGAMgASgJEhIKCnNlc3Npb25faWQYBCABKAkiWgoIVGVhbVRhc2sSCgoCaWQYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFc3RhdGUYAyABKAkSEAoIYXNzaWduZWUYBCABKAkSDAoEZGVwcxgFIAMoCSIrCgtUZWFtRmluZGluZxIOCgZtZW1iZXIYASABKAkSDAoEYm9keRgCIAEoCSJ9ChVUZWFtTWVtYmVyRGlzcG9zaXRpb24SDAoEbmFtZRgBIAEoCRIPCgdzdG9wcGVkGAIgASgIEi8KBnJlYXNvbhgDIAEoDjIfLm1lY2F0bC52MS5UZWFtTWVtYmVyU3RvcFJlYXNvbhIUCgxlcnJvcl9yb3VuZHMYBCABKAUiLgoSQ2xlYW51cFRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiFQoTQ2xlYW51cFRlYW1SZXNwb25zZSJvChJBcHByb3ZlUGxhblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIuCgt0YXJnZXRfbW9kZRgCIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIMCgRub3RlGAMgASgJIokBChdNYW51YWxEcmVhbUNhcGFiaWxpdGllcxI4Cg5wcm9qZWN0X21lbW9yeRgBIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkSNAoKdXNlcl9tb2RlbBgCIAEoCzIgLm1lY2F0bC52MS5EcmVhbVRhcmdldENhcGFiaWxpdHkiVQoVRHJlYW1UYXJnZXRDYXBhYmlsaXR5EhAKCGdlbmVyYXRlGAEgASgIEg4KBmRlY2lkZRgCIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAyABKAkiKgoYR2VuZXJhdGVEcmVhbVBsYW5SZXF1ZXN0Eg4KBnRhcmdldBgBIAEoCSJFChlHZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlEigKBHBsYW4YASABKAsyGi5tZWNhdGwudjEuRHJlYW1SZXZpZXdQbGFuIjsKFkRlY2lkZURyZWFtUGxhblJlcXVlc3QSDwoHcGxhbl9pZBgBIAEoCRIQCghkZWNpc2lvbhgCIAEoCSJDChdEZWNpZGVEcmVhbVBsYW5SZXNwb25zZRIoCgdyZWNlaXB0GAEgASgLMhcubWVjYXRsLnYxLkRyZWFtUmVjZWlwdCLLAQoPRHJlYW1SZXZpZXdQbGFuEgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRIuCgpleHBpcmVzX2F0GAMgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIfChdwbGFubmVkX29wZXJhdGlvbl9jb3VudBgEIAEoBRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgFIAEoBRItCgpvcGVyYXRpb25zGAYgAygLMhkubWVjYXRsLnYxLkRyZWFtT3BlcmF0aW9uIt8BCg5EcmVhbU9wZXJhdGlvbhIMCgRraW5kGAEgASgJEi0KCHN1cnZpdm9yGAIgASgLMhsubWVjYXRsLnYxLkRyZWFtUGFydGljaXBhbnQSLAoHc291cmNlcxgDIAMoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EjAKC3JlcGxhY2VtZW50GAQgASgLMhsubWVjYXRsLnYxLkRyZWFtUmVwbGFjZW1lbnQSDgoGcmVhc29uGAUgASgJEiAKGGV4YWN0X2R1cGxpY2F0ZV9lbGlnaWJsZRgGIAEoCCJDChBEcmVhbVBhcnRpY2lwYW50EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCRITCgtkZXNjcmlwdGlvbhgDIAEoCSI2ChBEcmVhbVJlcGxhY2VtZW50Eg0KBXZhbHVlGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJItcBCgxEcmVhbVJlY2VpcHQSCgoCaWQYASABKAkSDgoGdGFyZ2V0GAIgASgJEhMKC2Rpc3Bvc2l0aW9uGAMgASgJEhwKFHBsYW5uZWRfc291cmNlX2NvdW50GAQgASgFEhwKFGFwcGxpZWRfc291cmNlX2NvdW50GAUgASgFEh8KF2NvbmZsaWN0ZWRfc291cmNlX2NvdW50GAYgASgFEhwKFHNraXBwZWRfc291cmNlX2NvdW50GAcgASgFEhsKE2ZhaWxlZF9zb3VyY2VfY291bnQYCCABKAUiNAoVQ29tcGFjdFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiKwoWQ29tcGFjdFNlc3Npb25SZXNwb25zZRIRCgljb21wYWN0ZWQYASABKAgiNwohV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkiTgohV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0EhIKCnNlc3Npb25faWQYASABKAkSFQoNZW5yb2xsbWVudF9pZBgCIAEoCSJxChNXb3Jrc3BhY2VFbnJvbGxtZW50EhUKDWVucm9sbG1lbnRfaWQYASABKAkSDgoGc3RhdHVzGAIgASgJEhkKEXJlcXVpcmVkX3NlcnZpY2VzGAMgASgNEhgKEHByZXNlbnRhdGlvbl91cmwYBCABKAkqigEKDlBlcm1pc3Npb25Nb2RlEh8KG1BFUk1JU1NJT05fTU9ERV9VTlNQRUNJRklFRBAAEhsKF1BFUk1JU1NJT05fTU9ERV9ERUZBVUxUEAESGAoUUEVSTUlTU0lPTl9NT0RFX1BMQU4QAhIgChxQRVJNSVNTSU9OX01PREVfQUNDRVBUX0VESVRTEAMqkgEKD0FwcHJvdmFsVmVyZGljdBIgChxBUFBST1ZBTF9WRVJESUNUX1VOU1BFQ0lGSUVEEAASGQoVQVBQUk9WQUxfVkVSRElDVF9ERU5ZEAESHwobQVBQUk9WQUxfVkVSRElDVF9BTExPV19PTkNFEAISIQodQVBQUk9WQUxfVkVSRElDVF9BTExPV19BTFdBWVMQAyq+AQoMU3RlZXJPdXRjb21lEh0KGVNURUVSX09VVENPTUVfVU5TUEVDSUZJRUQQABIaChZTVEVFUl9PVVRDT01FX0FDQ0VQVEVEEAESGgoWU1RFRVJfT1VUQ09NRV9BUFBFTkRFRBACEhsKF1NURUVSX09VVENPTUVfUkVUUkFDVEVEEAMSHgoaU1RFRVJfT1VUQ09NRV9OT05FX1BFTkRJTkcQBBIaChZTVEVFUl9PVVRDT01FX1RPT19MQVRFEAUqmAEKDEhvb2tEZWNpc2lvbhIdChlIT09LX0RFQ0lTSU9OX1VOU1BFQ0lGSUVEEAASFgoSSE9PS19ERUNJU0lPTl9JTkZPEAESGQoVSE9PS19ERUNJU0lPTl9CTE9DS0VEEAISGgoWSE9PS19ERUNJU0lPTl9NT0RJRklFRBADEhoKFkhPT0tfREVDSVNJT05fQURWSVNPUlkQBCqWAQoQUmV0cnlEaXNwb3NpdGlvbhIhCh1SRVRSWV9ESVNQT1NJVElPTl9VTlNQRUNJRklFRBAAEh0KGVJFVFJZX0RJU1BPU0lUSU9OX1VOS05PV04QARIfChtSRVRSWV9ESVNQT1NJVElPTl9SRVRSWUFCTEUQAhIfChtSRVRSWV9ESVNQT1NJVElPTl9QRVJNQU5FTlQQAyqoAQoOU3RyZWFtUHJvZ3Jlc3MSHwobU1RSRUFNX1BST0dSRVNTX1VOU1BFQ0lGSUVEEAASGwoXU1RSRUFNX1BST0dSRVNTX1VOS05PV04QARIdChlTVFJFQU1fUFJPR1JFU1NfUFJFQ09NTUlUEAISGwoXU1RSRUFNX1BST0dSRVNTX1ZJU0lCTEUQAxIcChhTVFJFQU1fUFJPR1JFU1NfQ09NUExFVEUQBCqEAQoOU291bFByb3ZlbmFuY2USHwobU09VTF9QUk9WRU5BTkNFX1VOU1BFQ0lGSUVEEAASGAoUU09VTF9QUk9WRU5BTkNFX1VTRVIQARIbChdTT1VMX1BST1ZFTkFOQ0VfUFJPSkVDVBACEhoKFlNPVUxfUFJPVkVOQU5DRV9EUklWRVIQAyqtAQoUVGVhbU1lbWJlclN0b3BSZWFzb24SJwojVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fVU5TUEVDSUZJRUQQABIhCh1URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9FUlJPUhABEiUKIVRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0NBTkNFTExFRBACEiIKHlRFQU1fTUVNQkVSX1NUT1BfUkVBU09OX0JVREdFVBADMqE1Cg5IYXJuZXNzU2VydmljZRJnChRHZXRDb21wYXRpYmlsaXR5SW5mbxImLm1lY2F0bC52MS5HZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QaJy5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXNwb25zZRJSCg1DcmVhdGVTZXNzaW9uEh8ubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkNyZWF0ZVNlc3Npb25SZXNwb25zZRJSCg1HZXRTZXJ2ZXJJbmZvEh8ubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXF1ZXN0GiAubWVjYXRsLnYxLkdldFNlcnZlckluZm9SZXNwb25zZRJJCgpHZXRTZXNzaW9uEhwubWVjYXRsLnYxLkdldFNlc3Npb25SZXF1ZXN0Gh0ubWVjYXRsLnYxLkdldFNlc3Npb25SZXNwb25zZRJnChRHZXRTZXNzaW9uVHJhbnNjcmlwdBImLm1lY2F0bC52MS5HZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QaJy5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRJACgdTZXRNb2RlEhkubWVjYXRsLnYxLlNldE1vZGVSZXF1ZXN0GhoubWVjYXRsLnYxLlNldE1vZGVSZXNwb25zZRJPCgxDbG9zZVNlc3Npb24SHi5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbG9zZVNlc3Npb25SZXNwb25zZRJSCg1SZW5hbWVTZXNzaW9uEh8ubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLlJlbmFtZVNlc3Npb25SZXNwb25zZRJSCg1EZWxldGVTZXNzaW9uEh8ubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXF1ZXN0GiAubWVjYXRsLnYxLkRlbGV0ZVNlc3Npb25SZXNwb25zZRJVCg5Db21wYWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5Db21wYWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXNwb25zZRJPCgxDbGVhclNlc3Npb24SHi5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVxdWVzdBofLm1lY2F0bC52MS5DbGVhclNlc3Npb25SZXNwb25zZRJMCgtGb3JrU2Vzc2lvbhIdLm1lY2F0bC52MS5Gb3JrU2Vzc2lvblJlcXVlc3QaHi5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXNwb25zZRJHCghDb252ZXJzZRIaLm1lY2F0bC52MS5Db252ZXJzZVJlcXVlc3QaGy5tZWNhdGwudjEuQ29udmVyc2VSZXNwb25zZSgBMAESWwoQTGlzdE1jcFJlc291cmNlcxIiLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0TWNwUmVzb3VyY2VzUmVzcG9uc2USWAoPUmVhZE1jcFJlc291cmNlEiEubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlcXVlc3QaIi5tZWNhdGwudjEuUmVhZE1jcFJlc291cmNlUmVzcG9uc2USVQoOTGlzdE1jcFByb21wdHMSIC5tZWNhdGwudjEuTGlzdE1jcFByb21wdHNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVzcG9uc2USTwoMR2V0TWNwUHJvbXB0Eh4ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlcXVlc3QaHy5tZWNhdGwudjEuR2V0TWNwUHJvbXB0UmVzcG9uc2USVQoOTGlzdE1jcFNvdXJjZXMSIC5tZWNhdGwudjEuTGlzdE1jcFNvdXJjZXNSZXF1ZXN0GiEubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVzcG9uc2UScwoYTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzEioubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1JlcXVlc3QaKy5tZWNhdGwudjEuTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVzcG9uc2USYQoSTGlzdFRvb2xIaXZlR3JvdXBzEiQubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1JlcXVlc3QaJS5tZWNhdGwudjEuTGlzdFRvb2xIaXZlR3JvdXBzUmVzcG9uc2USSQoKTGlzdEFnZW50cxIcLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0QWdlbnRzUmVzcG9uc2USTwoMTGlzdENvbW1hbmRzEh4ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdENvbW1hbmRzUmVzcG9uc2USUgoNTGlzdFdvcmt0cmVlcxIfLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVxdWVzdBogLm1lY2F0bC52MS5MaXN0V29ya3RyZWVzUmVzcG9uc2USUAoTU3RyZWFtU2Vzc2lvbkV2ZW50cxIlLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEkwKEVN0cmVhbVNlc3Npb25MaXZlEiMubWVjYXRsLnYxLlN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmMKEldhdGNoU2Vzc2lvbkV2ZW50cxIkLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXF1ZXN0GiUubWVjYXRsLnYxLldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlMAESiAEKH0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb24SMS5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QaMi5tZWNhdGwudjEuR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlc3BvbnNlEnQKF1JlY2hlY2tNY3BBdXRob3JpemF0aW9uEikubWVjYXRsLnYxLlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBoqLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlc3BvbnNlKAEwARJxChZDYW5jZWxNY3BBdXRob3JpemF0aW9uEigubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXF1ZXN0GikubWVjYXRsLnYxLkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAESTwoMTGlzdFNlc3Npb25zEh4ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1JlcXVlc3QaHy5tZWNhdGwudjEuTGlzdFNlc3Npb25zUmVzcG9uc2USWwoQR2V0U3RvcmFnZUhlYWx0aBIiLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVxdWVzdBojLm1lY2F0bC52MS5HZXRTdG9yYWdlSGVhbHRoUmVzcG9uc2USXwoUUGxhblNlc3Npb25NaWdyYXRpb24SJi5tZWNhdGwudjEuUGxhblNlc3Npb25NaWdyYXRpb25SZXF1ZXN0Gh8ubWVjYXRsLnYxLlNlc3Npb25NaWdyYXRpb25QbGFuEmAKFUFwcGx5U2Vzc2lvbk1pZ3JhdGlvbhInLm1lY2F0bC52MS5BcHBseVNlc3Npb25NaWdyYXRpb25SZXF1ZXN0Gh4ubWVjYXRsLnYxLlNlc3Npb25NaWdyYXRpb25Kb2ISYgoWUmVzdW1lU2Vzc2lvbk1pZ3JhdGlvbhIoLm1lY2F0bC52MS5SZXN1bWVTZXNzaW9uTWlncmF0aW9uUmVxdWVzdBoeLm1lY2F0bC52MS5TZXNzaW9uTWlncmF0aW9uSm9iEmIKFkNhbmNlbFNlc3Npb25NaWdyYXRpb24SKC5tZWNhdGwudjEuQ2FuY2VsU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QaHi5tZWNhdGwudjEuU2Vzc2lvbk1pZ3JhdGlvbkpvYhJiChZHZXRTZXNzaW9uTWlncmF0aW9uSm9iEigubWVjYXRsLnYxLkdldFNlc3Npb25NaWdyYXRpb25Kb2JSZXF1ZXN0Gh4ubWVjYXRsLnYxLlNlc3Npb25NaWdyYXRpb25Kb2ISYQoSUGxhblNlc3Npb25DbGVhbnVwEiQubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlcXVlc3QaJS5tZWNhdGwudjEuUGxhblNlc3Npb25DbGVhbnVwUmVzcG9uc2USUwoTQXBwbHlTZXNzaW9uQ2xlYW51cBIlLm1lY2F0bC52MS5BcHBseVNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFENhbmNlbFNlc3Npb25DbGVhbnVwEiYubWVjYXRsLnYxLkNhbmNlbFNlc3Npb25DbGVhbnVwUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iElUKFEdldFNlc3Npb25DbGVhbnVwSm9iEiYubWVjYXRsLnYxLkdldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBoVLm1lY2F0bC52MS5DbGVhbnVwSm9iEkkKCkxpc3RTa2lsbHMSHC5tZWNhdGwudjEuTGlzdFNraWxsc1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdFNraWxsc1Jlc3BvbnNlEkAKB0dldFNvdWwSGS5tZWNhdGwudjEuR2V0U291bFJlcXVlc3QaGi5tZWNhdGwudjEuR2V0U291bFJlc3BvbnNlEk8KDEdldFVzZXJNb2RlbBIeLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldFVzZXJNb2RlbFJlc3BvbnNlElUKDlJlZmxlY3RTZXNzaW9uEiAubWVjYXRsLnYxLlJlZmxlY3RTZXNzaW9uUmVxdWVzdBohLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlc3BvbnNlEmEKEkdldExlYXJuaW5nQXR0ZW1wdBIkLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GiUubWVjYXRsLnYxLkdldExlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmcKFExpc3RMZWFybmluZ0F0dGVtcHRzEiYubWVjYXRsLnYxLkxpc3RMZWFybmluZ0F0dGVtcHRzUmVxdWVzdBonLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1Jlc3BvbnNlEmkKFFJldHJ5TGVhcm5pbmdBdHRlbXB0EicubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QaKC5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVzcG9uc2USawoWQWJhbmRvbkxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEl4KEUdlbmVyYXRlRHJlYW1QbGFuEiMubWVjYXRsLnYxLkdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBokLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlc3BvbnNlElgKD0RlY2lkZURyZWFtUGxhbhIhLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXF1ZXN0GiIubWVjYXRsLnYxLkRlY2lkZURyZWFtUGxhblJlc3BvbnNlEmoKFUxpc3RMZWFybmluZ1Byb3Bvc2FscxInLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0GigubWVjYXRsLnYxLkxpc3RMZWFybmluZ1Byb3Bvc2Fsc1Jlc3BvbnNlEmQKE0dldExlYXJuaW5nUHJvcG9zYWwSJS5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaJi5tZWNhdGwudjEuR2V0TGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEm0KFkRlY2lkZUxlYXJuaW5nUHJvcG9zYWwSKC5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QaKS5tZWNhdGwudjEuRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlc3BvbnNlEmoKFVVuZG9MZWFybmluZ1Byb21vdGlvbhInLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0GigubWVjYXRsLnYxLlVuZG9MZWFybmluZ1Byb21vdGlvblJlc3BvbnNlEl4KEUxpc3RMZWFybmVkU2tpbGxzEiMubWVjYXRsLnYxLkxpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBokLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1Jlc3BvbnNlElgKD0dldExlYXJuZWRTa2lsbBIhLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXF1ZXN0GiIubWVjYXRsLnYxLkdldExlYXJuZWRTa2lsbFJlc3BvbnNlEnMKGERpZmZMZWFybmVkU2tpbGxWZXJzaW9ucxIqLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXF1ZXN0GisubWVjYXRsLnYxLkRpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1Jlc3BvbnNlEmMKFEFjdGl2YXRlTGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYQoSUmVqZWN0TGVhcm5lZFNraWxsEiQubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USYgoTQXJjaGl2ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmUKFFJvbGxiYWNrTGVhcm5lZFNraWxsEiYubWVjYXRsLnYxLlJvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJbChBMaXN0U2tpbGxDaGFuZ2VzEiIubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXF1ZXN0GiMubWVjYXRsLnYxLkxpc3RTa2lsbENoYW5nZXNSZXNwb25zZRJJCgpMaXN0TW9kZWxzEhwubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RNb2RlbHNSZXNwb25zZRJJCgpDcmVhdGVUZWFtEhwubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXF1ZXN0Gh0ubWVjYXRsLnYxLkNyZWF0ZVRlYW1SZXNwb25zZRJSCg1TcGF3blRlYW1tYXRlEh8ubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXF1ZXN0GiAubWVjYXRsLnYxLlNwYXduVGVhbW1hdGVSZXNwb25zZRJkChNTZW5kVGVhbW1hdGVNZXNzYWdlEiUubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXF1ZXN0GiYubWVjYXRsLnYxLlNlbmRUZWFtbWF0ZU1lc3NhZ2VSZXNwb25zZRJVCg5DYW5jZWxUZWFtbWF0ZRIgLm1lY2F0bC52MS5DYW5jZWxUZWFtbWF0ZVJlcXVlc3QaIS5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXNwb25zZRI8CgdSdW5UZWFtEhkubWVjYXRsLnYxLlJ1blRlYW1SZXF1ZXN0GhQubWVjYXRsLnYxLlRlYW1FdmVudDABEkMKCExpc3RUZWFtEhoubWVjYXRsLnYxLkxpc3RUZWFtUmVxdWVzdBobLm1lY2F0bC52MS5MaXN0VGVhbVJlc3BvbnNlEkwKC0NsZWFudXBUZWFtEh0ubWVjYXRsLnYxLkNsZWFudXBUZWFtUmVxdWVzdBoeLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlc3BvbnNlEkAKC0FwcHJvdmVQbGFuEh0ubWVjYXRsLnYxLkFwcHJvdmVQbGFuUmVxdWVzdBoQLm1lY2F0bC52MS5FdmVudDABEmgKGENvbm5lY3RXb3Jrc3BhY2VTZXJ2aWNlcxIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29ubmVjdFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudBJoChhSZXRyeVdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaQoZQ2FuY2VsV29ya3NwYWNlRW5yb2xsbWVudBIsLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50Q29udHJvbFJlcXVlc3QaHi5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudEKiAQoNY29tLm1lY2F0bC52MUIMSGFybmVzc1Byb3RvUAFaPmdpdGh1Yi5jb20vc3RhY2tsb2svbWVjYXRsL2NvbnRyYWN0cy9nZW4vZ28vbWVjYXRsL3YxO21lY2F0bHYxogIDTVhYqgIJTWVjYXRsLlYxygIJTWVjYXRsXFYx4gIVTWVjYXRsXFYxXEdQQk1ldGFkYXRh6gIKTWVjYXRsOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]); + fileDesc("ChdtZWNhdGwvdjEvaGFybmVzcy5wcm90bxIJbWVjYXRsLnYxIlUKBkxpbWl0cxIRCgltYXhfdHVybnMYASABKAUSFgoObWF4X3Rvb2xfY2FsbHMYAiABKAUSIAoYbWF4X2NvbnNlY3V0aXZlX2ZhaWx1cmVzGAMgASgFIskCChRDcmVhdGVTZXNzaW9uUmVxdWVzdBInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlEiEKBmxpbWl0cxgDIAEoCzIRLm1lY2F0bC52MS5MaW1pdHMSEwoLcHJvdmlkZXJfaWQYBCABKAkSEAoIbW9kZWxfaWQYBSABKAkSDwoHcHJvZmlsZRgGIAEoCRIYChByZWFzb25pbmdfZWZmb3J0GAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAkgASgJEhkKEWRlYnVnX21jcF9zZXJ2ZXJzGAogAygJEi0KC21jcF9zZXJ2ZXJzGAsgAygLMhgubWVjYXRsLnYxLk1jcFNlcnZlclNwZWNKBAgBEAJKBAgIEAlSCXdvcmtzcGFjZVIRc291cmNlX3Nlc3Npb25faWQisQEKDU1jcFNlcnZlclNwZWMSDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSDAoEdHlwZRgDIAEoCRIPCgdjb21tYW5kGAQgASgJEjYKB2hlYWRlcnMYBSADKAsyJS5tZWNhdGwudjEuTWNwU2VydmVyU3BlYy5IZWFkZXJzRW50cnkaLgoMSGVhZGVyc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiKwoUR2V0U2VydmVySW5mb1JlcXVlc3QSEwoLcHJvdmlkZXJfaWQYASABKAkibwoVR2V0U2VydmVySW5mb1Jlc3BvbnNlEhAKCGJ1aWxkX2lkGAEgASgJEh0KFXNlcnZlcl9pbXBsZW1lbnRhdGlvbhgCIAEoCRIlCh1sbG1fcHJvdmlkZXJfZGlzcGxheV9lbmRwb2ludBgDIAEoCSIdChtHZXRDb21wYXRpYmlsaXR5SW5mb1JlcXVlc3QijAEKHEdldENvbXBhdGliaWxpdHlJbmZvUmVzcG9uc2USEQoJYXBpX21ham9yGAEgASgFEjMKDGNhcGFiaWxpdGllcxgCIAEoCzIdLm1lY2F0bC52MS5TZXJ2ZXJDYXBhYmlsaXRpZXMSEAoIZmVhdHVyZXMYAyADKAkSEgoKZGVwbG95bWVudBgEIAEoCSKhBQoSU2VydmVyQ2FwYWJpbGl0aWVzEgsKA21jcBgBIAEoCBIWCg5zbGFzaF9jb21tYW5kcxgCIAEoCBIOCgZtZW1vcnkYAyABKAgSDgoGc2tpbGxzGAQgASgIEg0KBXRlYW1zGAUgASgIEgwKBGJhc2gYBiABKAgSDQoFaW1hZ2UYByABKAgSDQoFYXVkaW8YCCABKAgSDgoGYWdlbnRzGAkgASgIEgwKBHNvdWwYCiABKAgSEgoKdXNlcl9tb2RlbBgLIAEoCBIXCg9tb2RlbF9zZWxlY3Rpb24YDCABKAgSDwoHcG9zdHVyZRgNIAEoCRIRCgl3b3JrdHJlZXMYDiABKAgSEgoKc2NoZWR1bGluZxgPIAEoCBISCgpyZWZsZWN0aW9uGBAgASgIEhoKEmxlYXJuaW5nX3Byb3Bvc2FscxgRIAEoCBIWCg5sZWFybmVkX3NraWxscxgSIAEoCBIZChFzdG9yYWdlX21pZ3JhdGlvbhgVIAEoCBIXCg9zdG9yYWdlX2NsZWFudXAYFiABKAgSOAoMbWFudWFsX2RyZWFtGBMgASgLMiIubWVjYXRsLnYxLk1hbnVhbERyZWFtQ2FwYWJpbGl0aWVzEhYKDnN0b3JhZ2VfaGVhbHRoGBcgASgIEg0KBXN0ZWVyGBggASgIEhkKEW1hbnVhbF9jb21wYWN0aW9uGBkgASgIEhUKDXNlc3Npb25fZGVidWcYGiABKAgSEQoJZGVidWdfbWNwGBsgASgIEhwKFHdvcmtzcGFjZV9lbnJvbGxtZW50GBwgASgIEhwKFG1jcF9jb25uZWN0b3Jfc3RhdHVzGB0gASgIEhMKC21jcF9yZWZyZXNoGB4gASgISgQIFBAVUg9sZWdhY3lfYWRvcHRpb24iNQofTGlzdFNlc3Npb25NY3BDb25uZWN0b3JzUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJIrIBCiBMaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXNwb25zZRIUCgxhdmFpbGFiaWxpdHkYASABKAkSGAoQZW5yb2xsbWVudF9zdGF0ZRgCIAEoCRIxCgpjb25uZWN0b3JzGAMgAygLMh0ubWVjYXRsLnYxLk1jcENvbm5lY3RvclN0YXR1cxIYChB0b3RhbF9jb25uZWN0b3JzGAQgASgNEhEKCXRydW5jYXRlZBgFIAEoCCJPChJNY3BDb25uZWN0b3JTdGF0dXMSDAoEbmFtZRgBIAEoCRIXCg9jYXRhbG9ndWVfc3RhdGUYAiABKAkSEgoKdG9vbF9jb3VudBgDIAEoDSKBAgoVQ3JlYXRlU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSMwoMY2FwYWJpbGl0aWVzGAIgASgLMh0ubWVjYXRsLnYxLlNlcnZlckNhcGFiaWxpdGllcxI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgDIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzEjAKDnJlc29sdmVkX21vZGVsGAQgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSLwoJcGxhY2VtZW50GAUgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIlIKEVBsYWNlbWVudE1ldGFkYXRhEgwKBGtpbmQYASABKAkSDQoFbGFiZWwYAiABKAkSDgoGYnJhbmNoGAMgASgJEhAKCHJldmlzaW9uGAQgASgJImgKDVJlc29sdmVkTW9kZWwSEwoLcHJvdmlkZXJfaWQYASABKAkSEAoIbW9kZWxfaWQYAiABKAkSFgoOY29udGV4dF93aW5kb3cYAyABKAMSGAoQcmVhc29uaW5nX2VmZm9ydBgEIAEoCSIzChNTZXNzaW9uQ2FwYWJpbGl0aWVzEg0KBWltYWdlGAEgASgIEg0KBWF1ZGlvGAIgASgIIjAKEUdldFNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiOQoSR2V0U2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiI6ChtHZXRTZXNzaW9uVHJhbnNjcmlwdFJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASJSChRBY3Rpdml0eVJlcGxheVN0YXR1cxIRCglhdmFpbGFibGUYASABKAgSEAoIY29tcGxldGUYAiABKAgSFQoNYXV0aG9yaXRhdGl2ZRgDIAEoCCLtAQocR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXNwb25zZRISCgpzZXNzaW9uX2lkGAEgASgJEjAKCG1lc3NhZ2VzGAIgAygLMh4ubWVjYXRsLnYxLkNvbnZlcnNhdGlvbk1lc3NhZ2USEAoIY29tcGxldGUYAyABKAgSMQoIYWN0aXZpdHkYBCABKAsyHy5tZWNhdGwudjEuQWN0aXZpdHlSZXBsYXlTdGF0dXMSDAoEa2luZBgFIAEoCRI0CgxyZWxhdGlvbnNoaXAYBiABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcCI5ChpTdHJlYW1TZXNzaW9uRXZlbnRzUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIjcKGFN0cmVhbVNlc3Npb25MaXZlUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIlgKGVdhdGNoU2Vzc2lvbkV2ZW50c1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIOCgZjdXJzb3IYAiABKAkSDgoGcnVuX2lkGAMgASgJIlwKGldhdGNoU2Vzc2lvbkV2ZW50c1Jlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50Eg4KBmN1cnNvchgCIAEoCRINCgVwaGFzZRgDIAEoCSI4ChNMaXN0U2Vzc2lvbnNSZXF1ZXN0EhEKCXBhZ2Vfc2l6ZRgBIAEoBRIOCgZjdXJzb3IYAiABKAkiTgoJUHJpbmNpcGFsEg4KBmlzc3VlchgBIAEoCRIPCgdzdWJqZWN0GAIgASgJEhIKCmdyYW50X3R5cGUYAyABKAkSDAoEbmFtZRgEIAEoCSKKBQoOU2Vzc2lvblN1bW1hcnkSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAIgASgDEg0KBXN0YXRlGAMgASgJEg0KBXR1cm5zGAQgASgFEhAKCG1vZGVsX2lkGAUgASgJEhcKD2NyZWF0ZWRfYXRfdW5peBgGIAEoAxIRCgV0aXRsZRgHIAEoCUICGAESIwoFb3duZXIYCCABKAsyFC5tZWNhdGwudjEuUHJpbmNpcGFsEgwKBGtpbmQYCSABKAkSNAoMcmVsYXRpb25zaGlwGAogASgLMh4ubWVjYXRsLnYxLlNlc3Npb25SZWxhdGlvbnNoaXASPQoMY2FwYWJpbGl0aWVzGAsgASgLMicubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcmVhc29uX2NvZGUYDCABKAkSHAoQdGl0bGVfcHJvdmVuYW5jZRgOIAEoCUICGAESLwoJcGxhY2VtZW50GA8gASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBAgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI+Cgt0b2tlbl91c2FnZRgRIAMoCzIpLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeS5Ub2tlblVzYWdlRW50cnkSFgoOYWN0aXZpdHlfc3RhdGUYEiABKAkaSAoPVG9rZW5Vc2FnZUVudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIVLm1lY2F0bC52MS5Ub2tlblVzYWdlOgI4AUoECA0QDlIJd29ya3NwYWNlIuYBChNTZXNzaW9uUmVsYXRpb25zaGlwEhkKEXBhcmVudF9zZXNzaW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSGQoMYnJhbmNoX2luZGV4GAMgASgFSACIAQESFQoNc2NoZWR1bGVfbmFtZRgEIAEoCRIZChFvcmlnaW5fc2Vzc2lvbl9pZBgFIAEoCRIPCgd0ZWFtX2lkGAYgASgJEhMKC21lbWJlcl9uYW1lGAcgASgJEh8KF2RlYnVnX3RhcmdldF9zZXNzaW9uX2lkGAggASgJQg8KDV9icmFuY2hfaW5kZXgikgIKHFNlc3Npb25JbnZlbnRvcnlDYXBhYmlsaXRpZXMSEwoLcHVibGljX2NoYXQYASABKAgSDwoHaW5zcGVjdBgCIAEoCBIgChhhdXRob3JpdGF0aXZlX3RyYW5zY3JpcHQYAyABKAgSFwoPYWN0aXZpdHlfcmVwbGF5GAQgASgIEg8KB2NvcHlfaWQYBSABKAgSFwoPdmlld190cmFuc2NyaXB0GAYgASgIEgwKBGZvcmsYByABKAgSDgoGcmVuYW1lGAggASgIEg4KBmRlbGV0ZRgJIAEoCBI5CgdyZWFzb25zGAogASgLMigubWVjYXRsLnYxLlNlc3Npb25JbnZlbnRvcnlBY3Rpb25SZWFzb25zIp0BCh1TZXNzaW9uSW52ZW50b3J5QWN0aW9uUmVhc29ucxITCgtwdWJsaWNfY2hhdBgBIAEoCRIPCgdpbnNwZWN0GAIgASgJEg8KB2NvcHlfaWQYAyABKAkSFwoPdmlld190cmFuc2NyaXB0GAQgASgJEgwKBGZvcmsYBSABKAkSDgoGcmVuYW1lGAYgASgJEg4KBmRlbGV0ZRgHIAEoCSJtChRMaXN0U2Vzc2lvbnNSZXNwb25zZRIrCghzZXNzaW9ucxgBIAMoCzIZLm1lY2F0bC52MS5TZXNzaW9uU3VtbWFyeRITCgtuZXh0X2N1cnNvchgCIAEoCRITCgt0b3RhbF9jb3VudBgDIAEoBSIZChdHZXRTdG9yYWdlSGVhbHRoUmVxdWVzdCLeAQoPUmV0ZW50aW9uUG9saWN5EhwKFG1haW5fbWF4X2FnZV9zZWNvbmRzGAEgASgDEhYKDm1haW5fbWF4X2NvdW50GAIgASgFEh0KFWNoaWxkX21heF9hZ2Vfc2Vjb25kcxgDIAEoAxIXCg9jaGlsZF9tYXhfY291bnQYBCABKAUSIQoZc2NoZWR1bGVkX21heF9hZ2Vfc2Vjb25kcxgFIAEoAxIbChNzY2hlZHVsZWRfbWF4X2NvdW50GAYgASgFEh0KFXN3ZWVwX2NhZGVuY2Vfc2Vjb25kcxgHIAEoAyLJBwoYR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEhEKCWF2YWlsYWJsZRgBIAEoCBIaChJ1bmF2YWlsYWJsZV9yZWFzb24YAiABKAkSFQoNY3VycmVudF9ieXRlcxgDIAEoAxIfChdjdXJyZW50X2J5dGVzX2F2YWlsYWJsZRgEIAEoCBIZChFyZWNsYWltYWJsZV9ieXRlcxgFIAEoAxIjChtyZWNsYWltYWJsZV9ieXRlc19hdmFpbGFibGUYBiABKAgSFQoNc2Vzc2lvbl9jb3VudBgHIAEoAxISCgpmaWxlX2NvdW50GAggASgDEhAKCHYxX2NvdW50GAkgASgDEhAKCHYyX2NvdW50GAogASgDEhIKCm1haW5fY291bnQYCyABKAMSEwoLY2hpbGRfY291bnQYDCABKAMSFwoPc2NoZWR1bGVkX2NvdW50GA0gASgDEhUKDXVua25vd25fY291bnQYDiABKAMSFQoNY29ycnVwdF9jb3VudBgPIAEoAxIqCgZwb2xpY3kYECABKAsyGi5tZWNhdGwudjEuUmV0ZW50aW9uUG9saWN5EhcKD2xhc3Rfc3dlZXBfdW5peBgRIAEoAxIcChRsYXN0X3N3ZWVwX2F2YWlsYWJsZRgSIAEoCBIXCg9uZXh0X3N3ZWVwX3VuaXgYEyABKAMSHAoUbmV4dF9zd2VlcF9hdmFpbGFibGUYFCABKAgSEgoKYWN0aXZlX2pvYhgVIAEoCRIUCgxsYXN0X2ZhaWx1cmUYFiABKAkSJAocb3duZXJsZXNzX3Nlc3Npb25zX2F2YWlsYWJsZRgXIAEoCBItCiVvd25lcmxlc3Nfc2Vzc2lvbnNfdW5hdmFpbGFibGVfcmVhc29uGBggASgJEh8KF293bmVybGVzc19zZXNzaW9uX2NvdW50GBkgASgDEh0KFW93bmVybGVzc19zZXNzaW9uX2lkcxgaIAMoCRInCh9vd25lcmxlc3Nfc2Vzc2lvbl9pZHNfdHJ1bmNhdGVkGBsgASgIEiUKHW93bmVybGVzc19zY2hlZHVsZXNfYXZhaWxhYmxlGBwgASgIEi4KJm93bmVybGVzc19zY2hlZHVsZXNfdW5hdmFpbGFibGVfcmVhc29uGB0gASgJEiAKGG93bmVybGVzc19zY2hlZHVsZV9jb3VudBgeIAEoAxIgChhvd25lcmxlc3Nfc2NoZWR1bGVfbmFtZXMYHyADKAkSKgoib3duZXJsZXNzX3NjaGVkdWxlX25hbWVzX3RydW5jYXRlZBggIAEoCCIdChtQbGFuU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3Qi/wEKFFNlc3Npb25NaWdyYXRpb25QbGFuEg8KB3BsYW5faWQYASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRITCgt2MV9mYW1pbGllcxgEIAEoAxITCgt2Ml9mYW1pbGllcxgFIAEoAxIYChBpbnZhbGlkX2ZhbWlsaWVzGAYgASgDEhgKEHNraXBwZWRfZmFtaWxpZXMYByABKAMSFQoNY3VycmVudF9ieXRlcxgIIAEoAxIZChFyZWNsYWltYWJsZV9ieXRlcxgJIAEoAxIXCg90ZW1wb3JhcnlfYnl0ZXMYCiABKAMiTAocQXBwbHlTZXNzaW9uTWlncmF0aW9uUmVxdWVzdBIYCgdwbGFuX2lkGAEgASgJQge6SARyAhABEhIKCmJhdGNoX3NpemUYAiABKAUiTAodUmVzdW1lU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABEhIKCmJhdGNoX3NpemUYAiABKAUiOAodQ2FuY2VsU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjgKHUdldFNlc3Npb25NaWdyYXRpb25Kb2JSZXF1ZXN0EhcKBmpvYl9pZBgBIAEoCUIHukgEcgIQASJWChlTZXNzaW9uTWlncmF0aW9uSXRlbUVycm9yEhMKC2l0ZW1faGFuZGxlGAEgASgJEhMKC3JlYXNvbl9jb2RlGAIgASgJEg8KB21lc3NhZ2UYAyABKAki2QIKDUNsZWFudXBDb3VudHMSDQoFdG90YWwYASABKAUSNQoHYnlfa2luZBgCIAMoCzIkLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5S2luZEVudHJ5EjcKCGJ5X3N0YXRlGAMgAygLMiUubWVjYXRsLnYxLkNsZWFudXBDb3VudHMuQnlTdGF0ZUVudHJ5EjkKCWJ5X3JlYXNvbhgEIAMoCzImLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzLkJ5UmVhc29uRW50cnkaLQoLQnlLaW5kRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARouCgxCeVN0YXRlRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARovCg1CeVJlYXNvbkVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEihgEKEENsZWFudXBDYW5kaWRhdGUSEgoKc2Vzc2lvbl9pZBgBIAEoCRIMCgRraW5kGAIgASgJEg0KBXN0YXRlGAMgASgJEg4KBnJlYXNvbhgEIAEoCRIYChBtb2RpZmllZF9hdF91bml4GAUgASgDEhcKD2VzdGltYXRlZF9ieXRlcxgGIAEoAyIqChlQbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0Eg0KBWtpbmRzGAEgAygJItMCChpQbGFuU2Vzc2lvbkNsZWFudXBSZXNwb25zZRIaChJjb25maXJtYXRpb25fdG9rZW4YASABKAkSEQoJYXZhaWxhYmxlGAIgASgIEhoKEnVuYXZhaWxhYmxlX3JlYXNvbhgDIAEoCRISCgpnZW5lcmF0aW9uGAQgASgJEhYKDnBvbGljeV92ZXJzaW9uGAUgASgJEi0KCGVsaWdpYmxlGAYgAygLMhsubWVjYXRsLnYxLkNsZWFudXBDYW5kaWRhdGUSKwoJcHJvdGVjdGVkGAcgASgLMhgubWVjYXRsLnYxLkNsZWFudXBDb3VudHMSFwoPZXN0aW1hdGVkX2J5dGVzGAggASgDEhYKDnBsYW5uZWRfam9iX2lkGAkgASgJEjEKD2VsaWdpYmxlX2NvdW50cxgKIAEoCzIYLm1lY2F0bC52MS5DbGVhbnVwQ291bnRzIkEKGkFwcGx5U2Vzc2lvbkNsZWFudXBSZXF1ZXN0EiMKEmNvbmZpcm1hdGlvbl90b2tlbhgBIAEoCUIHukgEcgIQASI2ChtDYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QSFwoGam9iX2lkGAEgASgJQge6SARyAhABIjYKG0dldFNlc3Npb25DbGVhbnVwSm9iUmVxdWVzdBIXCgZqb2JfaWQYASABKAlCB7pIBHICEAEiTQoQQ2xlYW51cEl0ZW1FcnJvchITCgtpdGVtX2hhbmRsZRgBIAEoCRITCgtyZWFzb25fY29kZRgCIAEoCRIPCgdtZXNzYWdlGAMgASgJIsgCChNTZXNzaW9uTWlncmF0aW9uSm9iEg4KBmpvYl9pZBgBIAEoCRINCgVzdGF0ZRgCIAEoCRITCgt2MV9mYW1pbGllcxgDIAEoAxITCgt2Ml9mYW1pbGllcxgEIAEoAxIYChBpbnZhbGlkX2ZhbWlsaWVzGAUgASgDEhgKEHNraXBwZWRfZmFtaWxpZXMYBiABKAMSFQoNY3VycmVudF9ieXRlcxgHIAEoAxIZChFyZWNsYWltYWJsZV9ieXRlcxgIIAEoAxIXCg90ZW1wb3JhcnlfYnl0ZXMYCSABKAMSEQoJcHJvY2Vzc2VkGAogASgDEhAKCG1pZ3JhdGVkGAsgASgDEg4KBmZhaWxlZBgMIAEoAxI0CgZlcnJvcnMYDSADKAsyJC5tZWNhdGwudjEuU2Vzc2lvbk1pZ3JhdGlvbkl0ZW1FcnJvciKsAQoKQ2xlYW51cEpvYhIOCgZqb2JfaWQYASABKAkSDQoFc3RhdGUYAiABKAkSEQoJcHJvY2Vzc2VkGAMgASgFEg8KB2RlbGV0ZWQYBCABKAUSDwoHc2tpcHBlZBgFIAEoBRINCgVzdGFsZRgGIAEoBRIOCgZmYWlsZWQYByABKAUSKwoGZXJyb3JzGAggAygLMhsubWVjYXRsLnYxLkNsZWFudXBJdGVtRXJyb3IiVgoOU2V0TW9kZVJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARInCgRtb2RlGAIgASgOMhkubWVjYXRsLnYxLlBlcm1pc3Npb25Nb2RlIjYKD1NldE1vZGVSZXNwb25zZRIjCgdzZXNzaW9uGAEgASgLMhIubWVjYXRsLnYxLlNlc3Npb24iMgoTQ2xvc2VTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhYKFENsb3NlU2Vzc2lvblJlc3BvbnNlIksKFFJlbmFtZVNlc3Npb25SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESFgoFdGl0bGUYAiABKAlCB7pIBHICEAEiPAoVUmVuYW1lU2Vzc2lvblJlc3BvbnNlEiMKB3Nlc3Npb24YASABKAsyEi5tZWNhdGwudjEuU2Vzc2lvbiIzChREZWxldGVTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIhcKFURlbGV0ZVNlc3Npb25SZXNwb25zZSJvChNDbGVhclNlc3Npb25SZXF1ZXN0EiIKEXNvdXJjZV9zZXNzaW9uX2lkGAEgASgJQge6SARyAhABEh4KEXdvcmt0cmVlX3NlbGVjdG9yGAIgASgJSACIAQFCFAoSX3dvcmt0cmVlX3NlbGVjdG9yIlsKFENsZWFyU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIr4BChJGb3JrU2Vzc2lvblJlcXVlc3QSIgoRc291cmNlX3Nlc3Npb25faWQYASABKAlCB7pIBHICEAESDQoFdGl0bGUYAiABKAkSGAoQcmVhc29uaW5nX2VmZm9ydBgDIAEoCRIeChF3b3JrdHJlZV9zZWxlY3RvchgEIAEoCUgAiAEBEhMKC3Byb3ZpZGVyX2lkGAUgASgJEhAKCG1vZGVsX2lkGAYgASgJQhQKEl93b3JrdHJlZV9zZWxlY3RvciJaChNGb3JrU2Vzc2lvblJlc3BvbnNlEhIKCnNlc3Npb25faWQYASABKAkSLwoJcGxhY2VtZW50GAIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhIpoGCgdTZXNzaW9uEhIKCnNlc3Npb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkSJwoEbW9kZRgDIAEoDjIZLm1lY2F0bC52MS5QZXJtaXNzaW9uTW9kZRIhCgZsaW1pdHMYBSABKAsyES5tZWNhdGwudjEuTGltaXRzEg0KBXR1cm5zGAYgASgFEhIKCnRvb2xfY2FsbHMYByABKAUSFwoPY3JlYXRlZF9hdF91bml4GAggASgDEjAKDnJlc29sdmVkX21vZGVsGAkgASgLMhgubWVjYXRsLnYxLlJlc29sdmVkTW9kZWwSEQoFdGl0bGUYCiABKAlCAhgBEhwKEHRpdGxlX3Byb3ZlbmFuY2UYDCABKAlCAhgBEjMKDGNhcGFiaWxpdGllcxgLIAEoCzIdLm1lY2F0bC52MS5TZXJ2ZXJDYXBhYmlsaXRpZXMSDAoEa2luZBgOIAEoCRI0CgxyZWxhdGlvbnNoaXAYDyABKAsyHi5tZWNhdGwudjEuU2Vzc2lvblJlbGF0aW9uc2hpcBIZChFkZWJ1Z19tY3Bfc2VydmVycxgQIAMoCRIXCg9kZWJ1Z19tY3BfdG9vbHMYESADKAkSLwoJcGxhY2VtZW50GBIgASgLMhwubWVjYXRsLnYxLlBsYWNlbWVudE1ldGFkYXRhEi8KDnRpdGxlX21ldGFkYXRhGBMgASgLMhcubWVjYXRsLnYxLlNlc3Npb25UaXRsZRI3Cgt0b2tlbl91c2FnZRgUIAMoCzIiLm1lY2F0bC52MS5TZXNzaW9uLlRva2VuVXNhZ2VFbnRyeRI8ChRzZXNzaW9uX2NhcGFiaWxpdGllcxgVIAEoCzIeLm1lY2F0bC52MS5TZXNzaW9uQ2FwYWJpbGl0aWVzGkgKD1Rva2VuVXNhZ2VFbnRyeRILCgNrZXkYASABKAkSJAoFdmFsdWUYAiABKAsyFS5tZWNhdGwudjEuVG9rZW5Vc2FnZToCOAFKBAgEEAVKBAgNEA5SCXdvcmtzcGFjZVIaYWRvcHRpb25fc291cmNlX3Nlc3Npb25faWQilQEKDFNlc3Npb25UaXRsZRINCgV0aXRsZRgBIAEoCRISCgpwcm92ZW5hbmNlGAIgASgJEhgKEGdlbmVyYXRpb25fc3RhdGUYAyABKAkSNgoObGF0ZXN0X2F0dGVtcHQYBCABKAsyHi5tZWNhdGwudjEuVGl0bGVBdHRlbXB0U3VtbWFyeRIQCghyZXZpc2lvbhgFIAEoBCI4ChNUaXRsZUF0dGVtcHRTdW1tYXJ5EgoKAmlkGAEgASgJEg8KB291dGNvbWUYAiABKAlKBAgDEAQioQEKClRva2VuVXNhZ2USHwoFdG90YWwYASABKAsyEC5tZWNhdGwudjEuVXNhZ2USMQoGbW9kZWxzGAIgAygLMiEubWVjYXRsLnYxLlRva2VuVXNhZ2UuTW9kZWxzRW50cnkaPwoLTW9kZWxzRW50cnkSCwoDa2V5GAEgASgJEh8KBXZhbHVlGAIgASgLMhAubWVjYXRsLnYxLlVzYWdlOgI4ASLEAgoPQ29udmVyc2VSZXF1ZXN0EiMKBnByb21wdBgBIAEoCzIRLm1lY2F0bC52MS5Qcm9tcHRIABImCgVyZXRyeRgCIAEoCzIVLm1lY2F0bC52MS5SZXRyeVN0YXJ0SAASNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAEi4KDGNhbmNlbF9jaGlsZBgMIAEoCzIWLm1lY2F0bC52MS5DYW5jZWxDaGlsZEgAEiEKBXN0ZWVyGA0gASgLMhAubWVjYXRsLnYxLlN0ZWVySAASLgoMc3RlZXJfY2FuY2VsGA4gASgLMhYubWVjYXRsLnYxLlN0ZWVyQ2FuY2VsSABCBgoEa2luZCIzChBDb252ZXJzZVJlc3BvbnNlEh8KBWV2ZW50GAEgASgLMhAubWVjYXRsLnYxLkV2ZW50IpwBCgdDb250ZW50EiUKBGtpbmQYASABKA4yFy5tZWNhdGwudjEuQ29udGVudC5LaW5kEhEKCW1pbWVfdHlwZRgCIAEoCRIMCgRkYXRhGAMgASgMEgsKA3VybBgEIAEoCSI8CgRLaW5kEhQKEEtJTkRfVU5TUEVDSUZJRUQQABIOCgpLSU5EX0lNQUdFEAESDgoKS0lORF9BVURJTxACIpADCgxDb250ZW50QmxvY2sSKgoEa2luZBgBIAEoDjIcLm1lY2F0bC52MS5Db250ZW50QmxvY2suS2luZBIRCgltaW1lX3R5cGUYAiABKAkSDAoEZGF0YRgDIAEoDBILCgN1cmwYBCABKAkSDAoEdGV4dBgFIAEoCRIMCgRuYW1lGAYgASgJEg0KBXRpdGxlGAcgASgJEhMKC2Rlc2NyaXB0aW9uGAggASgJEgwKBHNpemUYCSABKAMSEAoIYXVkaWVuY2UYCiADKAkSEAoIcHJpb3JpdHkYCyABKAESFQoNbGFzdF9tb2RpZmllZBgMIAEoCSKcAQoES2luZBIUChBLSU5EX1VOU1BFQ0lGSUVEEAASDQoJS0lORF9URVhUEAESDgoKS0lORF9JTUFHRRACEg4KCktJTkRfQVVESU8QAxIWChJLSU5EX1JFU09VUkNFX0xJTksQBBIaChZLSU5EX0VNQkVEREVEX1JFU09VUkNFEAUSGwoXS0lORF9TVFJVQ1RVUkVEX0NPTlRFTlQQBiIpCgpSZXRyeVN0YXJ0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiVgoGUHJvbXB0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESDAoEdGV4dBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50In4KDlJlc3VtZUFwcHJvdmFsEhcKBmFza19pZBgBIAEoCUIHukgEcgIQARINCgVhbGxvdxgCIAEoCBIrCgd2ZXJkaWN0GAMgASgOMhoubWVjYXRsLnYxLkFwcHJvdmFsVmVyZGljdBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiIQoGQ2FuY2VsEhcKD2V4cGVjdGVkX3J1bl9pZBgBIAEoCSIoCgtDYW5jZWxDaGlsZBIZCghjaGlsZF9pZBgBIAEoCUIHukgEcgIQASJlCgVTdGVlchIMCgR0ZXh0GAEgASgJEhIKCm1lc3NhZ2VfaWQYAiABKAkSIQoFcGFydHMYAyADKAsyEi5tZWNhdGwudjEuQ29udGVudBIXCg9leHBlY3RlZF9ydW5faWQYBCABKAkiOgoLU3RlZXJDYW5jZWwSEgoKbWVzc2FnZV9pZBgBIAEoCRIXCg9leHBlY3RlZF9ydW5faWQYAiABKAkiaAomR2V0TWNwQXV0aG9yaXphdGlvblByZXNlbnRhdGlvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQARIhChBhdXRob3JpemF0aW9uX2lkGAIgASgJQge6SARyAhABIjYKJ0dldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRILCgN1cmwYASABKAkitAEKHlJlY2hlY2tNY3BBdXRob3JpemF0aW9uUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhgKEGF1dGhvcml6YXRpb25faWQYAiABKAkSNAoPcmVzdW1lX2FwcHJvdmFsGAogASgLMhkubWVjYXRsLnYxLlJlc3VtZUFwcHJvdmFsSAASIwoGY2FuY2VsGAsgASgLMhEubWVjYXRsLnYxLkNhbmNlbEgAQgkKB2NvbnRyb2wiQgofUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKzAQodQ2FuY2VsTWNwQXV0aG9yaXphdGlvblJlcXVlc3QSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBhdXRob3JpemF0aW9uX2lkGAIgASgJEjQKD3Jlc3VtZV9hcHByb3ZhbBgKIAEoCzIZLm1lY2F0bC52MS5SZXN1bWVBcHByb3ZhbEgAEiMKBmNhbmNlbBgLIAEoCzIRLm1lY2F0bC52MS5DYW5jZWxIAEIJCgdjb250cm9sIkEKHkNhbmNlbE1jcEF1dGhvcml6YXRpb25SZXNwb25zZRIfCgVldmVudBgBIAEoCzIQLm1lY2F0bC52MS5FdmVudCKQAQoNQXV0aG9yaXphdGlvbhIYChBhdXRob3JpemF0aW9uX2lkGAEgASgJEg8KB2NhbGxfaWQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASDgoGc3RhdHVzGAQgASgJEhQKDGRpc3BsYXlfbmFtZRgFIAEoCSLQBgoFRXZlbnQSDAoEdHlwZRgBIAEoCRILCgNzZXEYAiABKAMSDAoEdHVybhgDIAEoBRIMCgR0ZXh0GAQgASgJEiYKCXRvb2xfY2FsbBgFIAEoCzITLm1lY2F0bC52MS5Ub29sQ2FsbBIqCgt0b29sX3Jlc3VsdBgGIAEoCzIVLm1lY2F0bC52MS5Ub29sUmVzdWx0EiUKA2FzaxgHIAEoCzIYLm1lY2F0bC52MS5QZXJtaXNzaW9uQXNrEiEKBnJlc3VsdBgIIAEoCzIRLm1lY2F0bC52MS5SZXN1bHQSHwoFdXNhZ2UYCSABKAsyEC5tZWNhdGwudjEuVXNhZ2USJAoIdHVybl9lbmQYCiABKAsyEi5tZWNhdGwudjEuVHVybkVuZBIdCgRob29rGAsgASgLMg8ubWVjYXRsLnYxLkhvb2sSJQoIc3ViYWdlbnQYDCABKAsyEy5tZWNhdGwudjEuU3ViYWdlbnQSHQoEdGVhbRgNIAEoCzIPLm1lY2F0bC52MS5UZWFtEiUKCHBhcmFsbGVsGA4gASgLMhMubWVjYXRsLnYxLlBhcmFsbGVsEiwKCHNjaGVkdWxlGA8gASgLMhoubWVjYXRsLnYxLlNjaGVkdWxlUGF5bG9hZBIlCghhcHByb3ZhbBgQIAEoCzITLm1lY2F0bC52MS5BcHByb3ZhbBIqCgt1c2VyX3Byb21wdBgRIAEoCzIVLm1lY2F0bC52MS5Vc2VyUHJvbXB0EjgKEmNvbXBhY3Rpb25fYXJjaGl2ZRgSIAEoCzIcLm1lY2F0bC52MS5Db21wYWN0aW9uQXJjaGl2ZRIjCgVzdGVlchgTIAEoCzIULm1lY2F0bC52MS5TdGVlckVjaG8SKgoNc3RlZXJfb3V0Y29tZRgUIAEoCzITLm1lY2F0bC52MS5TdGVlckFjaxIqCgttb2RlbF9yZXRyeRgVIAEoCzIVLm1lY2F0bC52MS5Nb2RlbFJldHJ5Eg4KBnJ1bl9pZBgWIAEoCRImCgV0aXRsZRgXIAEoCzIXLm1lY2F0bC52MS5TZXNzaW9uVGl0bGUSLwoNYXV0aG9yaXphdGlvbhgYIAEoCzIYLm1lY2F0bC52MS5BdXRob3JpemF0aW9uIngKCk1vZGVsUmV0cnkSNgoRcmV0cnlfZGlzcG9zaXRpb24YASABKA4yGy5tZWNhdGwudjEuUmV0cnlEaXNwb3NpdGlvbhIyCg9zdHJlYW1fcHJvZ3Jlc3MYAiABKA4yGS5tZWNhdGwudjEuU3RyZWFtUHJvZ3Jlc3MiUAoJU3RlZXJFY2hvEgwKBHRleHQYASABKAkSEgoKbWVzc2FnZV9pZBgCIAEoCRIhCgVwYXJ0cxgDIAMoCzISLm1lY2F0bC52MS5Db250ZW50ImgKCFN0ZWVyQWNrEigKB291dGNvbWUYASABKA4yFy5tZWNhdGwudjEuU3RlZXJPdXRjb21lEgwKBHRleHQYAiABKAkSEAoIcHJvbW90ZWQYAyABKAgSEgoKbWVzc2FnZV9pZBgEIAEoCSJgCghBcHByb3ZhbBIOCgZhc2tfaWQYASABKAkSDwoHdmVyZGljdBgCIAEoCRIMCgR0b29sGAMgASgJEg8KB2NhbGxfaWQYBCABKAkSFAoMYWxsb3dfYWx3YXlzGAUgASgIIlAKClVzZXJQcm9tcHQSDAoEdGV4dBgBIAEoCRIhCgVwYXJ0cxgCIAMoCzISLm1lY2F0bC52MS5Db250ZW50EhEKCXN5bnRoZXRpYxgDIAEoCCJFChFDb21wYWN0aW9uQXJjaGl2ZRIwCghyZXBsYWNlZBgBIAMoCzIeLm1lY2F0bC52MS5Db252ZXJzYXRpb25NZXNzYWdlIu8BChNDb252ZXJzYXRpb25NZXNzYWdlEgwKBHJvbGUYASABKAkSDAoEdGV4dBgCIAEoCRInCgp0b29sX2NhbGxzGAMgAygLMhMubWVjYXRsLnYxLlRvb2xDYWxsEioKC3Rvb2xfcmVzdWx0GAQgASgLMhUubWVjYXRsLnYxLlRvb2xSZXN1bHQSEQoJcmVhc29uaW5nGAUgASgJEhYKDnByb3ZpZGVyX3BoYXNlGAYgASgJEiEKBXBhcnRzGAcgAygLMhIubWVjYXRsLnYxLkNvbnRlbnQSGQoRcmVhc29uaW5nX2l0ZW1faWQYCCABKAkidgoPU2NoZWR1bGVQYXlsb2FkEhUKDXNjaGVkdWxlX25hbWUYASABKAkSDwoHZmlyZV9pZBgCIAEoCRISCgpzZXNzaW9uX2lkGAMgASgJEgwKBGtpbmQYBCABKAkSDAoEc3RvcBgFIAEoCRILCgNlcnIYBiABKAkiXwoESG9vaxINCgVwaGFzZRgBIAEoCRIMCgR0b29sGAIgASgJEikKCGRlY2lzaW9uGAMgASgOMhcubWVjYXRsLnYxLkhvb2tEZWNpc2lvbhIPCgdjYWxsX2lkGAQgASgJIuoCCghTdWJhZ2VudBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIQCghjaGlsZF9pZBgCIAEoCRIMCgRnb2FsGAMgASgJEhEKCXRvb2xfbmFtZRgEIAEoCRIQCghpc19lcnJvchgFIAEoCBISCgp0b29sX2NvdW50GAYgASgFEh8KBXVzYWdlGAcgASgLMhAubWVjYXRsLnYxLlVzYWdlEgwKBHN0b3AYCCABKAkSEwoLZHVyYXRpb25fbXMYCSABKAMSEgoKYmFja2dyb3VuZBgKIAEoCBIXCg9yb3V0ZWRfY2F0ZWdvcnkYCyABKAkSFAoMcm91dGVkX21vZGVsGAwgASgJEg0KBW1vZGVsGA0gASgJEhIKCmlubmVyX2tpbmQYDiABKAkSDAoEdGV4dBgPIAEoCRIOCgZkZXRhaWwYECABKAkSDQoFY2F1c2UYESABKAkSFgoOcm91dGluZ19yZWFzb24YEiABKAkiogEKDlRlYW1NZW1iZXJTcGVjEgwKBG5hbWUYASABKAkSDAoEcm9sZRgCIAEoCRIQCghtdXRhdGluZxgDIAEoCBIMCgRsZWFkGAQgASgIEhcKD3JvdXRlZF9jYXRlZ29yeRgFIAEoCRIUCgxyb3V0ZWRfbW9kZWwYBiABKAkSDQoFbW9kZWwYByABKAkSFgoOcm91dGluZ19yZWFzb24YCCABKAki3gMKBFRlYW0SFgoOcGFyZW50X2NhbGxfaWQYASABKAkSDwoHdGVhbV9pZBgCIAEoCRIpCgZyb3N0ZXIYAyADKAsyGS5tZWNhdGwudjEuVGVhbU1lbWJlclNwZWMSDgoGbWVtYmVyGAQgASgJEhIKCmlubmVyX2tpbmQYBSABKAkSDAoEdGV4dBgGIAEoCRIRCgl0b29sX25hbWUYByABKAkSDgoGZGV0YWlsGAggASgJEhAKCGlzX2Vycm9yGAkgASgIEg4KBnJvdW5kcxgKIAEoBRIMCgRzdG9wGAsgASgJEh8KBXVzYWdlGAwgASgLMhAubWVjYXRsLnYxLlVzYWdlEhQKDGNvbnRleHRfdXNlZBgNIAEoAxIWCg5jb250ZXh0X3dpbmRvdxgOIAEoAxIiCgV0YXNrcxgPIAMoCzITLm1lY2F0bC52MS5UZWFtVGFzaxIoCghmaW5kaW5ncxgQIAMoCzIWLm1lY2F0bC52MS5UZWFtRmluZGluZxI2CgxkaXNwb3NpdGlvbnMYESADKAsyIC5tZWNhdGwudjEuVGVhbU1lbWJlckRpc3Bvc2l0aW9uEhkKEW1lbWJlcl9zZXNzaW9uX2lkGBIgASgJEg0KBWNhdXNlGBMgASgJIu4DCghQYXJhbGxlbBIWCg5wYXJlbnRfY2FsbF9pZBgBIAEoCRIMCgRraW5kGAIgASgJEgwKBGpvaW4YAyABKAkSFAoMYnJhbmNoX2NvdW50GAQgASgFEhQKDGJyYW5jaF9pbmRleBgFIAEoBRIUCgxicmFuY2hfbGFiZWwYBiABKAkSDAoEZ29hbBgHIAEoCRIRCgl0b29sX25hbWUYCCABKAkSEAoIaXNfZXJyb3IYCSABKAgSEgoKdG9vbF9jb3VudBgKIAEoBRIOCgZmYWlsZWQYCyABKAgSDAoEc3RvcBgNIAEoCRIfCgV1c2FnZRgOIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgPIAEoAxIOCgZ3aW5uZXIYECABKAUSEAoIY2hpbGRfaWQYEiABKAkSFwoPcm91dGVkX2NhdGVnb3J5GBMgASgJEhQKDHJvdXRlZF9tb2RlbBgUIAEoCRINCgVtb2RlbBgVIAEoCRISCgppbm5lcl9raW5kGBYgASgJEgwKBHRleHQYFyABKAkSDgoGZGV0YWlsGBggASgJEhYKDnJvdXRpbmdfcmVhc29uGBkgASgJSgQIDBANSgQIERASUgl3b3Jrc3BhY2VSEHdpbm5lcl93b3Jrc3BhY2UiMgoIVG9vbENhbGwSCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRhcmdzGAMgASgJIoUBCgpUb29sUmVzdWx0Eg8KB2NhbGxfaWQYASABKAkSDwoHY29udGVudBgCIAEoCRIQCghpc19lcnJvchgDIAEoCBInCgZibG9ja3MYBCADKAsyFy5tZWNhdGwudjEuQ29udGVudEJsb2NrEhoKEnN0cnVjdHVyZWRfY29udGVudBgFIAEoCSJLCg1QZXJtaXNzaW9uQXNrEg4KBmFza19pZBgBIAEoCRIMCgR0b29sGAIgASgJEgwKBGFyZ3MYAyABKAkSDgoGcmVhc29uGAQgASgJIocCCgZSZXN1bHQSDAoEc3RvcBgBIAEoCRIMCgR0ZXh0GAIgASgJEh8KBXVzYWdlGAMgASgLMhAubWVjYXRsLnYxLlVzYWdlEg0KBWVycm9yGAQgASgJEhEKCXBlcm1hbmVudBgFIAEoCBI7ChFyZXRyeV9kaXNwb3NpdGlvbhgGIAEoDjIbLm1lY2F0bC52MS5SZXRyeURpc3Bvc2l0aW9uSACIAQESNwoPc3RyZWFtX3Byb2dyZXNzGAcgASgOMhkubWVjYXRsLnYxLlN0cmVhbVByb2dyZXNzSAGIAQFCFAoSX3JldHJ5X2Rpc3Bvc2l0aW9uQhIKEF9zdHJlYW1fcHJvZ3Jlc3MiPwoHVHVybkVuZBIfCgV1c2FnZRgBIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRITCgtkdXJhdGlvbl9tcxgCIAEoAyKFAQoFVXNhZ2USFAoMaW5wdXRfdG9rZW5zGAEgASgDEhUKDW91dHB1dF90b2tlbnMYAiABKAMSGQoRY2FjaGVfcmVhZF90b2tlbnMYAyABKAMSGgoSY2FjaGVfd3JpdGVfdG9rZW5zGAQgASgDEhgKEHJlYXNvbmluZ190b2tlbnMYBSABKAMikAEKC01jcFJlc291cmNlEg4KBnNlcnZlchgBIAEoCRILCgN1cmkYAiABKAkSDAoEbmFtZRgDIAEoCRINCgV0aXRsZRgEIAEoCRITCgtkZXNjcmlwdGlvbhgFIAEoCRIRCgltaW1lX3R5cGUYBiABKAkSDAoEc2l6ZRgHIAEoAxIRCglyZWFkX29ubHkYCCABKAgiKQoXTGlzdE1jcFJlc291cmNlc1JlcXVlc3QSDgoGc2VydmVyGAEgASgJIkUKGExpc3RNY3BSZXNvdXJjZXNSZXNwb25zZRIpCglyZXNvdXJjZXMYASADKAsyFi5tZWNhdGwudjEuTWNwUmVzb3VyY2UiUQoTTWNwUmVzb3VyY2VDb250ZW50cxILCgN1cmkYASABKAkSEQoJbWltZV90eXBlGAIgASgJEgwKBHRleHQYAyABKAkSDAoEYmxvYhgEIAEoDCJHChZSZWFkTWNwUmVzb3VyY2VSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIUCgN1cmkYAiABKAlCB7pIBHICEAEiSwoXUmVhZE1jcFJlc291cmNlUmVzcG9uc2USMAoIY29udGVudHMYASADKAsyHi5tZWNhdGwudjEuTWNwUmVzb3VyY2VDb250ZW50cyJXChFNY3BQcm9tcHRBcmd1bWVudBIMCgRuYW1lGAEgASgJEg0KBXRpdGxlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEhAKCHJlcXVpcmVkGAQgASgIIn4KCU1jcFByb21wdBIOCgZzZXJ2ZXIYASABKAkSDAoEbmFtZRgCIAEoCRINCgV0aXRsZRgDIAEoCRITCgtkZXNjcmlwdGlvbhgEIAEoCRIvCglhcmd1bWVudHMYBSADKAsyHC5tZWNhdGwudjEuTWNwUHJvbXB0QXJndW1lbnQiJwoVTGlzdE1jcFByb21wdHNSZXF1ZXN0Eg4KBnNlcnZlchgBIAEoCSI/ChZMaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEiUKB3Byb21wdHMYASADKAsyFC5tZWNhdGwudjEuTWNwUHJvbXB0IrkBChNHZXRNY3BQcm9tcHRSZXF1ZXN0EhcKBnNlcnZlchgBIAEoCUIHukgEcgIQARIVCgRuYW1lGAIgASgJQge6SARyAhABEkAKCWFyZ3VtZW50cxgDIAMoCzItLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0LkFyZ3VtZW50c0VudHJ5GjAKDkFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiLgoQTWNwUHJvbXB0TWVzc2FnZRIMCgRyb2xlGAEgASgJEgwKBHRleHQYAiABKAkiWgoUR2V0TWNwUHJvbXB0UmVzcG9uc2USEwoLZGVzY3JpcHRpb24YASABKAkSLQoIbWVzc2FnZXMYAiADKAsyGy5tZWNhdGwudjEuTWNwUHJvbXB0TWVzc2FnZSJMCg1NY3BTZXJ2ZXJJbmZvEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEhEKCXRyYW5zcG9ydBgDIAEoCRINCgVncm91cBgEIAEoCSKHAQoJTWNwU291cmNlEgwKBG5hbWUYASABKAkSDAoEa2luZBgCIAEoCRIPCgdlbmFibGVkGAMgASgIEg0KBWdyb3VwGAQgASgJEikKB3NlcnZlcnMYBSADKAsyGC5tZWNhdGwudjEuTWNwU2VydmVySW5mbxITCgtkaWFnbm9zdGljcxgGIAMoCSIXChVMaXN0TWNwU291cmNlc1JlcXVlc3QidQoWTGlzdE1jcFNvdXJjZXNSZXNwb25zZRIlCgdzb3VyY2VzGAEgAygLMhQubWVjYXRsLnYxLk1jcFNvdXJjZRIQCghyZXZpc2lvbhgCIAEoBBINCgVzdGFsZRgDIAEoCBITCgtyZWNvbmNpbGluZxgEIAEoCCI3ChhSZWZyZXNoTWNwU291cmNlc1JlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQASI+ChlSZWZyZXNoTWNwU291cmNlc1Jlc3BvbnNlEhAKCHJldmlzaW9uGAEgASgEEg8KB2NoYW5nZWQYAiABKAgiGwoZTGlzdFRvb2xIaXZlR3JvdXBzUmVxdWVzdCIsChpMaXN0VG9vbEhpdmVHcm91cHNSZXNwb25zZRIOCgZncm91cHMYASADKAkidAoJQWdlbnRJbmZvEgwKBG5hbWUYASABKAkSEwoLZGVzY3JpcHRpb24YAiABKAkSDQoFbW9kZWwYAyABKAkSDQoFdG9vbHMYBCADKAkSFwoPcGVybWlzc2lvbl9tb2RlGAUgASgJEg0KBWNvbG9yGAYgASgJIhMKEUxpc3RBZ2VudHNSZXF1ZXN0IjoKEkxpc3RBZ2VudHNSZXNwb25zZRIkCgZhZ2VudHMYASADKAsyFC5tZWNhdGwudjEuQWdlbnRJbmZvIiwKB0NvbW1hbmQSDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSIyChNMaXN0Q29tbWFuZHNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPAoUTGlzdENvbW1hbmRzUmVzcG9uc2USJAoIY29tbWFuZHMYASADKAsyEi5tZWNhdGwudjEuQ29tbWFuZCJpCghXb3JrdHJlZRIQCghzZWxlY3RvchgBIAEoCRIMCgRraW5kGAIgASgJEg0KBWxhYmVsGAMgASgJEg4KBmJyYW5jaBgEIAEoCRIQCghyZXZpc2lvbhgFIAEoCRIMCgRiYXJlGAYgASgIIjMKFExpc3RXb3JrdHJlZXNSZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAEiPwoVTGlzdFdvcmt0cmVlc1Jlc3BvbnNlEiYKCXdvcmt0cmVlcxgBIAMoCzITLm1lY2F0bC52MS5Xb3JrdHJlZSJwCglTa2lsbEluZm8SDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRITCgthZ2VudF9vd25lZBgDIAEoCBITCgtvd25lcl9hZ2VudBgEIAEoCRIWCg5hY3RpdmVfdmVyc2lvbhgFIAEoCSITChFMaXN0U2tpbGxzUmVxdWVzdCI6ChJMaXN0U2tpbGxzUmVzcG9uc2USJAoGc2tpbGxzGAEgAygLMhQubWVjYXRsLnYxLlNraWxsSW5mbyKhAQoIU291bEluZm8SDwoHY29udGVudBgBIAEoCRISCgpzaXplX2J5dGVzGAIgASgDEg4KBnNoYTI1NhgDIAEoCRIPCgdwcmVzZW50GAQgASgIEi0KCnByb3ZlbmFuY2UYBSABKA4yGS5tZWNhdGwudjEuU291bFByb3ZlbmFuY2USDwoHdHJ1c3RlZBgGIAEoCBIPCgdkcmlmdGVkGAcgASgIIhAKDkdldFNvdWxSZXF1ZXN0IjQKD0dldFNvdWxSZXNwb25zZRIhCgRzb3VsGAEgASgLMhMubWVjYXRsLnYxLlNvdWxJbmZvIjIKDlVzZXJNb2RlbEVudHJ5EgsKA2tleRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSIiChNHZXRVc2VyTW9kZWxSZXF1ZXN0EgsKA2tleRgBIAEoCSKWAgoRVXNlck1vZGVsUmV2aXNpb24SCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSDgoGc3RhdHVzGAUgASgJEg4KBndyaXRlchgGIAEoCRIOCgZvcmlnaW4YByABKAkSGQoRc291cmNlX3Nlc3Npb25faWQYCCABKAkSGgoSc291cmNlX3Byb3Bvc2FsX2lkGAkgASgJEi4KCnVwZGF0ZWRfYXQYCyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSgQIChALUg9zb3VyY2VfZXZlbnRfaWRSEXNvdXJjZV9tZXNzYWdlX2lkIooBCg9Vc2VyTW9kZWxEZXRhaWwSLQoHY3VycmVudBgBIAEoCzIcLm1lY2F0bC52MS5Vc2VyTW9kZWxSZXZpc2lvbhItCgdoaXN0b3J5GAIgAygLMhwubWVjYXRsLnYxLlVzZXJNb2RlbFJldmlzaW9uEhkKEWhpc3RvcnlfYXZhaWxhYmxlGAMgASgIIpIBChRHZXRVc2VyTW9kZWxSZXNwb25zZRIqCgdlbnRyaWVzGAEgAygLMhkubWVjYXRsLnYxLlVzZXJNb2RlbEVudHJ5EhIKCnNpemVfYnl0ZXMYAiABKAMSDgoGc2hhMjU2GAMgASgJEioKBmRldGFpbBgEIAEoCzIaLm1lY2F0bC52MS5Vc2VyTW9kZWxEZXRhaWwiewoJTW9kZWxJbmZvEgoKAmlkGAEgASgJEhMKC3Byb3ZpZGVyX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRINCgVpbWFnZRgEIAEoCBIRCglyZWFzb25pbmcYBSABKAgSFQoNY29udGV4dF9saW1pdBgGIAEoAyITChFMaXN0TW9kZWxzUmVxdWVzdCKbAQoOUHJvdmlkZXJTdGF0dXMSEwoLcHJvdmlkZXJfaWQYASABKAkSDQoFc3RhdGUYAiABKAkSDAoEaGludBgDIAEoCRIjChtkZWZhdWx0X21vZGVsX2F1dG9fc2VsZWN0ZWQYBCABKAgSEwoLbW9kZWxfY291bnQYBSABKAUSHQoVYXZhaWxhYmxlX25vdF9kZWZhdWx0GAYgASgIIm4KEkxpc3RNb2RlbHNSZXNwb25zZRIkCgZtb2RlbHMYASADKAsyFC5tZWNhdGwudjEuTW9kZWxJbmZvEjIKD3Byb3ZpZGVyX3N0YXR1cxgCIAMoCzIZLm1lY2F0bC52MS5Qcm92aWRlclN0YXR1cyJBChVSZWZsZWN0U2Vzc2lvblJlcXVlc3QSGwoKc2Vzc2lvbl9pZBgBIAEoCUIHukgEcgIQAUoECAIQA1IFYXN5bmMiuQEKEVJlZmxlY3Rpb25SZWNlaXB0EhUKDXJlZmxlY3Rpb25faWQYASABKAkSEwoLZGlzcG9zaXRpb24YAiABKAkSDgoGcXVldWVkGAMgASgFEhEKCWFic3RhaW5lZBgEIAEoCBIOCgZzdGFnZWQYBSABKAUSEAoIcHJvbW90ZWQYBiABKAUSEgoKY29uZmxpY3RlZBgHIAEoBRIOCgZyZWFzb24YCCABKAkSDwoHbWVzc2FnZRgJIAEoCSJHChZSZWZsZWN0U2Vzc2lvblJlc3BvbnNlEi0KB3JlY2VpcHQYASABKAsyHC5tZWNhdGwudjEuUmVmbGVjdGlvblJlY2VpcHQi8QIKD0xlYXJuaW5nQXR0ZW1wdBIKCgJpZBgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEg0KBXN0YXRlGAMgASgJEg8KB291dGNvbWUYBCABKAkSFAoMZmFpbHVyZV9jb2RlGAUgASgJEhoKEmF0dGVtcHRfZ2VuZXJhdGlvbhgGIAEoBBIYChBjbGFpbV9nZW5lcmF0aW9uGAcgASgEEjQKEGNsYWltX2V4cGlyZXNfYXQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhgKEGNoZWNrcG9pbnRfc3RhZ2UYCSABKAkSEwoLcHJvcG9zYWxfaWQYCiABKAkSEAoIc2tpbGxfaWQYCyABKAkSLgoKY3JlYXRlZF9hdBgMIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgNIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiMAoZR2V0TGVhcm5pbmdBdHRlbXB0UmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASJJChpHZXRMZWFybmluZ0F0dGVtcHRSZXNwb25zZRIrCgdhdHRlbXB0GAEgASgLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdCJLChtMaXN0TGVhcm5pbmdBdHRlbXB0c1JlcXVlc3QSDQoFc3RhdGUYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFImEKHExpc3RMZWFybmluZ0F0dGVtcHRzUmVzcG9uc2USLAoIYXR0ZW1wdHMYASADKAsyGi5tZWNhdGwudjEuTGVhcm5pbmdBdHRlbXB0EhMKC25leHRfY3Vyc29yGAIgASgJIlYKHE11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQASJMCh1NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRIrCgdhdHRlbXB0GAEgASgLMhoubWVjYXRsLnYxLkxlYXJuaW5nQXR0ZW1wdCJeChxMaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXF1ZXN0Eg4KBnN0YXR1cxgBIAEoCRIOCgZjdXJzb3IYAiABKAkSDQoFbGltaXQYAyABKAUSDwoHcHJvamVjdBgEIAEoCSK+AQoTTGVhcm5pbmdFdmlkZW5jZVJlZhISCgpzZXNzaW9uX2lkGAEgASgJEg8KB2xvY2F0b3IYAiABKAkSDwoHb3JkaW5hbBgDIAEoBRIRCglldmVudF9zZXEYBCABKAMSFAoMdG9vbF9jYWxsX2lkGAUgASgJEg4KBmRpZ2VzdBgGIAEoCRIRCglhdmFpbGFibGUYByABKAgSFAoMYXZhaWxhYmlsaXR5GAggASgJEg8KB3ByZXZpZXcYCSABKAkiZwoQTGVhcm5pbmdEZWNpc2lvbhIMCgRraW5kGAEgASgJEg0KBWFjdG9yGAIgASgJEg4KBnJlYXNvbhgDIAEoCRImCgJhdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAieQoYTGVhcm5pbmdQcm9tb3Rpb25SZWNlaXB0EhIKCm1lbW9yeV9rZXkYASABKAkSFwoPcHJldmlvdXNfZXhpc3RzGAIgASgIEhgKEHByZXZpb3VzX3ZlcnNpb24YAyABKAkSFgoOcmVzdWx0X3ZlcnNpb24YBCABKAkinAQKEExlYXJuaW5nUHJvcG9zYWwSCgoCaWQYASABKAkSDwoHdmVyc2lvbhgCIAEoCRIOCgZzdGF0dXMYAyABKAkSDAoEa2luZBgEIAEoCRILCgNrZXkYBSABKAkSDQoFdmFsdWUYBiABKAkSEwoLZGVzY3JpcHRpb24YByABKAkSDQoFdGl0bGUYCCABKAkSDAoEYm9keRgJIAEoCRIwCghldmlkZW5jZRgKIAMoCzIeLm1lY2F0bC52MS5MZWFybmluZ0V2aWRlbmNlUmVmEhAKCHRyaWdnZXJzGAsgAygJEi4KCWRlY2lzaW9ucxgMIAMoCzIbLm1lY2F0bC52MS5MZWFybmluZ0RlY2lzaW9uEjYKCXByb21vdGlvbhgNIAEoCzIjLm1lY2F0bC52MS5MZWFybmluZ1Byb21vdGlvblJlY2VpcHQSLgoKY3JlYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLgoKdXBkYXRlZF9hdBgPIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASFgoOcHJvamVjdF9zY29wZWQYECABKAgSGwoTcHJvbW90aW9uX2F2YWlsYWJsZRgRIAEoCBIkChxwcm9tb3Rpb25fdW5hdmFpbGFibGVfcmVhc29uGBIgASgJEhgKEGxlYXJuZWRfc2tpbGxfaWQYEyABKAkiZAodTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVzcG9uc2USLgoJcHJvcG9zYWxzGAEgAygLMhsubWVjYXRsLnYxLkxlYXJuaW5nUHJvcG9zYWwSEwoLbmV4dF9jdXJzb3IYAiABKAkiQgoaR2V0TGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESDwoHcHJvamVjdBgCIAEoCSJMChtHZXRMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCKTAQodRGVjaWRlTGVhcm5pbmdQcm9wb3NhbFJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESIQoQZXhwZWN0ZWRfdmVyc2lvbhgCIAEoCUIHukgEcgIQARIZCghkZWNpc2lvbhgDIAEoCUIHukgEcgIQARIOCgZyZWFzb24YBCABKAkSDwoHcHJvamVjdBgFIAEoCSJPCh5EZWNpZGVMZWFybmluZ1Byb3Bvc2FsUmVzcG9uc2USLQoIcHJvcG9zYWwYASABKAsyGy5tZWNhdGwudjEuTGVhcm5pbmdQcm9wb3NhbCJnChxVbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEiEKEGV4cGVjdGVkX3ZlcnNpb24YAiABKAlCB7pIBHICEAESDwoHcHJvamVjdBgDIAEoCSJOCh1VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXNwb25zZRItCghwcm9wb3NhbBgBIAEoCzIbLm1lY2F0bC52MS5MZWFybmluZ1Byb3Bvc2FsIuwDChNMZWFybmVkU2tpbGxWZXJzaW9uEgoKAmlkGAEgASgJEgwKBG5hbWUYAiABKAkSDwoHdmVyc2lvbhgDIAEoCRIQCghyZXZpc2lvbhgEIAEoCRINCgVzdGF0ZRgFIAEoCRITCgtvd25lcl9hZ2VudBgGIAEoCRITCgtkZXNjcmlwdGlvbhgHIAEoCRIMCgRib2R5GAggASgJEhIKCnN1cGVyc2VkZXMYCSABKAkSFgoOZXZpZGVuY2VfY291bnQYCiABKAUSMAoIZXZpZGVuY2UYCyADKAsyHi5tZWNhdGwudjEuTGVhcm5pbmdFdmlkZW5jZVJlZhIvCgtldmFsdWF0aW9ucxgMIAMoCzIaLm1lY2F0bC52MS5Ta2lsbEV2YWx1YXRpb24SLwoIcmVjZWlwdHMYDSADKAsyHS5tZWNhdGwudjEuU2tpbGxDaGFuZ2VSZWNlaXB0Ei4KCmNyZWF0ZWRfYXQYDiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCnVwZGF0ZWRfYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhkKEWluc3BlY3RfYXZhaWxhYmxlGBAgASgIEhYKDnVuZG9fYXZhaWxhYmxlGBEgASgIIpQBCg9Ta2lsbEV2YWx1YXRpb24SDwoHdmVyZGljdBgBIAEoCRITCgtmaXh0dXJlX2lkcxgCIAMoCRIQCghiYXNlbGluZRgDIAEoCRIRCgl0cmVhdG1lbnQYBCABKAkSDgoGcmVhc29uGAUgASgJEiYKAmF0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKCAwoSU2tpbGxDaGFuZ2VSZWNlaXB0EgoKAmlkGAEgASgJEhAKCHNraWxsX2lkGAIgASgJEgwKBG5hbWUYAyABKAkSDwoHdmVyc2lvbhgEIAEoCRIRCglvcGVyYXRpb24YBSABKAkSEgoKZnJvbV9zdGF0ZRgGIAEoCRIQCgh0b19zdGF0ZRgHIAEoCRIWCg5ldmlkZW5jZV9jb3VudBgIIAEoBRIaChJzb3VyY2Vfc2Vzc2lvbl9pZHMYCSADKAkSHAoUc291cmNlX3Rvb2xfY2FsbF9pZHMYCiADKAkSDwoHdmVyZGljdBgLIAEoCRITCgtmaXh0dXJlX2lkcxgMIAMoCRIQCghiYXNlbGluZRgNIAEoCRIRCgl0cmVhdG1lbnQYDiABKAkSJgoCYXQYDyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhkKEWluc3BlY3RfYXZhaWxhYmxlGBAgASgIEhYKDnVuZG9fYXZhaWxhYmxlGBEgASgIIm4KGExpc3RMZWFybmVkU2tpbGxzUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEg4KBmN1cnNvchgCIAEoCRINCgVsaW1pdBgDIAEoBRINCgVzdGF0ZRgEIAEoCRITCgtvd25lcl9hZ2VudBgFIAEoCSKFAQoZTGlzdExlYXJuZWRTa2lsbHNSZXNwb25zZRIuCgZza2lsbHMYASADKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhITCgtuZXh0X2N1cnNvchgCIAEoCRISCgpnZW5lcmF0aW9uGAMgASgEEg8KB3Byb2plY3QYBCABKAkibQoWR2V0TGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEg8KB3ZlcnNpb24YBCABKAkibQoXR2V0TGVhcm5lZFNraWxsUmVzcG9uc2USLQoFc2tpbGwYASABKAsyHi5tZWNhdGwudjEuTGVhcm5lZFNraWxsVmVyc2lvbhISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkioQEKH0RpZmZMZWFybmVkU2tpbGxWZXJzaW9uc1JlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIdCgxmcm9tX3ZlcnNpb24YBCABKAlCB7pIBHICEAESGwoKdG9fdmVyc2lvbhgFIAEoCUIHukgEcgIQASKRAQogRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVzcG9uc2USDAoEZGlmZhgBIAEoCRISCgpnZW5lcmF0aW9uGAIgASgEEg8KB3Byb2plY3QYAyABKAkSEAoIc2tpbGxfaWQYBCABKAkSFAoMZnJvbV92ZXJzaW9uGAUgASgJEhIKCnRvX3ZlcnNpb24YBiABKAkinQEKGU11dGF0ZUxlYXJuZWRTa2lsbFJlcXVlc3QSDwoHcHJvamVjdBgBIAEoCRIcCgtvd25lcl9hZ2VudBgCIAEoCUIHukgEcgIQARITCgJpZBgDIAEoCUIHukgEcgIQARIYCgd2ZXJzaW9uGAQgASgJQge6SARyAhABEiIKEWV4cGVjdGVkX3JldmlzaW9uGAUgASgJQge6SARyAhABIqcBChpNdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRItCgVza2lsbBgBIAEoCzIeLm1lY2F0bC52MS5MZWFybmVkU2tpbGxWZXJzaW9uEhIKCmdlbmVyYXRpb24YAiABKAQSDwoHcHJvamVjdBgDIAEoCRIaChJwdWJsaWNhdGlvbl9zdGF0dXMYBCABKAkSGQoRcHVibGljYXRpb25fZXJyb3IYBSABKAkipgEKG1JvbGxiYWNrTGVhcm5lZFNraWxsUmVxdWVzdBIPCgdwcm9qZWN0GAEgASgJEhwKC293bmVyX2FnZW50GAIgASgJQge6SARyAhABEhMKAmlkGAMgASgJQge6SARyAhABEh8KDnRhcmdldF92ZXJzaW9uGAQgASgJQge6SARyAhABEiIKEWV4cGVjdGVkX3JldmlzaW9uGAUgASgJQge6SARyAhABIkkKF0xpc3RTa2lsbENoYW5nZXNSZXF1ZXN0Eg8KB3Byb2plY3QYASABKAkSDgoGY3Vyc29yGAIgASgJEg0KBWxpbWl0GAMgASgFIoQBChhMaXN0U2tpbGxDaGFuZ2VzUmVzcG9uc2USLgoHY2hhbmdlcxgBIAMoCzIdLm1lY2F0bC52MS5Ta2lsbENoYW5nZVJlY2VpcHQSEwoLbmV4dF9jdXJzb3IYAiABKAkSEgoKZ2VuZXJhdGlvbhgDIAEoBBIPCgdwcm9qZWN0GAQgASgJIo8BChFDcmVhdGVUZWFtUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABEgwKBG5hbWUYAiABKAkSKAoHbWVtYmVycxgDIAMoCzIXLm1lY2F0bC52MS5UZWFtbWF0ZVNwZWMSDAoEZ29hbBgEIAEoCRIXCg9tYXhfdGVhbV90b2tlbnMYBSABKAUiTQoSQ3JlYXRlVGVhbVJlc3BvbnNlEg8KB3RlYW1faWQYASABKAkSJgoHbWVtYmVycxgCIAMoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyInEKDFRlYW1tYXRlU3BlYxIVCgRuYW1lGAEgASgJQge6SARyAhABEhIKCmFnZW50X3R5cGUYAiABKAkSDAoEbGVhZBgDIAEoCBIQCghtdXRhdGluZxgEIAEoCBIWCg5pbml0aWFsX3Byb21wdBgFIAEoCSKTAQoUU3Bhd25UZWFtbWF0ZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARIVCgRuYW1lGAIgASgJQge6SARyAhABEhIKCmFnZW50X3R5cGUYAyABKAkSDAoEbGVhZBgEIAEoCBIQCghtdXRhdGluZxgFIAEoCBIWCg5pbml0aWFsX3Byb21wdBgGIAEoCSI+ChVTcGF3blRlYW1tYXRlUmVzcG9uc2USJQoGbWVtYmVyGAEgASgLMhUubWVjYXRsLnYxLlRlYW1NZW1iZXIicAoaU2VuZFRlYW1tYXRlTWVzc2FnZVJlcXVlc3QSGAoHdGVhbV9pZBgBIAEoCUIHukgEcgIQARITCgJ0bxgCIAEoCUIHukgEcgIQARIMCgRmcm9tGAMgASgJEhUKBGJvZHkYBCABKAlCB7pIBHICEAEiHQobU2VuZFRlYW1tYXRlTWVzc2FnZVJlc3BvbnNlIkoKFUNhbmNlbFRlYW1tYXRlUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABEhcKBm1lbWJlchgCIAEoCUIHukgEcgIQASIYChZDYW5jZWxUZWFtbWF0ZVJlc3BvbnNlIioKDlJ1blRlYW1SZXF1ZXN0EhgKB3RlYW1faWQYASABKAlCB7pIBHICEAEiZQoJVGVhbUV2ZW50Eg4KBm1lbWJlchgBIAEoCRIfCgVldmVudBgCIAEoCzIQLm1lY2F0bC52MS5FdmVudBInCgdvdXRjb21lGAMgASgLMhYubWVjYXRsLnYxLlRlYW1PdXRjb21lItsBCgtUZWFtT3V0Y29tZRIOCgZyb3VuZHMYASABKAUSEQoJcXVpZXNjZW50GAIgASgIEhgKEGJ1ZGdldF9leGhhdXN0ZWQYAyABKAgSDAoEc3RvcBgEIAEoCRIfCgV1c2FnZRgFIAEoCzIQLm1lY2F0bC52MS5Vc2FnZRI2CgxkaXNwb3NpdGlvbnMYBiADKAsyIC5tZWNhdGwudjEuVGVhbU1lbWJlckRpc3Bvc2l0aW9uEigKCGZpbmRpbmdzGAcgAygLMhYubWVjYXRsLnYxLlRlYW1GaW5kaW5nIisKD0xpc3RUZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABInEKEExpc3RUZWFtUmVzcG9uc2USJgoHbWVtYmVycxgBIAMoCzIVLm1lY2F0bC52MS5UZWFtTWVtYmVyEiIKBXRhc2tzGAIgAygLMhMubWVjYXRsLnYxLlRlYW1UYXNrEhEKCXF1aWVzY2VudBgDIAEoCCJRCgpUZWFtTWVtYmVyEgwKBG5hbWUYASABKAkSEgoKYWdlbnRfdHlwZRgCIAEoCRINCgVzdGF0ZRgDIAEoCRISCgpzZXNzaW9uX2lkGAQgASgJIloKCFRlYW1UYXNrEgoKAmlkGAEgASgJEhMKC2Rlc2NyaXB0aW9uGAIgASgJEg0KBXN0YXRlGAMgASgJEhAKCGFzc2lnbmVlGAQgASgJEgwKBGRlcHMYBSADKAkiKwoLVGVhbUZpbmRpbmcSDgoGbWVtYmVyGAEgASgJEgwKBGJvZHkYAiABKAkifQoVVGVhbU1lbWJlckRpc3Bvc2l0aW9uEgwKBG5hbWUYASABKAkSDwoHc3RvcHBlZBgCIAEoCBIvCgZyZWFzb24YAyABKA4yHy5tZWNhdGwudjEuVGVhbU1lbWJlclN0b3BSZWFzb24SFAoMZXJyb3Jfcm91bmRzGAQgASgFIi4KEkNsZWFudXBUZWFtUmVxdWVzdBIYCgd0ZWFtX2lkGAEgASgJQge6SARyAhABIhUKE0NsZWFudXBUZWFtUmVzcG9uc2UibwoSQXBwcm92ZVBsYW5SZXF1ZXN0EhsKCnNlc3Npb25faWQYASABKAlCB7pIBHICEAESLgoLdGFyZ2V0X21vZGUYAiABKA4yGS5tZWNhdGwudjEuUGVybWlzc2lvbk1vZGUSDAoEbm90ZRgDIAEoCSKJAQoXTWFudWFsRHJlYW1DYXBhYmlsaXRpZXMSOAoOcHJvamVjdF9tZW1vcnkYASABKAsyIC5tZWNhdGwudjEuRHJlYW1UYXJnZXRDYXBhYmlsaXR5EjQKCnVzZXJfbW9kZWwYAiABKAsyIC5tZWNhdGwudjEuRHJlYW1UYXJnZXRDYXBhYmlsaXR5IlUKFURyZWFtVGFyZ2V0Q2FwYWJpbGl0eRIQCghnZW5lcmF0ZRgBIAEoCBIOCgZkZWNpZGUYAiABKAgSGgoSdW5hdmFpbGFibGVfcmVhc29uGAMgASgJIioKGEdlbmVyYXRlRHJlYW1QbGFuUmVxdWVzdBIOCgZ0YXJnZXQYASABKAkiRQoZR2VuZXJhdGVEcmVhbVBsYW5SZXNwb25zZRIoCgRwbGFuGAEgASgLMhoubWVjYXRsLnYxLkRyZWFtUmV2aWV3UGxhbiI7ChZEZWNpZGVEcmVhbVBsYW5SZXF1ZXN0Eg8KB3BsYW5faWQYASABKAkSEAoIZGVjaXNpb24YAiABKAkiQwoXRGVjaWRlRHJlYW1QbGFuUmVzcG9uc2USKAoHcmVjZWlwdBgBIAEoCzIXLm1lY2F0bC52MS5EcmVhbVJlY2VpcHQiywEKD0RyZWFtUmV2aWV3UGxhbhIKCgJpZBgBIAEoCRIOCgZ0YXJnZXQYAiABKAkSLgoKZXhwaXJlc19hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASHwoXcGxhbm5lZF9vcGVyYXRpb25fY291bnQYBCABKAUSHAoUcGxhbm5lZF9zb3VyY2VfY291bnQYBSABKAUSLQoKb3BlcmF0aW9ucxgGIAMoCzIZLm1lY2F0bC52MS5EcmVhbU9wZXJhdGlvbiLfAQoORHJlYW1PcGVyYXRpb24SDAoEa2luZBgBIAEoCRItCghzdXJ2aXZvchgCIAEoCzIbLm1lY2F0bC52MS5EcmVhbVBhcnRpY2lwYW50EiwKB3NvdXJjZXMYAyADKAsyGy5tZWNhdGwudjEuRHJlYW1QYXJ0aWNpcGFudBIwCgtyZXBsYWNlbWVudBgEIAEoCzIbLm1lY2F0bC52MS5EcmVhbVJlcGxhY2VtZW50Eg4KBnJlYXNvbhgFIAEoCRIgChhleGFjdF9kdXBsaWNhdGVfZWxpZ2libGUYBiABKAgiQwoQRHJlYW1QYXJ0aWNpcGFudBILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkiNgoQRHJlYW1SZXBsYWNlbWVudBINCgV2YWx1ZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCSLXAQoMRHJlYW1SZWNlaXB0EgoKAmlkGAEgASgJEg4KBnRhcmdldBgCIAEoCRITCgtkaXNwb3NpdGlvbhgDIAEoCRIcChRwbGFubmVkX3NvdXJjZV9jb3VudBgEIAEoBRIcChRhcHBsaWVkX3NvdXJjZV9jb3VudBgFIAEoBRIfChdjb25mbGljdGVkX3NvdXJjZV9jb3VudBgGIAEoBRIcChRza2lwcGVkX3NvdXJjZV9jb3VudBgHIAEoBRIbChNmYWlsZWRfc291cmNlX2NvdW50GAggASgFIjQKFUNvbXBhY3RTZXNzaW9uUmVxdWVzdBIbCgpzZXNzaW9uX2lkGAEgASgJQge6SARyAhABIisKFkNvbXBhY3RTZXNzaW9uUmVzcG9uc2USEQoJY29tcGFjdGVkGAEgASgIIjcKIVdvcmtzcGFjZUVucm9sbG1lbnRDb25uZWN0UmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJIk4KIVdvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBISCgpzZXNzaW9uX2lkGAEgASgJEhUKDWVucm9sbG1lbnRfaWQYAiABKAkicQoTV29ya3NwYWNlRW5yb2xsbWVudBIVCg1lbnJvbGxtZW50X2lkGAEgASgJEg4KBnN0YXR1cxgCIAEoCRIZChFyZXF1aXJlZF9zZXJ2aWNlcxgDIAEoDRIYChBwcmVzZW50YXRpb25fdXJsGAQgASgJKooBCg5QZXJtaXNzaW9uTW9kZRIfChtQRVJNSVNTSU9OX01PREVfVU5TUEVDSUZJRUQQABIbChdQRVJNSVNTSU9OX01PREVfREVGQVVMVBABEhgKFFBFUk1JU1NJT05fTU9ERV9QTEFOEAISIAocUEVSTUlTU0lPTl9NT0RFX0FDQ0VQVF9FRElUUxADKpIBCg9BcHByb3ZhbFZlcmRpY3QSIAocQVBQUk9WQUxfVkVSRElDVF9VTlNQRUNJRklFRBAAEhkKFUFQUFJPVkFMX1ZFUkRJQ1RfREVOWRABEh8KG0FQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfT05DRRACEiEKHUFQUFJPVkFMX1ZFUkRJQ1RfQUxMT1dfQUxXQVlTEAMqvgEKDFN0ZWVyT3V0Y29tZRIdChlTVEVFUl9PVVRDT01FX1VOU1BFQ0lGSUVEEAASGgoWU1RFRVJfT1VUQ09NRV9BQ0NFUFRFRBABEhoKFlNURUVSX09VVENPTUVfQVBQRU5ERUQQAhIbChdTVEVFUl9PVVRDT01FX1JFVFJBQ1RFRBADEh4KGlNURUVSX09VVENPTUVfTk9ORV9QRU5ESU5HEAQSGgoWU1RFRVJfT1VUQ09NRV9UT09fTEFURRAFKpgBCgxIb29rRGVjaXNpb24SHQoZSE9PS19ERUNJU0lPTl9VTlNQRUNJRklFRBAAEhYKEkhPT0tfREVDSVNJT05fSU5GTxABEhkKFUhPT0tfREVDSVNJT05fQkxPQ0tFRBACEhoKFkhPT0tfREVDSVNJT05fTU9ESUZJRUQQAxIaChZIT09LX0RFQ0lTSU9OX0FEVklTT1JZEAQqlgEKEFJldHJ5RGlzcG9zaXRpb24SIQodUkVUUllfRElTUE9TSVRJT05fVU5TUEVDSUZJRUQQABIdChlSRVRSWV9ESVNQT1NJVElPTl9VTktOT1dOEAESHwobUkVUUllfRElTUE9TSVRJT05fUkVUUllBQkxFEAISHwobUkVUUllfRElTUE9TSVRJT05fUEVSTUFORU5UEAMqqAEKDlN0cmVhbVByb2dyZXNzEh8KG1NUUkVBTV9QUk9HUkVTU19VTlNQRUNJRklFRBAAEhsKF1NUUkVBTV9QUk9HUkVTU19VTktOT1dOEAESHQoZU1RSRUFNX1BST0dSRVNTX1BSRUNPTU1JVBACEhsKF1NUUkVBTV9QUk9HUkVTU19WSVNJQkxFEAMSHAoYU1RSRUFNX1BST0dSRVNTX0NPTVBMRVRFEAQqhAEKDlNvdWxQcm92ZW5hbmNlEh8KG1NPVUxfUFJPVkVOQU5DRV9VTlNQRUNJRklFRBAAEhgKFFNPVUxfUFJPVkVOQU5DRV9VU0VSEAESGwoXU09VTF9QUk9WRU5BTkNFX1BST0pFQ1QQAhIaChZTT1VMX1BST1ZFTkFOQ0VfRFJJVkVSEAMqrQEKFFRlYW1NZW1iZXJTdG9wUmVhc29uEicKI1RFQU1fTUVNQkVSX1NUT1BfUkVBU09OX1VOU1BFQ0lGSUVEEAASIQodVEVBTV9NRU1CRVJfU1RPUF9SRUFTT05fRVJST1IQARIlCiFURUFNX01FTUJFUl9TVE9QX1JFQVNPTl9DQU5DRUxMRUQQAhIiCh5URUFNX01FTUJFUl9TVE9QX1JFQVNPTl9CVURHRVQQAzKBNgoOSGFybmVzc1NlcnZpY2USZwoUR2V0Q29tcGF0aWJpbGl0eUluZm8SJi5tZWNhdGwudjEuR2V0Q29tcGF0aWJpbGl0eUluZm9SZXF1ZXN0GicubWVjYXRsLnYxLkdldENvbXBhdGliaWxpdHlJbmZvUmVzcG9uc2USUgoNQ3JlYXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5DcmVhdGVTZXNzaW9uUmVzcG9uc2USUgoNR2V0U2VydmVySW5mbxIfLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVxdWVzdBogLm1lY2F0bC52MS5HZXRTZXJ2ZXJJbmZvUmVzcG9uc2USSQoKR2V0U2Vzc2lvbhIcLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVxdWVzdBodLm1lY2F0bC52MS5HZXRTZXNzaW9uUmVzcG9uc2USZwoUR2V0U2Vzc2lvblRyYW5zY3JpcHQSJi5tZWNhdGwudjEuR2V0U2Vzc2lvblRyYW5zY3JpcHRSZXF1ZXN0GicubWVjYXRsLnYxLkdldFNlc3Npb25UcmFuc2NyaXB0UmVzcG9uc2USQAoHU2V0TW9kZRIZLm1lY2F0bC52MS5TZXRNb2RlUmVxdWVzdBoaLm1lY2F0bC52MS5TZXRNb2RlUmVzcG9uc2USTwoMQ2xvc2VTZXNzaW9uEh4ubWVjYXRsLnYxLkNsb3NlU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xvc2VTZXNzaW9uUmVzcG9uc2USUgoNUmVuYW1lU2Vzc2lvbhIfLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5SZW5hbWVTZXNzaW9uUmVzcG9uc2USUgoNRGVsZXRlU2Vzc2lvbhIfLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVxdWVzdBogLm1lY2F0bC52MS5EZWxldGVTZXNzaW9uUmVzcG9uc2USVQoOQ29tcGFjdFNlc3Npb24SIC5tZWNhdGwudjEuQ29tcGFjdFNlc3Npb25SZXF1ZXN0GiEubWVjYXRsLnYxLkNvbXBhY3RTZXNzaW9uUmVzcG9uc2USTwoMQ2xlYXJTZXNzaW9uEh4ubWVjYXRsLnYxLkNsZWFyU2Vzc2lvblJlcXVlc3QaHy5tZWNhdGwudjEuQ2xlYXJTZXNzaW9uUmVzcG9uc2USTAoLRm9ya1Nlc3Npb24SHS5tZWNhdGwudjEuRm9ya1Nlc3Npb25SZXF1ZXN0Gh4ubWVjYXRsLnYxLkZvcmtTZXNzaW9uUmVzcG9uc2USRwoIQ29udmVyc2USGi5tZWNhdGwudjEuQ29udmVyc2VSZXF1ZXN0GhsubWVjYXRsLnYxLkNvbnZlcnNlUmVzcG9uc2UoATABElsKEExpc3RNY3BSZXNvdXJjZXMSIi5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1JlcXVlc3QaIy5tZWNhdGwudjEuTGlzdE1jcFJlc291cmNlc1Jlc3BvbnNlElgKD1JlYWRNY3BSZXNvdXJjZRIhLm1lY2F0bC52MS5SZWFkTWNwUmVzb3VyY2VSZXF1ZXN0GiIubWVjYXRsLnYxLlJlYWRNY3BSZXNvdXJjZVJlc3BvbnNlElUKDkxpc3RNY3BQcm9tcHRzEiAubWVjYXRsLnYxLkxpc3RNY3BQcm9tcHRzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwUHJvbXB0c1Jlc3BvbnNlEk8KDEdldE1jcFByb21wdBIeLm1lY2F0bC52MS5HZXRNY3BQcm9tcHRSZXF1ZXN0Gh8ubWVjYXRsLnYxLkdldE1jcFByb21wdFJlc3BvbnNlElUKDkxpc3RNY3BTb3VyY2VzEiAubWVjYXRsLnYxLkxpc3RNY3BTb3VyY2VzUmVxdWVzdBohLm1lY2F0bC52MS5MaXN0TWNwU291cmNlc1Jlc3BvbnNlEl4KEVJlZnJlc2hNY3BTb3VyY2VzEiMubWVjYXRsLnYxLlJlZnJlc2hNY3BTb3VyY2VzUmVxdWVzdBokLm1lY2F0bC52MS5SZWZyZXNoTWNwU291cmNlc1Jlc3BvbnNlEnMKGExpc3RTZXNzaW9uTWNwQ29ubmVjdG9ycxIqLm1lY2F0bC52MS5MaXN0U2Vzc2lvbk1jcENvbm5lY3RvcnNSZXF1ZXN0GisubWVjYXRsLnYxLkxpc3RTZXNzaW9uTWNwQ29ubmVjdG9yc1Jlc3BvbnNlEmEKEkxpc3RUb29sSGl2ZUdyb3VwcxIkLm1lY2F0bC52MS5MaXN0VG9vbEhpdmVHcm91cHNSZXF1ZXN0GiUubWVjYXRsLnYxLkxpc3RUb29sSGl2ZUdyb3Vwc1Jlc3BvbnNlEkkKCkxpc3RBZ2VudHMSHC5tZWNhdGwudjEuTGlzdEFnZW50c1JlcXVlc3QaHS5tZWNhdGwudjEuTGlzdEFnZW50c1Jlc3BvbnNlEk8KDExpc3RDb21tYW5kcxIeLm1lY2F0bC52MS5MaXN0Q29tbWFuZHNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RDb21tYW5kc1Jlc3BvbnNlElIKDUxpc3RXb3JrdHJlZXMSHy5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1JlcXVlc3QaIC5tZWNhdGwudjEuTGlzdFdvcmt0cmVlc1Jlc3BvbnNlElAKE1N0cmVhbVNlc3Npb25FdmVudHMSJS5tZWNhdGwudjEuU3RyZWFtU2Vzc2lvbkV2ZW50c1JlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJMChFTdHJlYW1TZXNzaW9uTGl2ZRIjLm1lY2F0bC52MS5TdHJlYW1TZXNzaW9uTGl2ZVJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJjChJXYXRjaFNlc3Npb25FdmVudHMSJC5tZWNhdGwudjEuV2F0Y2hTZXNzaW9uRXZlbnRzUmVxdWVzdBolLm1lY2F0bC52MS5XYXRjaFNlc3Npb25FdmVudHNSZXNwb25zZTABEogBCh9HZXRNY3BBdXRob3JpemF0aW9uUHJlc2VudGF0aW9uEjEubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXF1ZXN0GjIubWVjYXRsLnYxLkdldE1jcEF1dGhvcml6YXRpb25QcmVzZW50YXRpb25SZXNwb25zZRJ0ChdSZWNoZWNrTWNwQXV0aG9yaXphdGlvbhIpLm1lY2F0bC52MS5SZWNoZWNrTWNwQXV0aG9yaXphdGlvblJlcXVlc3QaKi5tZWNhdGwudjEuUmVjaGVja01jcEF1dGhvcml6YXRpb25SZXNwb25zZSgBMAEScQoWQ2FuY2VsTWNwQXV0aG9yaXphdGlvbhIoLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVxdWVzdBopLm1lY2F0bC52MS5DYW5jZWxNY3BBdXRob3JpemF0aW9uUmVzcG9uc2UoATABEk8KDExpc3RTZXNzaW9ucxIeLm1lY2F0bC52MS5MaXN0U2Vzc2lvbnNSZXF1ZXN0Gh8ubWVjYXRsLnYxLkxpc3RTZXNzaW9uc1Jlc3BvbnNlElsKEEdldFN0b3JhZ2VIZWFsdGgSIi5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlcXVlc3QaIy5tZWNhdGwudjEuR2V0U3RvcmFnZUhlYWx0aFJlc3BvbnNlEl8KFFBsYW5TZXNzaW9uTWlncmF0aW9uEiYubWVjYXRsLnYxLlBsYW5TZXNzaW9uTWlncmF0aW9uUmVxdWVzdBofLm1lY2F0bC52MS5TZXNzaW9uTWlncmF0aW9uUGxhbhJgChVBcHBseVNlc3Npb25NaWdyYXRpb24SJy5tZWNhdGwudjEuQXBwbHlTZXNzaW9uTWlncmF0aW9uUmVxdWVzdBoeLm1lY2F0bC52MS5TZXNzaW9uTWlncmF0aW9uSm9iEmIKFlJlc3VtZVNlc3Npb25NaWdyYXRpb24SKC5tZWNhdGwudjEuUmVzdW1lU2Vzc2lvbk1pZ3JhdGlvblJlcXVlc3QaHi5tZWNhdGwudjEuU2Vzc2lvbk1pZ3JhdGlvbkpvYhJiChZDYW5jZWxTZXNzaW9uTWlncmF0aW9uEigubWVjYXRsLnYxLkNhbmNlbFNlc3Npb25NaWdyYXRpb25SZXF1ZXN0Gh4ubWVjYXRsLnYxLlNlc3Npb25NaWdyYXRpb25Kb2ISYgoWR2V0U2Vzc2lvbk1pZ3JhdGlvbkpvYhIoLm1lY2F0bC52MS5HZXRTZXNzaW9uTWlncmF0aW9uSm9iUmVxdWVzdBoeLm1lY2F0bC52MS5TZXNzaW9uTWlncmF0aW9uSm9iEmEKElBsYW5TZXNzaW9uQ2xlYW51cBIkLm1lY2F0bC52MS5QbGFuU2Vzc2lvbkNsZWFudXBSZXF1ZXN0GiUubWVjYXRsLnYxLlBsYW5TZXNzaW9uQ2xlYW51cFJlc3BvbnNlElMKE0FwcGx5U2Vzc2lvbkNsZWFudXASJS5tZWNhdGwudjEuQXBwbHlTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRDYW5jZWxTZXNzaW9uQ2xlYW51cBImLm1lY2F0bC52MS5DYW5jZWxTZXNzaW9uQ2xlYW51cFJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJVChRHZXRTZXNzaW9uQ2xlYW51cEpvYhImLm1lY2F0bC52MS5HZXRTZXNzaW9uQ2xlYW51cEpvYlJlcXVlc3QaFS5tZWNhdGwudjEuQ2xlYW51cEpvYhJJCgpMaXN0U2tpbGxzEhwubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXF1ZXN0Gh0ubWVjYXRsLnYxLkxpc3RTa2lsbHNSZXNwb25zZRJACgdHZXRTb3VsEhkubWVjYXRsLnYxLkdldFNvdWxSZXF1ZXN0GhoubWVjYXRsLnYxLkdldFNvdWxSZXNwb25zZRJPCgxHZXRVc2VyTW9kZWwSHi5tZWNhdGwudjEuR2V0VXNlck1vZGVsUmVxdWVzdBofLm1lY2F0bC52MS5HZXRVc2VyTW9kZWxSZXNwb25zZRJVCg5SZWZsZWN0U2Vzc2lvbhIgLm1lY2F0bC52MS5SZWZsZWN0U2Vzc2lvblJlcXVlc3QaIS5tZWNhdGwudjEuUmVmbGVjdFNlc3Npb25SZXNwb25zZRJhChJHZXRMZWFybmluZ0F0dGVtcHQSJC5tZWNhdGwudjEuR2V0TGVhcm5pbmdBdHRlbXB0UmVxdWVzdBolLm1lY2F0bC52MS5HZXRMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJnChRMaXN0TGVhcm5pbmdBdHRlbXB0cxImLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdBdHRlbXB0c1JlcXVlc3QaJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nQXR0ZW1wdHNSZXNwb25zZRJpChRSZXRyeUxlYXJuaW5nQXR0ZW1wdBInLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXF1ZXN0GigubWVjYXRsLnYxLk11dGF0ZUxlYXJuaW5nQXR0ZW1wdFJlc3BvbnNlEmsKFkFiYW5kb25MZWFybmluZ0F0dGVtcHQSJy5tZWNhdGwudjEuTXV0YXRlTGVhcm5pbmdBdHRlbXB0UmVxdWVzdBooLm1lY2F0bC52MS5NdXRhdGVMZWFybmluZ0F0dGVtcHRSZXNwb25zZRJeChFHZW5lcmF0ZURyZWFtUGxhbhIjLm1lY2F0bC52MS5HZW5lcmF0ZURyZWFtUGxhblJlcXVlc3QaJC5tZWNhdGwudjEuR2VuZXJhdGVEcmVhbVBsYW5SZXNwb25zZRJYCg9EZWNpZGVEcmVhbVBsYW4SIS5tZWNhdGwudjEuRGVjaWRlRHJlYW1QbGFuUmVxdWVzdBoiLm1lY2F0bC52MS5EZWNpZGVEcmVhbVBsYW5SZXNwb25zZRJqChVMaXN0TGVhcm5pbmdQcm9wb3NhbHMSJy5tZWNhdGwudjEuTGlzdExlYXJuaW5nUHJvcG9zYWxzUmVxdWVzdBooLm1lY2F0bC52MS5MaXN0TGVhcm5pbmdQcm9wb3NhbHNSZXNwb25zZRJkChNHZXRMZWFybmluZ1Byb3Bvc2FsEiUubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GiYubWVjYXRsLnYxLkdldExlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJtChZEZWNpZGVMZWFybmluZ1Byb3Bvc2FsEigubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXF1ZXN0GikubWVjYXRsLnYxLkRlY2lkZUxlYXJuaW5nUHJvcG9zYWxSZXNwb25zZRJqChVVbmRvTGVhcm5pbmdQcm9tb3Rpb24SJy5tZWNhdGwudjEuVW5kb0xlYXJuaW5nUHJvbW90aW9uUmVxdWVzdBooLm1lY2F0bC52MS5VbmRvTGVhcm5pbmdQcm9tb3Rpb25SZXNwb25zZRJeChFMaXN0TGVhcm5lZFNraWxscxIjLm1lY2F0bC52MS5MaXN0TGVhcm5lZFNraWxsc1JlcXVlc3QaJC5tZWNhdGwudjEuTGlzdExlYXJuZWRTa2lsbHNSZXNwb25zZRJYCg9HZXRMZWFybmVkU2tpbGwSIS5tZWNhdGwudjEuR2V0TGVhcm5lZFNraWxsUmVxdWVzdBoiLm1lY2F0bC52MS5HZXRMZWFybmVkU2tpbGxSZXNwb25zZRJzChhEaWZmTGVhcm5lZFNraWxsVmVyc2lvbnMSKi5tZWNhdGwudjEuRGlmZkxlYXJuZWRTa2lsbFZlcnNpb25zUmVxdWVzdBorLm1lY2F0bC52MS5EaWZmTGVhcm5lZFNraWxsVmVyc2lvbnNSZXNwb25zZRJjChRBY3RpdmF0ZUxlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmEKElJlamVjdExlYXJuZWRTa2lsbBIkLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXF1ZXN0GiUubWVjYXRsLnYxLk11dGF0ZUxlYXJuZWRTa2lsbFJlc3BvbnNlEmIKE0FyY2hpdmVMZWFybmVkU2tpbGwSJC5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVxdWVzdBolLm1lY2F0bC52MS5NdXRhdGVMZWFybmVkU2tpbGxSZXNwb25zZRJlChRSb2xsYmFja0xlYXJuZWRTa2lsbBImLm1lY2F0bC52MS5Sb2xsYmFja0xlYXJuZWRTa2lsbFJlcXVlc3QaJS5tZWNhdGwudjEuTXV0YXRlTGVhcm5lZFNraWxsUmVzcG9uc2USWwoQTGlzdFNraWxsQ2hhbmdlcxIiLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVxdWVzdBojLm1lY2F0bC52MS5MaXN0U2tpbGxDaGFuZ2VzUmVzcG9uc2USSQoKTGlzdE1vZGVscxIcLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVxdWVzdBodLm1lY2F0bC52MS5MaXN0TW9kZWxzUmVzcG9uc2USSQoKQ3JlYXRlVGVhbRIcLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVxdWVzdBodLm1lY2F0bC52MS5DcmVhdGVUZWFtUmVzcG9uc2USUgoNU3Bhd25UZWFtbWF0ZRIfLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVxdWVzdBogLm1lY2F0bC52MS5TcGF3blRlYW1tYXRlUmVzcG9uc2USZAoTU2VuZFRlYW1tYXRlTWVzc2FnZRIlLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVxdWVzdBomLm1lY2F0bC52MS5TZW5kVGVhbW1hdGVNZXNzYWdlUmVzcG9uc2USVQoOQ2FuY2VsVGVhbW1hdGUSIC5tZWNhdGwudjEuQ2FuY2VsVGVhbW1hdGVSZXF1ZXN0GiEubWVjYXRsLnYxLkNhbmNlbFRlYW1tYXRlUmVzcG9uc2USPAoHUnVuVGVhbRIZLm1lY2F0bC52MS5SdW5UZWFtUmVxdWVzdBoULm1lY2F0bC52MS5UZWFtRXZlbnQwARJDCghMaXN0VGVhbRIaLm1lY2F0bC52MS5MaXN0VGVhbVJlcXVlc3QaGy5tZWNhdGwudjEuTGlzdFRlYW1SZXNwb25zZRJMCgtDbGVhbnVwVGVhbRIdLm1lY2F0bC52MS5DbGVhbnVwVGVhbVJlcXVlc3QaHi5tZWNhdGwudjEuQ2xlYW51cFRlYW1SZXNwb25zZRJACgtBcHByb3ZlUGxhbhIdLm1lY2F0bC52MS5BcHByb3ZlUGxhblJlcXVlc3QaEC5tZWNhdGwudjEuRXZlbnQwARJoChhDb25uZWN0V29ya3NwYWNlU2VydmljZXMSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbm5lY3RSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnQSaAoYUmV0cnlXb3Jrc3BhY2VFbnJvbGxtZW50EiwubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRDb250cm9sUmVxdWVzdBoeLm1lY2F0bC52MS5Xb3Jrc3BhY2VFbnJvbGxtZW50EmkKGUNhbmNlbFdvcmtzcGFjZUVucm9sbG1lbnQSLC5tZWNhdGwudjEuV29ya3NwYWNlRW5yb2xsbWVudENvbnRyb2xSZXF1ZXN0Gh4ubWVjYXRsLnYxLldvcmtzcGFjZUVucm9sbG1lbnRCogEKDWNvbS5tZWNhdGwudjFCDEhhcm5lc3NQcm90b1ABWj5naXRodWIuY29tL3N0YWNrbG9rL21lY2F0bC9jb250cmFjdHMvZ2VuL2dvL21lY2F0bC92MTttZWNhdGx2MaICA01YWKoCCU1lY2F0bC5WMcoCCU1lY2F0bFxWMeICFU1lY2F0bFxWMVxHUEJNZXRhZGF0YeoCCk1lY2F0bDo6VjFiBnByb3RvMw", [file_buf_validate_validate, file_google_protobuf_timestamp]); /** * Limits are the configured stop conditions for a session. A zero value in @@ -667,6 +667,14 @@ export type ServerCapabilities = Message<"mecatl.v1.ServerCapabilities"> & { * @generated from field: bool mcp_connector_status = 29; */ mcpConnectorStatus: boolean; + + /** + * mcp_refresh is true when direct/global MCP source reconciliation is wired. + * It is mutually exclusive with workspace_enrollment in a valid deployment. + * + * @generated from field: bool mcp_refresh = 30; + */ + mcpRefresh: boolean; }; /** @@ -6113,6 +6121,27 @@ export type ListMcpSourcesResponse = Message<"mecatl.v1.ListMcpSourcesResponse"> * @generated from field: repeated mecatl.v1.McpSource sources = 1; */ sources: McpSource[]; + + /** + * revision is the current published direct-runtime revision. + * + * @generated from field: uint64 revision = 2; + */ + revision: bigint; + + /** + * stale is true when source or candidate degradation retained an older runtime. + * + * @generated from field: bool stale = 3; + */ + stale: boolean; + + /** + * reconciling is true while the shared reconciler is processing a cycle. + * + * @generated from field: bool reconciling = 4; + */ + reconciling: boolean; }; /** @@ -6122,6 +6151,50 @@ export type ListMcpSourcesResponse = Message<"mecatl.v1.ListMcpSourcesResponse"> export const ListMcpSourcesResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_mecatl_v1_harness, 121); +/** + * RefreshMcpSourcesRequest names the owned session whose direct-name authority + * may be widened after reconciliation. + * + * @generated from message mecatl.v1.RefreshMcpSourcesRequest + */ +export type RefreshMcpSourcesRequest = Message<"mecatl.v1.RefreshMcpSourcesRequest"> & { + /** + * @generated from field: string session_id = 1; + */ + sessionId: string; +}; + +/** + * Describes the message mecatl.v1.RefreshMcpSourcesRequest. + * Use `create(RefreshMcpSourcesRequestSchema)` to create a new message. + */ +export const RefreshMcpSourcesRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mecatl_v1_harness, 122); + +/** + * RefreshMcpSourcesResponse identifies the request-pinned runtime snapshot. + * + * @generated from message mecatl.v1.RefreshMcpSourcesResponse + */ +export type RefreshMcpSourcesResponse = Message<"mecatl.v1.RefreshMcpSourcesResponse"> & { + /** + * @generated from field: uint64 revision = 1; + */ + revision: bigint; + + /** + * @generated from field: bool changed = 2; + */ + changed: boolean; +}; + +/** + * Describes the message mecatl.v1.RefreshMcpSourcesResponse. + * Use `create(RefreshMcpSourcesResponseSchema)` to create a new message. + */ +export const RefreshMcpSourcesResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mecatl_v1_harness, 123); + /** * ListToolHiveGroupsRequest requests the distinct ToolHive groups in the * resolved inventory. @@ -6136,7 +6209,7 @@ export type ListToolHiveGroupsRequest = Message<"mecatl.v1.ListToolHiveGroupsReq * Use `create(ListToolHiveGroupsRequestSchema)` to create a new message. */ export const ListToolHiveGroupsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 122); + messageDesc(file_mecatl_v1_harness, 124); /** * ListToolHiveGroupsResponse carries the distinct, non-empty ToolHive groups. @@ -6157,7 +6230,7 @@ export type ListToolHiveGroupsResponse = Message<"mecatl.v1.ListToolHiveGroupsRe * Use `create(ListToolHiveGroupsResponseSchema)` to create a new message. */ export const ListToolHiveGroupsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 123); + messageDesc(file_mecatl_v1_harness, 125); /** * AgentInfo is the inventory for one resolved agent definition. It mirrors the @@ -6218,7 +6291,7 @@ export type AgentInfo = Message<"mecatl.v1.AgentInfo"> & { * Use `create(AgentInfoSchema)` to create a new message. */ export const AgentInfoSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 124); + messageDesc(file_mecatl_v1_harness, 126); /** * ListAgentsRequest requests the resolved agent-definition snapshot. @@ -6233,7 +6306,7 @@ export type ListAgentsRequest = Message<"mecatl.v1.ListAgentsRequest"> & { * Use `create(ListAgentsRequestSchema)` to create a new message. */ export const ListAgentsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 125); + messageDesc(file_mecatl_v1_harness, 127); /** * ListAgentsResponse carries the resolved agent definitions. @@ -6254,7 +6327,7 @@ export type ListAgentsResponse = Message<"mecatl.v1.ListAgentsResponse"> & { * Use `create(ListAgentsResponseSchema)` to create a new message. */ export const ListAgentsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 126); + messageDesc(file_mecatl_v1_harness, 128); /** * Command is one discovered slash command's listing metadata. Mirrors @@ -6286,7 +6359,7 @@ export type Command = Message<"mecatl.v1.Command"> & { * Use `create(CommandSchema)` to create a new message. */ export const CommandSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 127); + messageDesc(file_mecatl_v1_harness, 129); /** * @generated from message mecatl.v1.ListCommandsRequest @@ -6303,7 +6376,7 @@ export type ListCommandsRequest = Message<"mecatl.v1.ListCommandsRequest"> & { * Use `create(ListCommandsRequestSchema)` to create a new message. */ export const ListCommandsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 128); + messageDesc(file_mecatl_v1_harness, 130); /** * ListCommandsResponse carries the discovered slash commands. @@ -6324,7 +6397,7 @@ export type ListCommandsResponse = Message<"mecatl.v1.ListCommandsResponse"> & { * Use `create(ListCommandsResponseSchema)` to create a new message. */ export const ListCommandsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 129); + messageDesc(file_mecatl_v1_harness, 131); /** * Worktree is one display-safe eligible placement choice. Selector is opaque, @@ -6369,7 +6442,7 @@ export type Worktree = Message<"mecatl.v1.Worktree"> & { * Use `create(WorktreeSchema)` to create a new message. */ export const WorktreeSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 130); + messageDesc(file_mecatl_v1_harness, 132); /** * @generated from message mecatl.v1.ListWorktreesRequest @@ -6386,7 +6459,7 @@ export type ListWorktreesRequest = Message<"mecatl.v1.ListWorktreesRequest"> & { * Use `create(ListWorktreesRequestSchema)` to create a new message. */ export const ListWorktreesRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 131); + messageDesc(file_mecatl_v1_harness, 133); /** * ListWorktreesResponse carries the discovered worktrees. @@ -6408,7 +6481,7 @@ export type ListWorktreesResponse = Message<"mecatl.v1.ListWorktreesResponse"> & * Use `create(ListWorktreesResponseSchema)` to create a new message. */ export const ListWorktreesResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 132); + messageDesc(file_mecatl_v1_harness, 134); /** * SkillInfo is one discovered skill's listing metadata: the activation name and @@ -6457,7 +6530,7 @@ export type SkillInfo = Message<"mecatl.v1.SkillInfo"> & { * Use `create(SkillInfoSchema)` to create a new message. */ export const SkillInfoSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 133); + messageDesc(file_mecatl_v1_harness, 135); /** * ListSkillsRequest requests the resolved skills inventory snapshot. @@ -6472,7 +6545,7 @@ export type ListSkillsRequest = Message<"mecatl.v1.ListSkillsRequest"> & { * Use `create(ListSkillsRequestSchema)` to create a new message. */ export const ListSkillsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 134); + messageDesc(file_mecatl_v1_harness, 136); /** * ListSkillsResponse carries the resolved skills inventory. @@ -6493,7 +6566,7 @@ export type ListSkillsResponse = Message<"mecatl.v1.ListSkillsResponse"> & { * Use `create(ListSkillsResponseSchema)` to create a new message. */ export const ListSkillsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 135); + messageDesc(file_mecatl_v1_harness, 137); /** * SoulInfo is the BUILD-TIME SNAPSHOT of the resolved soul: the selected soul's @@ -6564,7 +6637,7 @@ export type SoulInfo = Message<"mecatl.v1.SoulInfo"> & { * Use `create(SoulInfoSchema)` to create a new message. */ export const SoulInfoSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 136); + messageDesc(file_mecatl_v1_harness, 138); /** * GetSoulRequest requests the resolved soul snapshot. @@ -6579,7 +6652,7 @@ export type GetSoulRequest = Message<"mecatl.v1.GetSoulRequest"> & { * Use `create(GetSoulRequestSchema)` to create a new message. */ export const GetSoulRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 137); + messageDesc(file_mecatl_v1_harness, 139); /** * GetSoulResponse carries the resolved soul snapshot. @@ -6601,7 +6674,7 @@ export type GetSoulResponse = Message<"mecatl.v1.GetSoulResponse"> & { * Use `create(GetSoulResponseSchema)` to create a new message. */ export const GetSoulResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 138); + messageDesc(file_mecatl_v1_harness, 140); /** * UserModelEntry is one user-model fact's listing metadata: its key + a one-line @@ -6631,7 +6704,7 @@ export type UserModelEntry = Message<"mecatl.v1.UserModelEntry"> & { * Use `create(UserModelEntrySchema)` to create a new message. */ export const UserModelEntrySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 139); + messageDesc(file_mecatl_v1_harness, 141); /** * GetUserModelRequest requests the current user-model index. When key is set, @@ -6651,7 +6724,7 @@ export type GetUserModelRequest = Message<"mecatl.v1.GetUserModelRequest"> & { * Use `create(GetUserModelRequestSchema)` to create a new message. */ export const GetUserModelRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 140); + messageDesc(file_mecatl_v1_harness, 142); /** * UserModelRevision is one read-only lifecycle revision for detail inspection. @@ -6715,7 +6788,7 @@ export type UserModelRevision = Message<"mecatl.v1.UserModelRevision"> & { * Use `create(UserModelRevisionSchema)` to create a new message. */ export const UserModelRevisionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 141); + messageDesc(file_mecatl_v1_harness, 143); /** * @generated from message mecatl.v1.UserModelDetail @@ -6744,7 +6817,7 @@ export type UserModelDetail = Message<"mecatl.v1.UserModelDetail"> & { * Use `create(UserModelDetailSchema)` to create a new message. */ export const UserModelDetailSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 142); + messageDesc(file_mecatl_v1_harness, 144); /** * GetUserModelResponse carries the current user-model entries plus aggregate @@ -6789,7 +6862,7 @@ export type GetUserModelResponse = Message<"mecatl.v1.GetUserModelResponse"> & { * Use `create(GetUserModelResponseSchema)` to create a new message. */ export const GetUserModelResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 143); + messageDesc(file_mecatl_v1_harness, 145); /** * ModelInfo is one selectable model in the resolved inventory. It mirrors the @@ -6850,7 +6923,7 @@ export type ModelInfo = Message<"mecatl.v1.ModelInfo"> & { * Use `create(ModelInfoSchema)` to create a new message. */ export const ModelInfoSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 144); + messageDesc(file_mecatl_v1_harness, 146); /** * ListModelsRequest requests the selectable-model inventory. @@ -6865,7 +6938,7 @@ export type ListModelsRequest = Message<"mecatl.v1.ListModelsRequest"> & { * Use `create(ListModelsRequestSchema)` to create a new message. */ export const ListModelsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 145); + messageDesc(file_mecatl_v1_harness, 147); /** * ProviderStatus is one provider's last live-listing outcome, for client @@ -6943,7 +7016,7 @@ export type ProviderStatus = Message<"mecatl.v1.ProviderStatus"> & { * Use `create(ProviderStatusSchema)` to create a new message. */ export const ProviderStatusSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 146); + messageDesc(file_mecatl_v1_harness, 148); /** * ListModelsResponse carries the selectable models across AVAILABLE providers @@ -6977,7 +7050,7 @@ export type ListModelsResponse = Message<"mecatl.v1.ListModelsResponse"> & { * Use `create(ListModelsResponseSchema)` to create a new message. */ export const ListModelsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 147); + messageDesc(file_mecatl_v1_harness, 149); /** * @generated from message mecatl.v1.ReflectSessionRequest @@ -6994,7 +7067,7 @@ export type ReflectSessionRequest = Message<"mecatl.v1.ReflectSessionRequest"> & * Use `create(ReflectSessionRequestSchema)` to create a new message. */ export const ReflectSessionRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 148); + messageDesc(file_mecatl_v1_harness, 150); /** * @generated from message mecatl.v1.ReflectionReceipt @@ -7055,7 +7128,7 @@ export type ReflectionReceipt = Message<"mecatl.v1.ReflectionReceipt"> & { * Use `create(ReflectionReceiptSchema)` to create a new message. */ export const ReflectionReceiptSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 149); + messageDesc(file_mecatl_v1_harness, 151); /** * @generated from message mecatl.v1.ReflectSessionResponse @@ -7072,7 +7145,7 @@ export type ReflectSessionResponse = Message<"mecatl.v1.ReflectSessionResponse"> * Use `create(ReflectSessionResponseSchema)` to create a new message. */ export const ReflectSessionResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 150); + messageDesc(file_mecatl_v1_harness, 152); /** * LearningAttempt is deliberately content-free. It contains only the closed @@ -7153,7 +7226,7 @@ export type LearningAttempt = Message<"mecatl.v1.LearningAttempt"> & { * Use `create(LearningAttemptSchema)` to create a new message. */ export const LearningAttemptSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 151); + messageDesc(file_mecatl_v1_harness, 153); /** * @generated from message mecatl.v1.GetLearningAttemptRequest @@ -7170,7 +7243,7 @@ export type GetLearningAttemptRequest = Message<"mecatl.v1.GetLearningAttemptReq * Use `create(GetLearningAttemptRequestSchema)` to create a new message. */ export const GetLearningAttemptRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 152); + messageDesc(file_mecatl_v1_harness, 154); /** * @generated from message mecatl.v1.GetLearningAttemptResponse @@ -7187,7 +7260,7 @@ export type GetLearningAttemptResponse = Message<"mecatl.v1.GetLearningAttemptRe * Use `create(GetLearningAttemptResponseSchema)` to create a new message. */ export const GetLearningAttemptResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 153); + messageDesc(file_mecatl_v1_harness, 155); /** * @generated from message mecatl.v1.ListLearningAttemptsRequest @@ -7214,7 +7287,7 @@ export type ListLearningAttemptsRequest = Message<"mecatl.v1.ListLearningAttempt * Use `create(ListLearningAttemptsRequestSchema)` to create a new message. */ export const ListLearningAttemptsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 154); + messageDesc(file_mecatl_v1_harness, 156); /** * @generated from message mecatl.v1.ListLearningAttemptsResponse @@ -7236,7 +7309,7 @@ export type ListLearningAttemptsResponse = Message<"mecatl.v1.ListLearningAttemp * Use `create(ListLearningAttemptsResponseSchema)` to create a new message. */ export const ListLearningAttemptsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 155); + messageDesc(file_mecatl_v1_harness, 157); /** * @generated from message mecatl.v1.MutateLearningAttemptRequest @@ -7258,7 +7331,7 @@ export type MutateLearningAttemptRequest = Message<"mecatl.v1.MutateLearningAtte * Use `create(MutateLearningAttemptRequestSchema)` to create a new message. */ export const MutateLearningAttemptRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 156); + messageDesc(file_mecatl_v1_harness, 158); /** * @generated from message mecatl.v1.MutateLearningAttemptResponse @@ -7275,7 +7348,7 @@ export type MutateLearningAttemptResponse = Message<"mecatl.v1.MutateLearningAtt * Use `create(MutateLearningAttemptResponseSchema)` to create a new message. */ export const MutateLearningAttemptResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 157); + messageDesc(file_mecatl_v1_harness, 159); /** * @generated from message mecatl.v1.ListLearningProposalsRequest @@ -7309,7 +7382,7 @@ export type ListLearningProposalsRequest = Message<"mecatl.v1.ListLearningPropos * Use `create(ListLearningProposalsRequestSchema)` to create a new message. */ export const ListLearningProposalsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 158); + messageDesc(file_mecatl_v1_harness, 160); /** * @generated from message mecatl.v1.LearningEvidenceRef @@ -7370,7 +7443,7 @@ export type LearningEvidenceRef = Message<"mecatl.v1.LearningEvidenceRef"> & { * Use `create(LearningEvidenceRefSchema)` to create a new message. */ export const LearningEvidenceRefSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 159); + messageDesc(file_mecatl_v1_harness, 161); /** * @generated from message mecatl.v1.LearningDecision @@ -7402,7 +7475,7 @@ export type LearningDecision = Message<"mecatl.v1.LearningDecision"> & { * Use `create(LearningDecisionSchema)` to create a new message. */ export const LearningDecisionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 160); + messageDesc(file_mecatl_v1_harness, 162); /** * @generated from message mecatl.v1.LearningPromotionReceipt @@ -7434,7 +7507,7 @@ export type LearningPromotionReceipt = Message<"mecatl.v1.LearningPromotionRecei * Use `create(LearningPromotionReceiptSchema)` to create a new message. */ export const LearningPromotionReceiptSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 161); + messageDesc(file_mecatl_v1_harness, 163); /** * @generated from message mecatl.v1.LearningProposal @@ -7548,7 +7621,7 @@ export type LearningProposal = Message<"mecatl.v1.LearningProposal"> & { * Use `create(LearningProposalSchema)` to create a new message. */ export const LearningProposalSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 162); + messageDesc(file_mecatl_v1_harness, 164); /** * @generated from message mecatl.v1.ListLearningProposalsResponse @@ -7570,7 +7643,7 @@ export type ListLearningProposalsResponse = Message<"mecatl.v1.ListLearningPropo * Use `create(ListLearningProposalsResponseSchema)` to create a new message. */ export const ListLearningProposalsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 163); + messageDesc(file_mecatl_v1_harness, 165); /** * @generated from message mecatl.v1.GetLearningProposalRequest @@ -7592,7 +7665,7 @@ export type GetLearningProposalRequest = Message<"mecatl.v1.GetLearningProposalR * Use `create(GetLearningProposalRequestSchema)` to create a new message. */ export const GetLearningProposalRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 164); + messageDesc(file_mecatl_v1_harness, 166); /** * @generated from message mecatl.v1.GetLearningProposalResponse @@ -7609,7 +7682,7 @@ export type GetLearningProposalResponse = Message<"mecatl.v1.GetLearningProposal * Use `create(GetLearningProposalResponseSchema)` to create a new message. */ export const GetLearningProposalResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 165); + messageDesc(file_mecatl_v1_harness, 167); /** * @generated from message mecatl.v1.DecideLearningProposalRequest @@ -7646,7 +7719,7 @@ export type DecideLearningProposalRequest = Message<"mecatl.v1.DecideLearningPro * Use `create(DecideLearningProposalRequestSchema)` to create a new message. */ export const DecideLearningProposalRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 166); + messageDesc(file_mecatl_v1_harness, 168); /** * @generated from message mecatl.v1.DecideLearningProposalResponse @@ -7663,7 +7736,7 @@ export type DecideLearningProposalResponse = Message<"mecatl.v1.DecideLearningPr * Use `create(DecideLearningProposalResponseSchema)` to create a new message. */ export const DecideLearningProposalResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 167); + messageDesc(file_mecatl_v1_harness, 169); /** * @generated from message mecatl.v1.UndoLearningPromotionRequest @@ -7690,7 +7763,7 @@ export type UndoLearningPromotionRequest = Message<"mecatl.v1.UndoLearningPromot * Use `create(UndoLearningPromotionRequestSchema)` to create a new message. */ export const UndoLearningPromotionRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 168); + messageDesc(file_mecatl_v1_harness, 170); /** * @generated from message mecatl.v1.UndoLearningPromotionResponse @@ -7707,7 +7780,7 @@ export type UndoLearningPromotionResponse = Message<"mecatl.v1.UndoLearningPromo * Use `create(UndoLearningPromotionResponseSchema)` to create a new message. */ export const UndoLearningPromotionResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 169); + messageDesc(file_mecatl_v1_harness, 171); /** * LearnedSkillVersion is a bounded inspect-only projection of an agent-owned @@ -7807,7 +7880,7 @@ export type LearnedSkillVersion = Message<"mecatl.v1.LearnedSkillVersion"> & { * Use `create(LearnedSkillVersionSchema)` to create a new message. */ export const LearnedSkillVersionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 170); + messageDesc(file_mecatl_v1_harness, 172); /** * @generated from message mecatl.v1.SkillEvaluation @@ -7849,7 +7922,7 @@ export type SkillEvaluation = Message<"mecatl.v1.SkillEvaluation"> & { * Use `create(SkillEvaluationSchema)` to create a new message. */ export const SkillEvaluationSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 171); + messageDesc(file_mecatl_v1_harness, 173); /** * @generated from message mecatl.v1.SkillChangeReceipt @@ -7946,7 +8019,7 @@ export type SkillChangeReceipt = Message<"mecatl.v1.SkillChangeReceipt"> & { * Use `create(SkillChangeReceiptSchema)` to create a new message. */ export const SkillChangeReceiptSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 172); + messageDesc(file_mecatl_v1_harness, 174); /** * @generated from message mecatl.v1.ListLearnedSkillsRequest @@ -7983,7 +8056,7 @@ export type ListLearnedSkillsRequest = Message<"mecatl.v1.ListLearnedSkillsReque * Use `create(ListLearnedSkillsRequestSchema)` to create a new message. */ export const ListLearnedSkillsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 173); + messageDesc(file_mecatl_v1_harness, 175); /** * @generated from message mecatl.v1.ListLearnedSkillsResponse @@ -8015,7 +8088,7 @@ export type ListLearnedSkillsResponse = Message<"mecatl.v1.ListLearnedSkillsResp * Use `create(ListLearnedSkillsResponseSchema)` to create a new message. */ export const ListLearnedSkillsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 174); + messageDesc(file_mecatl_v1_harness, 176); /** * @generated from message mecatl.v1.GetLearnedSkillRequest @@ -8047,7 +8120,7 @@ export type GetLearnedSkillRequest = Message<"mecatl.v1.GetLearnedSkillRequest"> * Use `create(GetLearnedSkillRequestSchema)` to create a new message. */ export const GetLearnedSkillRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 175); + messageDesc(file_mecatl_v1_harness, 177); /** * @generated from message mecatl.v1.GetLearnedSkillResponse @@ -8074,7 +8147,7 @@ export type GetLearnedSkillResponse = Message<"mecatl.v1.GetLearnedSkillResponse * Use `create(GetLearnedSkillResponseSchema)` to create a new message. */ export const GetLearnedSkillResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 176); + messageDesc(file_mecatl_v1_harness, 178); /** * @generated from message mecatl.v1.DiffLearnedSkillVersionsRequest @@ -8111,7 +8184,7 @@ export type DiffLearnedSkillVersionsRequest = Message<"mecatl.v1.DiffLearnedSkil * Use `create(DiffLearnedSkillVersionsRequestSchema)` to create a new message. */ export const DiffLearnedSkillVersionsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 177); + messageDesc(file_mecatl_v1_harness, 179); /** * @generated from message mecatl.v1.DiffLearnedSkillVersionsResponse @@ -8153,7 +8226,7 @@ export type DiffLearnedSkillVersionsResponse = Message<"mecatl.v1.DiffLearnedSki * Use `create(DiffLearnedSkillVersionsResponseSchema)` to create a new message. */ export const DiffLearnedSkillVersionsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 178); + messageDesc(file_mecatl_v1_harness, 180); /** * @generated from message mecatl.v1.MutateLearnedSkillRequest @@ -8190,7 +8263,7 @@ export type MutateLearnedSkillRequest = Message<"mecatl.v1.MutateLearnedSkillReq * Use `create(MutateLearnedSkillRequestSchema)` to create a new message. */ export const MutateLearnedSkillRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 179); + messageDesc(file_mecatl_v1_harness, 181); /** * @generated from message mecatl.v1.MutateLearnedSkillResponse @@ -8227,7 +8300,7 @@ export type MutateLearnedSkillResponse = Message<"mecatl.v1.MutateLearnedSkillRe * Use `create(MutateLearnedSkillResponseSchema)` to create a new message. */ export const MutateLearnedSkillResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 180); + messageDesc(file_mecatl_v1_harness, 182); /** * @generated from message mecatl.v1.RollbackLearnedSkillRequest @@ -8264,7 +8337,7 @@ export type RollbackLearnedSkillRequest = Message<"mecatl.v1.RollbackLearnedSkil * Use `create(RollbackLearnedSkillRequestSchema)` to create a new message. */ export const RollbackLearnedSkillRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 181); + messageDesc(file_mecatl_v1_harness, 183); /** * @generated from message mecatl.v1.ListSkillChangesRequest @@ -8291,7 +8364,7 @@ export type ListSkillChangesRequest = Message<"mecatl.v1.ListSkillChangesRequest * Use `create(ListSkillChangesRequestSchema)` to create a new message. */ export const ListSkillChangesRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 182); + messageDesc(file_mecatl_v1_harness, 184); /** * @generated from message mecatl.v1.ListSkillChangesResponse @@ -8323,7 +8396,7 @@ export type ListSkillChangesResponse = Message<"mecatl.v1.ListSkillChangesRespon * Use `create(ListSkillChangesResponseSchema)` to create a new message. */ export const ListSkillChangesResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 183); + messageDesc(file_mecatl_v1_harness, 185); /** * CreateTeamRequest creates a team owned by an existing session. @@ -8385,7 +8458,7 @@ export type CreateTeamRequest = Message<"mecatl.v1.CreateTeamRequest"> & { * Use `create(CreateTeamRequestSchema)` to create a new message. */ export const CreateTeamRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 184); + messageDesc(file_mecatl_v1_harness, 186); /** * CreateTeamResponse returns the new team's id and the enrolled initial roster. @@ -8414,7 +8487,7 @@ export type CreateTeamResponse = Message<"mecatl.v1.CreateTeamResponse"> & { * Use `create(CreateTeamResponseSchema)` to create a new message. */ export const CreateTeamResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 185); + messageDesc(file_mecatl_v1_harness, 187); /** * TeammateSpec describes a member to enrol — the per-member fields shared by @@ -8464,7 +8537,7 @@ export type TeammateSpec = Message<"mecatl.v1.TeammateSpec"> & { * Use `create(TeammateSpecSchema)` to create a new message. */ export const TeammateSpecSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 186); + messageDesc(file_mecatl_v1_harness, 188); /** * SpawnTeammateRequest enrols a member in a team before it runs. @@ -8520,7 +8593,7 @@ export type SpawnTeammateRequest = Message<"mecatl.v1.SpawnTeammateRequest"> & { * Use `create(SpawnTeammateRequestSchema)` to create a new message. */ export const SpawnTeammateRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 187); + messageDesc(file_mecatl_v1_harness, 189); /** * SpawnTeammateResponse returns the enrolled member. @@ -8541,7 +8614,7 @@ export type SpawnTeammateResponse = Message<"mecatl.v1.SpawnTeammateResponse"> & * Use `create(SpawnTeammateResponseSchema)` to create a new message. */ export const SpawnTeammateResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 188); + messageDesc(file_mecatl_v1_harness, 190); /** * SendTeammateMessageRequest posts a message into a member's inbox. @@ -8583,7 +8656,7 @@ export type SendTeammateMessageRequest = Message<"mecatl.v1.SendTeammateMessageR * Use `create(SendTeammateMessageRequestSchema)` to create a new message. */ export const SendTeammateMessageRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 189); + messageDesc(file_mecatl_v1_harness, 191); /** * SendTeammateMessageResponse is the empty acknowledgement. @@ -8598,7 +8671,7 @@ export type SendTeammateMessageResponse = Message<"mecatl.v1.SendTeammateMessage * Use `create(SendTeammateMessageResponseSchema)` to create a new message. */ export const SendTeammateMessageResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 190); + messageDesc(file_mecatl_v1_harness, 192); /** * CancelTeammateRequest cancels one member of a running team. @@ -8626,7 +8699,7 @@ export type CancelTeammateRequest = Message<"mecatl.v1.CancelTeammateRequest"> & * Use `create(CancelTeammateRequestSchema)` to create a new message. */ export const CancelTeammateRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 191); + messageDesc(file_mecatl_v1_harness, 193); /** * CancelTeammateResponse is the empty acknowledgement. @@ -8641,7 +8714,7 @@ export type CancelTeammateResponse = Message<"mecatl.v1.CancelTeammateResponse"> * Use `create(CancelTeammateResponseSchema)` to create a new message. */ export const CancelTeammateResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 192); + messageDesc(file_mecatl_v1_harness, 194); /** * RunTeamRequest drives a team to quiescence, streaming member events. @@ -8662,7 +8735,7 @@ export type RunTeamRequest = Message<"mecatl.v1.RunTeamRequest"> & { * Use `create(RunTeamRequestSchema)` to create a new message. */ export const RunTeamRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 193); + messageDesc(file_mecatl_v1_harness, 195); /** * TeamEvent is one member's session Event, tagged with the producing member — @@ -8700,7 +8773,7 @@ export type TeamEvent = Message<"mecatl.v1.TeamEvent"> & { * Use `create(TeamEventSchema)` to create a new message. */ export const TeamEventSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 194); + messageDesc(file_mecatl_v1_harness, 196); /** * TeamOutcome is the terminal result of a RunTeam drive — the wire projection of @@ -8776,7 +8849,7 @@ export type TeamOutcome = Message<"mecatl.v1.TeamOutcome"> & { * Use `create(TeamOutcomeSchema)` to create a new message. */ export const TeamOutcomeSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 195); + messageDesc(file_mecatl_v1_harness, 197); /** * ListTeamRequest names the team to snapshot. @@ -8797,7 +8870,7 @@ export type ListTeamRequest = Message<"mecatl.v1.ListTeamRequest"> & { * Use `create(ListTeamRequestSchema)` to create a new message. */ export const ListTeamRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 196); + messageDesc(file_mecatl_v1_harness, 198); /** * ListTeamResponse is the team roster, task list, and completion state. @@ -8832,7 +8905,7 @@ export type ListTeamResponse = Message<"mecatl.v1.ListTeamResponse"> & { * Use `create(ListTeamResponseSchema)` to create a new message. */ export const ListTeamResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 197); + messageDesc(file_mecatl_v1_harness, 199); /** * TeamMember mirrors a team roster entry. @@ -8874,7 +8947,7 @@ export type TeamMember = Message<"mecatl.v1.TeamMember"> & { * Use `create(TeamMemberSchema)` to create a new message. */ export const TeamMemberSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 198); + messageDesc(file_mecatl_v1_harness, 200); /** * TeamTask mirrors a shared task-list entry. @@ -8923,7 +8996,7 @@ export type TeamTask = Message<"mecatl.v1.TeamTask"> & { * Use `create(TeamTaskSchema)` to create a new message. */ export const TeamTaskSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 199); + messageDesc(file_mecatl_v1_harness, 201); /** * TeamFinding mirrors a shared findings-ledger entry, projected onto the team event @@ -8953,7 +9026,7 @@ export type TeamFinding = Message<"mecatl.v1.TeamFinding"> & { * Use `create(TeamFindingSchema)` to create a new message. */ export const TeamFindingSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 200); + messageDesc(file_mecatl_v1_harness, 202); /** * TeamMemberDisposition is one member's TERMINAL disposition (team.end). Mirrors @@ -9004,7 +9077,7 @@ export type TeamMemberDisposition = Message<"mecatl.v1.TeamMemberDisposition"> & * Use `create(TeamMemberDispositionSchema)` to create a new message. */ export const TeamMemberDispositionSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 201); + messageDesc(file_mecatl_v1_harness, 203); /** * CleanupTeamRequest names the finished team to tear down. @@ -9025,7 +9098,7 @@ export type CleanupTeamRequest = Message<"mecatl.v1.CleanupTeamRequest"> & { * Use `create(CleanupTeamRequestSchema)` to create a new message. */ export const CleanupTeamRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 202); + messageDesc(file_mecatl_v1_harness, 204); /** * CleanupTeamResponse is the empty acknowledgement. @@ -9040,7 +9113,7 @@ export type CleanupTeamResponse = Message<"mecatl.v1.CleanupTeamResponse"> & { * Use `create(CleanupTeamResponseSchema)` to create a new message. */ export const CleanupTeamResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 203); + messageDesc(file_mecatl_v1_harness, 205); /** * ApprovePlanRequest resolves a parked plan-approval ask (issue #206). See the @@ -9080,7 +9153,7 @@ export type ApprovePlanRequest = Message<"mecatl.v1.ApprovePlanRequest"> & { * Use `create(ApprovePlanRequestSchema)` to create a new message. */ export const ApprovePlanRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 204); + messageDesc(file_mecatl_v1_harness, 206); /** * ManualDreamCapabilities reports manual generation/decision availability for @@ -9105,7 +9178,7 @@ export type ManualDreamCapabilities = Message<"mecatl.v1.ManualDreamCapabilities * Use `create(ManualDreamCapabilitiesSchema)` to create a new message. */ export const ManualDreamCapabilitiesSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 205); + messageDesc(file_mecatl_v1_harness, 207); /** * @generated from message mecatl.v1.DreamTargetCapability @@ -9132,7 +9205,7 @@ export type DreamTargetCapability = Message<"mecatl.v1.DreamTargetCapability"> & * Use `create(DreamTargetCapabilitySchema)` to create a new message. */ export const DreamTargetCapabilitySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 206); + messageDesc(file_mecatl_v1_harness, 208); /** * @generated from message mecatl.v1.GenerateDreamPlanRequest @@ -9151,7 +9224,7 @@ export type GenerateDreamPlanRequest = Message<"mecatl.v1.GenerateDreamPlanReque * Use `create(GenerateDreamPlanRequestSchema)` to create a new message. */ export const GenerateDreamPlanRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 207); + messageDesc(file_mecatl_v1_harness, 209); /** * @generated from message mecatl.v1.GenerateDreamPlanResponse @@ -9168,7 +9241,7 @@ export type GenerateDreamPlanResponse = Message<"mecatl.v1.GenerateDreamPlanResp * Use `create(GenerateDreamPlanResponseSchema)` to create a new message. */ export const GenerateDreamPlanResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 208); + messageDesc(file_mecatl_v1_harness, 210); /** * @generated from message mecatl.v1.DecideDreamPlanRequest @@ -9192,7 +9265,7 @@ export type DecideDreamPlanRequest = Message<"mecatl.v1.DecideDreamPlanRequest"> * Use `create(DecideDreamPlanRequestSchema)` to create a new message. */ export const DecideDreamPlanRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 209); + messageDesc(file_mecatl_v1_harness, 211); /** * @generated from message mecatl.v1.DecideDreamPlanResponse @@ -9209,7 +9282,7 @@ export type DecideDreamPlanResponse = Message<"mecatl.v1.DecideDreamPlanResponse * Use `create(DecideDreamPlanResponseSchema)` to create a new message. */ export const DecideDreamPlanResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 210); + messageDesc(file_mecatl_v1_harness, 212); /** * @generated from message mecatl.v1.DreamReviewPlan @@ -9251,7 +9324,7 @@ export type DreamReviewPlan = Message<"mecatl.v1.DreamReviewPlan"> & { * Use `create(DreamReviewPlanSchema)` to create a new message. */ export const DreamReviewPlanSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 211); + messageDesc(file_mecatl_v1_harness, 213); /** * @generated from message mecatl.v1.DreamOperation @@ -9293,7 +9366,7 @@ export type DreamOperation = Message<"mecatl.v1.DreamOperation"> & { * Use `create(DreamOperationSchema)` to create a new message. */ export const DreamOperationSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 212); + messageDesc(file_mecatl_v1_harness, 214); /** * @generated from message mecatl.v1.DreamParticipant @@ -9320,7 +9393,7 @@ export type DreamParticipant = Message<"mecatl.v1.DreamParticipant"> & { * Use `create(DreamParticipantSchema)` to create a new message. */ export const DreamParticipantSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 213); + messageDesc(file_mecatl_v1_harness, 215); /** * @generated from message mecatl.v1.DreamReplacement @@ -9342,7 +9415,7 @@ export type DreamReplacement = Message<"mecatl.v1.DreamReplacement"> & { * Use `create(DreamReplacementSchema)` to create a new message. */ export const DreamReplacementSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 214); + messageDesc(file_mecatl_v1_harness, 216); /** * @generated from message mecatl.v1.DreamReceipt @@ -9394,7 +9467,7 @@ export type DreamReceipt = Message<"mecatl.v1.DreamReceipt"> & { * Use `create(DreamReceiptSchema)` to create a new message. */ export const DreamReceiptSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 215); + messageDesc(file_mecatl_v1_harness, 217); /** * CompactSessionRequest identifies the owned main-chat session to compact. @@ -9413,7 +9486,7 @@ export type CompactSessionRequest = Message<"mecatl.v1.CompactSessionRequest"> & * Use `create(CompactSessionRequestSchema)` to create a new message. */ export const CompactSessionRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 216); + messageDesc(file_mecatl_v1_harness, 218); /** * CompactSessionResponse reports whether the compactor reduced model history. @@ -9432,7 +9505,7 @@ export type CompactSessionResponse = Message<"mecatl.v1.CompactSessionResponse"> * Use `create(CompactSessionResponseSchema)` to create a new message. */ export const CompactSessionResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 217); + messageDesc(file_mecatl_v1_harness, 219); /** * WorkspaceEnrollmentConnectRequest starts or observes the caller-owned bundle. @@ -9451,7 +9524,7 @@ export type WorkspaceEnrollmentConnectRequest = Message<"mecatl.v1.WorkspaceEnro * Use `create(WorkspaceEnrollmentConnectRequestSchema)` to create a new message. */ export const WorkspaceEnrollmentConnectRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 218); + messageDesc(file_mecatl_v1_harness, 220); /** * WorkspaceEnrollmentControlRequest targets one exact whole-bundle correlation. @@ -9476,7 +9549,7 @@ export type WorkspaceEnrollmentControlRequest = Message<"mecatl.v1.WorkspaceEnro * Use `create(WorkspaceEnrollmentControlRequestSchema)` to create a new message. */ export const WorkspaceEnrollmentControlRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 219); + messageDesc(file_mecatl_v1_harness, 221); /** * WorkspaceEnrollment is the safe bundle-level client projection. presentation_url @@ -9511,7 +9584,7 @@ export type WorkspaceEnrollment = Message<"mecatl.v1.WorkspaceEnrollment"> & { * Use `create(WorkspaceEnrollmentSchema)` to create a new message. */ export const WorkspaceEnrollmentSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_mecatl_v1_harness, 220); + messageDesc(file_mecatl_v1_harness, 222); /** * PermissionMode is the session-wide permission posture, mirroring @@ -10102,10 +10175,8 @@ export const HarnessService: GenService<{ output: typeof GetMcpPromptResponseSchema; }, /** - * ListMcpSources returns the resolved MCP source inventory snapshot: each - * configured source (static / ToolHive), the servers it contributed, and any - * diagnostics it raised. Derived from the resolution snapshot taken at - * startup; it performs no live discovery. + * ListMcpSources returns the cached published/pre-shadow source inventory and + * reconciler status. It performs no independent upstream probe. * * @generated from rpc mecatl.v1.HarnessService.ListMcpSources */ @@ -10114,6 +10185,17 @@ export const HarnessService: GenService<{ input: typeof ListMcpSourcesRequestSchema; output: typeof ListMcpSourcesResponseSchema; }, + /** + * RefreshMcpSources explicitly reconciles direct MCP sources for an owned + * eligible ordinary-root session and unions newly active direct names. + * + * @generated from rpc mecatl.v1.HarnessService.RefreshMcpSources + */ + refreshMcpSources: { + methodKind: "unary"; + input: typeof RefreshMcpSourcesRequestSchema; + output: typeof RefreshMcpSourcesResponseSchema; + }, /** * ListSessionMcpConnectors inspects the owned session's broker-local catalogue. * This read neither probes upstreams nor progresses enrollment. diff --git a/sdk/typescript/src/namespaces-core.ts b/sdk/typescript/src/namespaces-core.ts index b1055bdaa4..c52eeb1f48 100644 --- a/sdk/typescript/src/namespaces-core.ts +++ b/sdk/typescript/src/namespaces-core.ts @@ -21,6 +21,8 @@ import type { ListWorktreesResponse, ReadMcpResourceRequest, ReadMcpResourceResponse, + RefreshMcpSourcesRequest, + RefreshMcpSourcesResponse, } from "./gen/mecatl/v1/harness_pb.js"; import type { RawClient } from "./raw.js"; import { RPC_CATALOG } from "./rpc-catalog.js"; @@ -52,6 +54,11 @@ export interface McpInventory { request: ListMcpSourcesRequest, options?: RequestOptions, ): Promise; + /** Refreshes direct MCP sources for one eligible owned session. */ + refresh( + request: RefreshMcpSourcesRequest, + options?: RequestOptions, + ): Promise; /** Lists ToolHive groups present in the resolved MCP inventory. */ listToolHiveGroups( request: ListToolHiveGroupsRequest, @@ -135,6 +142,12 @@ export function createCoreNamespaces(operations: Pick): Core request, options, ), + refresh: (request, options) => + operations.unary( + RPC_CATALOG["HarnessService.RefreshMcpSources"].grpc.descriptor, + request, + options, + ), listToolHiveGroups: (request, options) => operations.unary( RPC_CATALOG["HarnessService.ListToolHiveGroups"].grpc.descriptor, diff --git a/sdk/typescript/src/rpc-catalog.ts b/sdk/typescript/src/rpc-catalog.ts index ddb4af320d..480acf4749 100644 --- a/sdk/typescript/src/rpc-catalog.ts +++ b/sdk/typescript/src/rpc-catalog.ts @@ -550,6 +550,15 @@ const rpcCatalogRows = [ grpc: grpc(HarnessService.method.listMcpSources), http: http("GET", "/v1/mcp/sources", [], [], "none", "json"), }), + rpc({ + key: "HarnessService.RefreshMcpSources", + service: "HarnessService", + method: "RefreshMcpSources", + shape: "unary", + backingService: "RefreshMcpSources", + grpc: grpc(HarnessService.method.refreshMcpSources), + http: http("POST", "/v1/sessions/{id}/mcp-refresh", ["id=session_id"], [], "none", "json"), + }), rpc({ key: "HarnessService.ListToolHiveGroups", service: "HarnessService", diff --git a/sdk/typescript/test/namespaces-core.test.ts b/sdk/typescript/test/namespaces-core.test.ts index f73b2280ce..bdbdffb8c2 100644 --- a/sdk/typescript/test/namespaces-core.test.ts +++ b/sdk/typescript/test/namespaces-core.test.ts @@ -28,6 +28,7 @@ import { ListToolHiveGroupsRequestSchema, ListWorktreesRequestSchema, ReadMcpResourceRequestSchema, + RefreshMcpSourcesRequestSchema, } from "../src/gen/mecatl/v1/harness_pb.js"; import { connect } from "../src/index.js"; import { RPC_CATALOG } from "../src/rpc-catalog.js"; @@ -41,6 +42,7 @@ const batchACatalogKeys = [ "HarnessService.ListMcpPrompts", "HarnessService.GetMcpPrompt", "HarnessService.ListMcpSources", + "HarnessService.RefreshMcpSources", "HarnessService.ListToolHiveGroups", "HarnessService.ListAgents", "HarnessService.ListCommands", @@ -69,6 +71,7 @@ const expectedSignatures = { "listPrompts(request: ListMcpPromptsRequest, options?: RequestOptions): Promise;", "listResources(request: ListMcpResourcesRequest, options?: RequestOptions): Promise;", "listSources(request: ListMcpSourcesRequest, options?: RequestOptions): Promise;", + "refresh(request: RefreshMcpSourcesRequest, options?: RequestOptions): Promise;", "listToolHiveGroups(request: ListToolHiveGroupsRequest, options?: RequestOptions): Promise;", "readResource(request: ReadMcpResourceRequest, options?: RequestOptions): Promise;", ], @@ -199,6 +202,7 @@ describe("core typed namespaces", () => { }), ), () => client.mcp.listSources(create(ListMcpSourcesRequestSchema)), + () => client.mcp.refresh(create(RefreshMcpSourcesRequestSchema, { sessionId: "session-1" })), () => client.mcp.listToolHiveGroups(create(ListToolHiveGroupsRequestSchema)), () => client.agents.list(create(ListAgentsRequestSchema)), () => client.commands.list(create(ListCommandsRequestSchema, { sessionId: "session-1" })), @@ -213,6 +217,7 @@ describe("core typed namespaces", () => { "ListMcpPrompts", "GetMcpPrompt", "ListMcpSources", + "RefreshMcpSources", "ListToolHiveGroups", "ListAgents", "ListCommands", diff --git a/sdk/typescript/test/rpc-catalog.test.ts b/sdk/typescript/test/rpc-catalog.test.ts index e704b7f6ee..0e7c27c665 100644 --- a/sdk/typescript/test/rpc-catalog.test.ts +++ b/sdk/typescript/test/rpc-catalog.test.ts @@ -88,7 +88,7 @@ describe("RPC transport catalog", () => { } } - expect(transport.calls).toHaveLength(84); + expect(transport.calls).toHaveLength(85); expect(transport.calls.sort()).toEqual( Object.values(RPC_CATALOG) .map(({ method }) => method) @@ -101,7 +101,7 @@ describe("RPC transport catalog", () => { ...Object.values(HarnessService.method).map((method) => `HarnessService.${method.name}`), ...Object.values(ScheduleService.method).map((method) => `ScheduleService.${method.name}`), ]; - expect(descriptorKeys).toHaveLength(84); + expect(descriptorKeys).toHaveLength(85); expect(Object.keys(RPC_CATALOG).sort()).toEqual(descriptorKeys.sort()); const omitted = "HarnessService.GetSession"; diff --git a/sdk/typescript/test/session-projections.test.ts b/sdk/typescript/test/session-projections.test.ts index ef188e8c87..f02c80dd8c 100644 --- a/sdk/typescript/test/session-projections.test.ts +++ b/sdk/typescript/test/session-projections.test.ts @@ -349,6 +349,7 @@ describe("session projections", () => { "manualDream", "mcp", "mcpConnectorStatus", + "mcpRefresh", "memory", "modelSelection", "posture", diff --git a/user-docs/building/deployment/mecak8s.md b/user-docs/building/deployment/mecak8s.md index e20bbd3180..419942f90f 100644 --- a/user-docs/building/deployment/mecak8s.md +++ b/user-docs/building/deployment/mecak8s.md @@ -462,8 +462,9 @@ Pending setup shows “Setup in progress” and `x cancel setup`; prompts and a second refresh are blocked until the existing operation settles. The existing browser flow continues without a reopen-browser action. A running or awaiting session does not offer refresh. Setup is destructive and bundle-wide: starting -it withdraws broker tools, and cancellation or failure leaves them unavailable; -`/tools-connect` and `/tools-cancel` remain unchanged bare-command shortcuts. +it withdraws broker tools, and cancellation or failure leaves them unavailable. +Use `/mcp-refresh` for this broker flow. `/tools-connect` remains a deprecated +broker-only alias, and `/tools-cancel` cancels pending setup. ToolHive remains the sole custodian of upstream OAuth presentation, callback state, credentials, tokens, refresh, and any grant reuse; Mecatl exposes only diff --git a/user-docs/building/what-you-get/mcp-client.md b/user-docs/building/what-you-get/mcp-client.md index e09d1969dd..89979e69cb 100644 --- a/user-docs/building/what-you-get/mcp-client.md +++ b/user-docs/building/what-you-get/mcp-client.md @@ -79,9 +79,12 @@ for profile configuration and recovery. ### ToolHive discovery -Mecatl discovers running ToolHive MCP servers by default, so they do not need -`--mcp-server` entries. Use `--toolhive=false` to disable discovery or -`--toolhive-group ` to select a group. +Mecatl keeps one immutable direct MCP runtime and reconciles ToolHive discovery on +one bounded polling loop. A successful complete candidate publishes additions and +removals together. If source consultation or candidate construction fails, Mecatl +keeps the last usable runtime and marks the cached source status stale. Use +`--toolhive=false` to disable discovery or `--toolhive-group ` to select a +group. ## Tool namespacing @@ -115,9 +118,9 @@ Mecatl does not automatically replay a server-declared failure, including structured JSON-RPC 400/404 responses and HTTP 429/502/503/504 responses. This avoids running a mutating operation twice when its first response is ambiguous. -The startup catalog remains stable across a reconnect. Restart Mecatl to adopt a -changed tool list. Operator logs report when a reconnect starts, succeeds, or -fails. +A reconnect keeps the operation's pinned runtime revision. Source reconciliation +publishes a complete replacement only after all desired servers connect and list +their tools, resources, and prompts successfully. ## Resources and prompts @@ -169,14 +172,31 @@ connection. ## Server-initiated notifications -When a server sends `tools/list_changed`, `prompts/list_changed`, or -`resources/list_changed`, Mecatl marks that list as stale. It refreshes the list -the next time a session reads it instead of making a network call in the -notification handler. - -New sessions receive the refreshed catalog. An in-flight session keeps its -existing catalog, so calling a tool that the server removed returns an error -rather than changing the session's tools while it runs. +When a current server sends `tools/list_changed`, `prompts/list_changed`, or +`resources/list_changed`, Mecatl reconciles all three contract lists through the +same bounded path as ToolHive polling. Notifications from a retired runtime do +not affect the current publication. + +A run or direct team operation keeps the runtime revision it started with. The +next operation pins the current publication, so it sees a successful addition or +removal without mixing old schemas with new dispatch targets. + +## Refresh MCP tools for a session + +Automatic reconciliation updates availability but does not grant newly added +names to an existing session. Run `/mcp-refresh` in `mecatui`, call +`RefreshMcpSources`, or send a bodyless `POST` to +`/v1/sessions//mcp-refresh` while the owned root session is idle or +completed. The operation adds currently active direct MCP names to that session's +existing name authority. It preserves completed state and does not reopen the +conversation. + +A name that disappears is unavailable but remains in the session's durable name +authority. If the exact name returns, the existing grant applies again. A refresh +response reports the runtime revision considered by that request and whether its +reconciliation cycle or authority union changed anything. Inspect +`ListMcpSources` for the cached revision, stale, and reconciliation status; the +status call does not probe upstream servers. ## Authentication and credentials diff --git a/user-docs/mecatui/commands-and-memory.md b/user-docs/mecatui/commands-and-memory.md index 2faa160a37..7539eadb50 100644 --- a/user-docs/mecatui/commands-and-memory.md +++ b/user-docs/mecatui/commands-and-memory.md @@ -15,11 +15,18 @@ embedded session and a remote server can expose different commands. ## Workspace service enrollment -When the server provides protected workspace services, run `/tools-connect` to -start or recheck the connection. Run `/tools-cancel` to cancel a pending -connection. You can continue editing the prompt while browser consent is -pending. If the server requires the connection before accepting a prompt, -`mecatui` sends the retained prompt after the connection succeeds. +When the server provides protected workspace services, run `/mcp-refresh` to +start or recheck the connection. This broker path keeps the existing destructive +reconnection disclosure and browser consent flow. `/tools-connect` is a +deprecated broker-only alias. Run `/tools-cancel` to cancel a pending connection. +You can continue editing the prompt while browser consent is pending. If the +server requires the connection before accepting a prompt, `mecatui` sends the +retained prompt after the connection succeeds. + +On a direct MCP server, `/mcp-refresh` performs the direct refresh without a +browser consent flow. `mecatui` enables exactly one path from server +capabilities. It refuses the command when both modes, neither mode, or the +matching client collaborator are unavailable. ## Completed-session learning diff --git a/user-docs/mecatui/using-the-tui.md b/user-docs/mecatui/using-the-tui.md index 0b15b4b711..0f5054b91d 100644 --- a/user-docs/mecatui/using-the-tui.md +++ b/user-docs/mecatui/using-the-tui.md @@ -121,6 +121,7 @@ commands supported by the connected server. |Task|Open in `mecatui`|More information| |-|-|-| |Browse MCP servers, resources, and prompts|`/mcp`; press `f8` to open MCP prompts directly|[MCP client](/building/what-you-get/mcp-client.md)| +|Refresh direct MCP tools or broker workspace services|`/mcp-refresh`|[Use learning and memory commands](./commands-and-memory.md#workspace-service-enrollment)| |Inspect named agent definitions|`/agents`|[Named agents](/features/named-agents.md)| |Inspect available skills and the active soul|`/skills` and `/soul`|[Skills, commands, and soul](/features/skills-commands-and-soul.md)| |Inspect the user model|`/usermodel`|[Memory](/building/what-you-get/memory.md)| diff --git a/user-docs/reference/grpc-api.md b/user-docs/reference/grpc-api.md index ea7e00eb26..a462a06a09 100644 --- a/user-docs/reference/grpc-api.md +++ b/user-docs/reference/grpc-api.md @@ -221,7 +221,8 @@ should hide the action. Calling an old server's unknown method returns |`UndoLearningPromotion`|unary|CAS compensating revision only while the linked promoted memory revision remains current; stale/newer revisions return `ABORTED`| |`ListMcpResources` / `ReadMcpResource`|unary|static MCP resource snapshots; read one resource by URI| |`ListMcpPrompts` / `GetMcpPrompt`|unary|MCP prompt snapshots; expand one prompt to its rendered messages| -|`ListMcpSources`|unary|the resolved MCP source inventory (static / ToolHive) + diagnostics| +|`ListMcpSources`|unary|cached published/pre-shadow MCP sources plus revision, stale, and reconciling status; performs no probe| +|`RefreshMcpSources`|unary|reconcile direct MCP for an eligible owned root and return the request-pinned revision plus request-local changed result| |`ListToolHiveGroups`|unary|the distinct ToolHive groups in the resolved inventory (no live ToolHive call)| **Manual dream review.** Read `CreateSessionResponse.capabilities.manual_dream` diff --git a/user-docs/reference/http-sse-api.md b/user-docs/reference/http-sse-api.md index a78844f9e9..8461c831e3 100644 --- a/user-docs/reference/http-sse-api.md +++ b/user-docs/reference/http-sse-api.md @@ -164,7 +164,8 @@ and trusted driver storage retain the exact private |`GET /v1/mcp/resources/read`|read one MCP resource by URI| |`GET /v1/mcp/prompts`|the MCP prompt inventory| |`POST /v1/mcp/prompts/get`|expand one MCP prompt (rendered messages)| -|`GET /v1/mcp/sources`|the resolved MCP source inventory| +|`GET /v1/mcp/sources`|cached published/pre-shadow MCP sources plus revision, stale, and reconciling status| +|`POST /v1/sessions/{id}/mcp-refresh`|bodyless direct MCP refresh for an eligible owned root; returns request-pinned revision and changed| |`GET /v1/mcp/toolhive/groups`|the ToolHive groups in the resolved inventory| Manual dream generation sends the selected bounded memory values/descriptions to diff --git a/user-docs/reference/typescript-sdk-api/core.md b/user-docs/reference/typescript-sdk-api/core.md index b75dea2483..d42ec24ff4 100644 --- a/user-docs/reference/typescript-sdk-api/core.md +++ b/user-docs/reference/typescript-sdk-api/core.md @@ -2497,7 +2497,7 @@ MCP resource, prompt, source, and ToolHive-group inventory operations. export interface McpInventory ``` -Callable members: [`getPrompt()`](#api-mcpinventory-getprompt-methodsignature), [`listPrompts()`](#api-mcpinventory-listprompts-methodsignature), [`listResources()`](#api-mcpinventory-listresources-methodsignature), [`listSources()`](#api-mcpinventory-listsources-methodsignature), [`listToolHiveGroups()`](#api-mcpinventory-listtoolhivegroups-methodsignature), [`readResource()`](#api-mcpinventory-readresource-methodsignature) +Callable members: [`getPrompt()`](#api-mcpinventory-getprompt-methodsignature), [`listPrompts()`](#api-mcpinventory-listprompts-methodsignature), [`listResources()`](#api-mcpinventory-listresources-methodsignature), [`listSources()`](#api-mcpinventory-listsources-methodsignature), [`listToolHiveGroups()`](#api-mcpinventory-listtoolhivegroups-methodsignature), [`readResource()`](#api-mcpinventory-readresource-methodsignature), [`refresh()`](#api-mcpinventory-refresh-methodsignature) McpInventory.getPrompt @@ -2589,6 +2589,21 @@ Parameters: Returns: `Promise` +McpInventory.refresh + +Refreshes direct MCP sources for one eligible owned session. + +```ts +refresh(request: RefreshMcpSourcesRequest, options?: RequestOptions): Promise; +``` + +Parameters: + +- `request` (`RefreshMcpSourcesRequest`) +- `options` (`RequestOptions`, optional) + +Returns: `Promise` + MecatlErrorOptions Metadata attached to one MecatlError. From 72c10b25e026f418d91c899a370971353e958fc3 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 00:26:06 +0200 Subject: [PATCH 06/14] fix(mcp): preserve immutable runtime operations Co-Authored-By: mecatl --- docs/adr/0027-cloud-native.md | 2 +- docs/design/IMPLEMENTATION-NOTES.md | 20 +- internal/adapter/mcp/candidate_budget_test.go | 44 ++- internal/adapter/mcp/mcp.go | 34 +- internal/adapter/mcp/notifications_test.go | 41 ++ internal/adapter/mcp/source/toolhive.go | 12 +- internal/adapter/mcp/source/toolhive_test.go | 14 + internal/adapter/server/close_test.go | 63 +++ .../adapter/server/manual_compaction_test.go | 36 ++ internal/adapter/server/service.go | 36 +- .../server/session_mutation_inventory.go | 2 +- internal/adapter/server/team.go | 364 ++++++++---------- internal/app/mcp_reconciler.go | 54 +-- internal/app/mcp_reconciler_test.go | 47 ++- internal/app/mcp_runtime_publication_test.go | 16 +- 15 files changed, 494 insertions(+), 291 deletions(-) diff --git a/docs/adr/0027-cloud-native.md b/docs/adr/0027-cloud-native.md index 7e1144dd46..0dd7c332f6 100644 --- a/docs/adr/0027-cloud-native.md +++ b/docs/adr/0027-cloud-native.md @@ -807,7 +807,7 @@ durable artifact survives and is reloaded), or **lost** (gone, possibly leaking) | 61 | Provider OIDC issuer and gateway HTTP clients | `internal/cliconfig.NativeEndpointRuntime` | process, one pair per provider runtime | clients have no independent goroutine; their transports die with the runtime/loader | reconstructible from explicit issuer/gateway trust policies and CA bundles; neither trust root is reused for the other | `internal/cliconfig/native_endpoint.go` (`OpenNativeEndpointRuntime`, `nativeTrustClient`) | | 62 | Provider OIDC keyring and encrypted Store handles | `internal/cliconfig.NativeEndpointRuntime` | operation handles; serving Store handles live for the runtime | Login/status/logout defer Store close; `Source` handles close at runtime/loader close | reopened only from explicit `credential_store.oidc.home` and provider identity; no discovery, migration, plaintext, or environment fallback | `internal/cliconfig/native_endpoint.go` (`open`, `Login`, `Status`, `Logout`, `Close`); `internal/adapter/llmendpoint/lifecycle.go` (`NewProtectedStore`) | | 63 | Provider OIDC transaction-lock handles | `llmendpoint.TransactionLocker` | one provider lifecycle operation | `With` releases its owner-only flock after the callback; no lock is retained across gateway requests | reset/reacquired after restart from the hashed provider identity; the durable record remains the source of truth | `internal/adapter/llmendpoint/lifecycle.go` (`TransactionLocker`, `With`) | -| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, immutable current and bounded retiring runtimes, one deferred-successor bit, revision-tagged engine caches, and run/operation pins | `app.Build` through `connectMCP`; `server.Service` owns root-run and direct-Team pin lifetime | process publication state plus one pin per active root run or resource/prompt operation; a direct Team retains its creation pin until `RunTeam`, explicit cleanup, or Service shutdown because member engines are built during creation | the Build close fold first drains `Service`, including created-but-not-run Teams, then invokes `mcpSourceReconciler.Close` and `mcpRuntimeSet.close`; publication never mutates a live manager, a displaced runtime closes only after its pins drain, and a full retirement set discards the candidate without force-close and schedules one retry after drain. Cached-engine close never closes a direct manager. Caller cancellation only stops that caller's reconciliation wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects one complete runtime, and begins with no source LKG, retired runtime, pin, cache revision, or pending invalidation; direct Teams are process-local and are not restored, so their retained pins disappear with them; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `mcpReconcileCandidate`, `Close`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`, `pin`, `publish`, `release`); `internal/adapter/server/service.go` (`beginRunAdmission`, `engineAndEnvironmentFor`, `SessionEngineResult.RuntimeRevision`); `internal/adapter/server/team.go` (`createTeamInEnvironment`, `RunTeam`, `CleanupTeam`); `internal/app/build.go` (`connectMCP`) | +| 64 | Direct MCP source reconciler worker, bounded jitter timer, coalescing channel/waiters, per-source LKG/status, immutable current and bounded retiring runtimes, one deferred-successor bit, revision-tagged engine caches, and run/operation pins | `app.Build` through `connectMCP`; `server.Service` owns root-run and direct-Team pin lifetime | process publication state plus one pin per active root run, direct `RunTeam`, or resource/prompt operation; a created-but-unrun direct Team stores declarations only and retains no runtime pin | the Build close fold first cancels Service operations without detaching their pins, then `mcpRuntimeSet.close` waits for actual `removeRunState`/`RunTeam`/operation settlement before closing managers. Publication never mutates a live manager, a displaced runtime closes only after its pins drain, and a full retirement set discards the candidate without force-close and schedules one retry after drain. Direct `RunTeam` acquires current once and builds its supervisor, member engines, referenced specialists, and root authority from that operation context. Cached-engine close never closes a direct manager. Caller cancellation only stops that caller's reconciliation wait | reset-by-design and reconstructible: restart re-resolves static configuration and ToolHive, reconnects one complete runtime, and begins with no source LKG, retired runtime, pin, cache revision, or pending invalidation; direct Teams are process-local and are not restored; no runtime metadata is durable | `internal/app/mcp_reconciler.go` (`mcpSourceReconciler`, `mcpReconcileCandidate`, `Close`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`, `pin`, `publish`, `release`); `internal/adapter/server/service.go` (`beginRunAdmission`, `removeRunState`, `engineAndEnvironmentFor`, `SessionEngineResult.RuntimeRevision`); `internal/adapter/server/team.go` (`createTeamInEnvironment`, `buildTeamForOperation`, `RunTeam`, `CleanupTeam`); `internal/app/build.go` (`connectMCP`) | | 1 | Direct global MCP managers (one per immutable current/retiring runtime) | `app.Build` / `mcpRuntimeSet` | process, bounded current plus retired set | a candidate owns its manager from complete construction; unchanged/failed/unpublishable candidates close immediately, retired managers close after operation pins drain, and joined Build close closes the remainder. They are NEVER folded into per-session engine close | reconstructible (reconnects a complete desired set from ordered sources at next Build) | `internal/app/mcp_reconciler.go` (`mcpReconcileCandidate`); `internal/app/mcp_runtime.go` (`mcpRuntimeSet`); `internal/app/build.go` (`connectMCP`) | | 2 | Per-session client MCP managers and their original `Service.clientMCPSpecs` mount declarations | `sessionEngineFactory` / `Service` | session / process-local map | per-session close func, invoked by `Service.CloseSession` (`service.go:743`) and shutdown. **Two callers now reach this** (issue #821, Scenario 9): the ACP adapter, which calls `CloseSession` on editor disconnect, and the gRPC/HTTP `CreateSession` wire path, whose teardown is the precondition-checked `EndSession` (same teardown) or `Service.Close`. `CloseSession`, failed-create rollback, and `Service.Close` remove the corresponding `clientMCPSpecs` entry; an engine-rebuild failure deliberately retains it because the surviving session can retry/remount the same client tools. The wire caller is a client that may simply go away without ending its session, so a mounted manager can outlive its last use until process shutdown — bounded by `MaxSessionEngines` (which fails a create at the cap rather than growing without limit), not by a reaper. That residual is the same one every per-session engine has, and it is why the field is deployment-gated to a UNIX-socket-only daemon rather than exposed to an anonymous network caller. A create REFUSED for an unreachable server does not add to it: `verifyClientMCPMounted` runs before any id is minted and invokes the same `closeFn` every other rejection in `createPerSessionEngine` does, so the partially-connected manager is torn down on that path rather than left registered against a session that does not exist | **reset/remount by design:** client specs, including secret-shaped headers, are never persisted. A restart drops `clientMCPSpecs` and every client manager; the client explicitly re-mounts via `LoadSessionWithMCP`, `service.go:968`, or creates a new session with `mcp_servers`. Within one Service lifetime, a rebuild reuses the retained original declaration. | `internal/app/build.go:962`; `internal/adapter/server/service.go` (`clientMCPSpecs`, `ClientMCPFromWire`, `WithClientMCP`) | | 3 | Preserved-fork LRU (`LRUForkReaper`) — Parallel ONLY | `app.Build` (shared via `catalogAssets`, built only when Parallel is enabled) | process | LRU eviction runs each entry's cleanup (dir removal) outside the lock; graceful app shutdown calls `Built.Close`, which drains retained entries and eviction cleanups already detached before closure outside the lock | registry lost; the preserved fork DIRS remain on disk un-tracked (a leak on crash) | `engine/agent/forkreaper.go:41,64`; built at `internal/app/build.go:4895`. NOTE: the writable Subagent (`mode:"read-write"`) no longer creates a per-call fork dir — it writes the parent workspace directly (ADR 0077), so it contributes no fork dirs here; the shared `autoMerger` (`forker.SerializingMerger`) is likewise Parallel-only now | diff --git a/docs/design/IMPLEMENTATION-NOTES.md b/docs/design/IMPLEMENTATION-NOTES.md index c2944b3046..72d7155dbb 100644 --- a/docs/design/IMPLEMENTATION-NOTES.md +++ b/docs/design/IMPLEMENTATION-NOTES.md @@ -5996,18 +5996,26 @@ failed source's last-known-good snapshot, and treats a successful empty snapshot as withdrawal. Stable, non-dirty observations stop before candidate connection. A dirty current-runtime notification rebuilds a complete candidate and therefore re-lists tools, resources, and prompts together; callbacks from displaced -candidate generations are ignored. `internal/adapter/mcp/mcp.go` +candidate generations are ignored, while a callback received during candidate +construction queues exactly one successor after publication. Reconciler-owned +servers keep their validated tool/resource/prompt projections frozen: notifications +only invalidate the reconciler, so old and failed candidates cannot lazily mutate a +published schema. `internal/adapter/mcp/mcp.go` (`NewCompleteManager`) connects and lists all desired servers all-or-nothing, using one candidate-wide page/byte/cardinality budget and no OAuth presenter. -Candidate equality covers source/server configuration and bounded tool, +Concurrent response reads reserve aggregate bytes before touching a body. ToolHive's +current API still allocates its returned workload slice internally; mecatl rejects a +raw over-limit slice immediately before group filtering or derived result/diagnostic +allocation. Candidate equality covers source/server configuration and bounded tool, resource, and prompt metadata. `internal/app/mcp_runtime.go` (`mcpRuntimeSet`) atomically publishes the complete candidate as one manager/provider/catalog contribution. Root runs pin it in `server.Service.beginRunAdmission`; the pin context reaches prompt expansion and every Subagent/Parallel/Team/named/reference -factory built by the one `assembleCatalog` path. Direct `RunTeam` members are -built during team creation, so that path retains its creation pin until the run, -explicit cleanup, or Service shutdown and derives its member factory from the -same pinned manager. Out-of-run resource and prompt provider calls take one +factory built by the one `assembleCatalog` path. Direct `RunTeam` stores only +member declarations at creation; at the actual run boundary it acquires one current +operation pin, then builds the supervisor, every member engine, referenced specialist, +and root authority from that same context. An unrun Team therefore never fills the +retirement set. Out-of-run resource and prompt provider calls take one call-scoped pin. Shared and cached default, selector, no-FS, client-MCP, mode, specialist, and debug engines carry only a revision tag; `server.Service.engineAndEnvironmentFor` rebuilds a mismatch before use, so idle engine caches never lease a manager and their close functions never own one. diff --git a/internal/adapter/mcp/candidate_budget_test.go b/internal/adapter/mcp/candidate_budget_test.go index 654e6244bb..0706525157 100644 --- a/internal/adapter/mcp/candidate_budget_test.go +++ b/internal/adapter/mcp/candidate_budget_test.go @@ -2,7 +2,10 @@ package mcp import ( "strings" + "sync" + "sync/atomic" "testing" + "time" ) func TestCandidateListBudgetBoundsInputBeforePublication(t *testing.T) { @@ -19,12 +22,16 @@ func TestCandidateListBudgetBoundsInputBeforePublication(t *testing.T) { buf := make([]byte, 8) n, err := budget.readResponse(strings.NewReader("12345"), buf) + if err != nil || n != 4 { + t.Fatalf("byte boundary read = (%d, %v), want (4, nil)", n, err) + } + n, err = budget.readResponse(strings.NewReader("5"), buf) if err == nil || n != 0 || !strings.Contains(err.Error(), "bytes exceed") { t.Fatalf("byte over-bound read = (%d, %v)", n, err) } _, pages, bytes := budget.Stats() - if pages != 2 || bytes != 0 { - t.Fatalf("failed input changed counters: pages=%d bytes=%d", pages, bytes) + if pages != 2 || bytes != 4 { + t.Fatalf("input counters: pages=%d bytes=%d", pages, bytes) } budget.Seal() @@ -36,3 +43,36 @@ func TestCandidateListBudgetBoundsInputBeforePublication(t *testing.T) { t.Fatalf("sealed runtime read bytes = %d, want 5", n) } } + +type slowCountingReader struct { + reads *atomic.Int64 +} + +func (r slowCountingReader) Read(p []byte) (int, error) { + time.Sleep(10 * time.Millisecond) + r.reads.Add(1) + p[0] = 'x' + return 1, nil +} + +func TestCandidateListBudgetChargesConcurrentBodiesBeforeAllocation(t *testing.T) { + const limit = 4 + budget := NewCandidateListBudget(1, 1, limit) + var reads atomic.Int64 + var wg sync.WaitGroup + for range 16 { + wg.Add(1) + go func() { + defer wg.Done() + _, _ = budget.readResponse(slowCountingReader{reads: &reads}, make([]byte, 1)) + }() + } + wg.Wait() + if got := reads.Load(); got != limit { + t.Fatalf("underlying concurrent body reads = %d, want aggregate limit %d", got, limit) + } + _, _, gotBytes := budget.Stats() + if gotBytes != limit { + t.Fatalf("charged bytes = %d, want %d", gotBytes, limit) + } +} diff --git a/internal/adapter/mcp/mcp.go b/internal/adapter/mcp/mcp.go index 846c7281bf..5c6448efae 100644 --- a/internal/adapter/mcp/mcp.go +++ b/internal/adapter/mcp/mcp.go @@ -108,23 +108,23 @@ func (b *CandidateListBudget) readResponse(body io.Reader, p []byte) (int, error return body.Read(p) } remaining := b.maxBytes - b.bytes - b.mu.Unlock() if remaining <= 0 { + b.mu.Unlock() return 0, fmt.Errorf("mcp: candidate response bytes exceed limit %d", b.maxBytes) } - if len(p) > remaining+1 { - p = p[:remaining+1] + reserved := len(p) + if reserved > remaining { + reserved = remaining } - n, err := body.Read(p) + b.bytes += reserved + b.mu.Unlock() + + n, err := body.Read(p[:reserved]) b.mu.Lock() - defer b.mu.Unlock() - if b.sealed { - return n, err - } - if b.bytes+n > b.maxBytes { - return 0, fmt.Errorf("mcp: candidate response bytes exceed limit %d", b.maxBytes) + if !b.sealed && n < reserved { + b.bytes -= reserved - n } - b.bytes += n + b.mu.Unlock() return n, err } @@ -643,7 +643,7 @@ type candidateBudgetRoundTripper struct { func (t candidateBudgetRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { res, err := t.base.RoundTrip(req) - if err != nil || res == nil || res.Body == nil { + if err != nil || res == nil || res.Body == nil || req.Method == http.MethodGet { return res, err } res.Body = &candidateBudgetBody{ReadCloser: res.Body, budget: t.budget} @@ -1010,11 +1010,13 @@ func (s *Server) Name() string { return s.name } // notifications/tools/list_changed has fired since the last read (ADR 0057), the // snapshot is lazily re-listed under a bounded context.Background() before // returning, so a post-notification caller sees the server's current tool set. -// The re-list runs WITHOUT s.mu held (it may reconnect, which re-acquires +// Reconciliation candidates are the exception: CandidateBudget marks a validated +// immutable projection, so notifications only invoke ListChanged and the published +// snapshot never mutates. The re-list runs WITHOUT s.mu held (it may reconnect, which re-acquires // s.mu); only the dirty-check and the final swap hold the lock. func (s *Server) Tools() []tool.Tool { s.mu.Lock() - dirty := s.toolsDirty + dirty := s.toolsDirty && s.cfg.CandidateBudget == nil tools := s.tools s.mu.Unlock() if dirty { @@ -1031,7 +1033,7 @@ func (s *Server) Tools() []tool.Tool { // discipline. func (s *Server) Resources() []Resource { s.mu.Lock() - dirty := s.resourcesDirty + dirty := s.resourcesDirty && s.cfg.CandidateBudget == nil res := s.resources s.mu.Unlock() if dirty { @@ -1048,7 +1050,7 @@ func (s *Server) Resources() []Resource { // discipline. func (s *Server) Prompts() []Prompt { s.mu.Lock() - dirty := s.promptsDirty + dirty := s.promptsDirty && s.cfg.CandidateBudget == nil pr := s.prompts s.mu.Unlock() if dirty { diff --git a/internal/adapter/mcp/notifications_test.go b/internal/adapter/mcp/notifications_test.go index a32befe04b..25881f7474 100644 --- a/internal/adapter/mcp/notifications_test.go +++ b/internal/adapter/mcp/notifications_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "sync/atomic" "testing" "time" @@ -49,6 +50,46 @@ func eventually(t *testing.T, timeout time.Duration, cond func() bool, msg strin t.Fatalf("eventually: %s (timed out after %v)", msg, timeout) } +func TestReconciliationCandidateListProjectionStaysFrozenAfterNotification(t *testing.T) { + url, remote := newMutableTestServer(t) + var invalidations atomic.Int64 + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + s, err := ConnectComplete(ctx, ServerConfig{ + Name: "fake", URL: url, + CandidateBudget: NewCandidateListBudget(32, 32, 1<<20), + ListChanged: func() { invalidations.Add(1) }, + }, &recordingDiag{}) + if err != nil { + t.Fatalf("ConnectComplete: %v", err) + } + t.Cleanup(func() { _ = s.Close() }) + wantTools, wantResources, wantPrompts := len(s.Tools()), len(s.Resources()), len(s.Prompts()) + + mcpsdk.AddTool(remote, &mcpsdk.Tool{Name: "late", Description: "late"}, + func(context.Context, *mcpsdk.CallToolRequest, noArgs) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{}, nil, nil + }) + remote.AddResource(&mcpsdk.Resource{URI: "test://late", Name: "late"}, + func(_ context.Context, req *mcpsdk.ReadResourceRequest) (*mcpsdk.ReadResourceResult, error) { + return &mcpsdk.ReadResourceResult{Contents: []*mcpsdk.ResourceContents{{URI: req.Params.URI, Text: "late"}}}, nil + }) + remote.AddPrompt(&mcpsdk.Prompt{Name: "late"}, + func(context.Context, *mcpsdk.GetPromptRequest) (*mcpsdk.GetPromptResult, error) { + return &mcpsdk.GetPromptResult{}, nil + }) + eventually(t, 3*time.Second, func() bool { return invalidations.Load() >= 3 }, "candidate notifications did not invalidate reconciler") + if got := len(s.Tools()); got != wantTools { + t.Fatalf("candidate Tools mutated from %d to %d", wantTools, got) + } + if got := len(s.Resources()); got != wantResources { + t.Fatalf("candidate Resources mutated from %d to %d", wantResources, got) + } + if got := len(s.Prompts()); got != wantPrompts { + t.Fatalf("candidate Prompts mutated from %d to %d", wantPrompts, got) + } +} + // TestToolListChangedNotificationRefreshesSnapshot is the Phase-1 acceptance // test (ADR 0057): with the standalone SSE stream enabled, adding a tool // server-side fires notifications/tools/list_changed, the handler sets the diff --git a/internal/adapter/mcp/source/toolhive.go b/internal/adapter/mcp/source/toolhive.go index dc28213ea6..84ea02c77b 100644 --- a/internal/adapter/mcp/source/toolhive.go +++ b/internal/adapter/mcp/source/toolhive.go @@ -33,7 +33,14 @@ import ( // effectiveDefaultGroup is the group name used when the operator did not name one // (mirroring ToolHive's own notion of a "default" group). Empty group -> "default". -const effectiveDefaultGroup = "default" +const ( + effectiveDefaultGroup = "default" + // ToolHive's current listing API materializes the returned slice before the + // caller can filter it. Reject it immediately, before group filtering or any + // derived server/diagnostic allocation; the dependency-owned slice allocation + // is the unavoidable residual until ToolHive exposes a bounded listing API. + maxToolHiveWorkloads = 128 +) // workloadLister is the minimal slice of the ToolHive library mecatl needs: list // the running workloads. Defining our own interface (rather than depending on @@ -119,6 +126,9 @@ func (s ToolHiveSource) Servers(ctx context.Context) ([]mcp.ServerConfig, []Skip if err != nil { return nil, nil, fmt.Errorf("listing ToolHive workloads: %w", err) } + if len(list) > maxToolHiveWorkloads { + return nil, nil, fmt.Errorf("ToolHive workload count exceeds limit %d", maxToolHiveWorkloads) + } // FilterByGroup is a pure in-memory filter over the already-listed workloads: // no extra manager construction and no runtime round-trip. (It is not a diff --git a/internal/adapter/mcp/source/toolhive_test.go b/internal/adapter/mcp/source/toolhive_test.go index f737d99ea1..a5d8618366 100644 --- a/internal/adapter/mcp/source/toolhive_test.go +++ b/internal/adapter/mcp/source/toolhive_test.go @@ -59,6 +59,20 @@ func running(name, url string, tt types.TransportType, proxyMode types.ProxyMode } } +func TestToolHiveRejectsRawWorkloadListBeforeFiltering(t *testing.T) { + f := &fakeLister{workloads: make([]core.Workload, maxToolHiveWorkloads+1)} + got, skips, err := sourceWith("default", f, nil).Servers(context.Background()) + if err == nil || !strings.Contains(err.Error(), "workload count exceeds limit") { + t.Fatalf("Servers = (%v, %v, %v), want bounded source error", got, skips, err) + } + if got != nil || skips != nil { + t.Fatalf("over-limit source materialized derived output: servers=%v skips=%v", got, skips) + } + if f.calls != 1 { + t.Fatalf("ListWorkloads calls = %d, want 1", f.calls) + } +} + func TestToolHiveMapsRunningStreamable(t *testing.T) { f := &fakeLister{workloads: []core.Workload{ running("github", "http://127.0.0.1:8080/mcp", types.TransportTypeStreamableHTTP, types.ProxyModeStreamableHTTP, "default"), diff --git a/internal/adapter/server/close_test.go b/internal/adapter/server/close_test.go index 479d19ea0b..1c9f78f0fb 100644 --- a/internal/adapter/server/close_test.go +++ b/internal/adapter/server/close_test.go @@ -2,6 +2,8 @@ package server_test import ( "context" + "iter" + "sync/atomic" "testing" "time" @@ -9,6 +11,7 @@ import ( "github.com/stacklok/mecatl/engine/adapter/permpolicy" "github.com/stacklok/mecatl/engine/adapter/permstore" "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/engine/tool" "github.com/stacklok/mecatl/internal/adapter/mcp" @@ -17,6 +20,66 @@ import ( // blockingProvider is defined in lease_test.go (same package). +type settlementBlockingProvider struct { + entered chan struct{} + release chan struct{} +} + +func (p settlementBlockingProvider) Stream(context.Context, port.LLMRequest) (iter.Seq2[port.Chunk, error], error) { + return func(yield func(port.Chunk, error) bool) { + close(p.entered) + <-p.release + yield(port.Chunk{Kind: port.ChunkDone, Stop: session.StopEndTurn}, nil) + }, nil +} + +func (settlementBlockingProvider) Capabilities() port.ProviderCapabilities { + return port.ProviderCapabilities{} +} + +func TestCloseRetainsOperationPinUntilRunActuallySettles(t *testing.T) { + provider := settlementBlockingProvider{entered: make(chan struct{}), release: make(chan struct{})} + var released atomic.Bool + svc, err := newPlacementTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{ + LLM: provider, Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(nil, permstore.New()), Model: "test-model", + }), + Store: memstore.New(), + OperationPin: func(ctx context.Context) (context.Context, func(), error) { + return ctx, func() { released.Store(true) }, nil + }, + }) + if err != nil { + t.Fatal(err) + } + sess, err := svc.CreateSession(context.Background(), session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatal(err) + } + run, err := svc.StartRun(context.Background(), sess.ID, "go") + if err != nil { + t.Fatal(err) + } + <-provider.entered + closed := make(chan struct{}) + go func() { svc.Close(); close(closed) }() + select { + case <-closed: + case <-time.After(time.Second): + t.Fatal("Service.Close did not finish cancellation") + } + if released.Load() { + t.Fatal("Service.Close released the operation pin while provider work was still blocked") + } + close(provider.release) + for range run.Events() { + } + svc.FinishRun(sess.ID, run) + if !released.Load() { + t.Fatal("operation pin was not released after settlement") + } +} + // TestCloseCancelsInFlightRun proves that Service.Close() cancels a run that is // blocked in an LLM call. A blockingProvider streams nothing until ctx is // cancelled; Close calls shutdownCancelFn + run.Cancel(), so the run unblocks diff --git a/internal/adapter/server/manual_compaction_test.go b/internal/adapter/server/manual_compaction_test.go index 7b34647448..01a16efdaa 100644 --- a/internal/adapter/server/manual_compaction_test.go +++ b/internal/adapter/server/manual_compaction_test.go @@ -41,6 +41,17 @@ func (c serviceCompactCompactor) Compact(context.Context, *session.Conversation) return c.out, c.summary, nil } +type compactOperationKey struct{} + +type pinAwareCompactor struct { + seen *bool +} + +func (c pinAwareCompactor) Compact(ctx context.Context, _ *session.Conversation) ([]session.Message, string, error) { + *c.seen, _ = ctx.Value(compactOperationKey{}).(bool) + return []session.Message{session.NewUserMessage("short")}, "pinned", nil +} + type serviceCompactCounter struct{} func (serviceCompactCounter) Count(s string) int { return len(s) } @@ -163,6 +174,31 @@ func compactFixture(t *testing.T, state session.State) (*compactTrackingStore, * return store, sess, owner } +func TestCompactSessionPinsRuntimeThroughCompactor(t *testing.T) { + store, sess, owner := compactFixture(t, session.StateIdle) + seen, released := false, false + eng := agent.NewEngine(agent.Deps{ + LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(nil, nil), Model: "test", + Compactor: pinAwareCompactor{seen: &seen}, TokenCounter: serviceCompactCounter{}, + }) + svc, err := newPlacementTestService(server.Config{ + Engine: eng, Store: store, EventLog: store, Now: time.Now, OwnershipEnforced: true, + OperationPin: func(ctx context.Context) (context.Context, func(), error) { + return context.WithValue(ctx, compactOperationKey{}, true), func() { released = true }, nil + }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(svc.Close) + if _, err := svc.CompactSession(session.WithPrincipal(context.Background(), owner), sess.ID, owner); err != nil { + t.Fatal(err) + } + if !seen || !released { + t.Fatalf("compaction operation pin: seen=%v released=%v", seen, released) + } +} + func TestCompactSessionPersistsBeforeOrderedAttributedEvents(t *testing.T) { store, sess, owner := compactFixture(t, session.StateIdle) original := session.CloneMessages(sess.Conversation.Messages) diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index 54bbc378ae..f8b342d371 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -584,7 +584,7 @@ type Config struct { // Mutating member) and the provider/model. MemberEngine MemberEngineFactory // MemberEngineForOperation resolves the direct RunTeam member factory from the - // same operation-pinned context retained by the team. Nil uses MemberEngine. + // operation-pinned context acquired at RunTeam. Nil uses MemberEngine. MemberEngineForOperation func(context.Context) MemberEngineFactory // TeamGoalUntrusted, when true, re-fences the gRPC/HTTP CreateTeam goal as // UNTRUSTED data in member and synthesis prompts (threaded to @@ -3048,28 +3048,19 @@ func (s *Service) Close() { for id := range s.heldLeases { leasedIDs = append(leasedIDs, id) } - teamOperationReleases := make([]func(), 0, len(s.teams)) - for _, ts := range s.teams { - // A running direct Team owns its operation pin until Supervisor.Run - // returns. Releasing it here would let Build close the manager under live - // member calls; the RunTeam defer performs the release after drain. - if ts.phase != teamRunning && ts.operationRelease != nil { - teamOperationReleases = append(teamOperationReleases, ts.operationRelease) - ts.operationRelease = nil - ts.operationCtx = nil - } - } runOperationReleases := make([]func(), 0, len(s.runs)) for _, rs := range s.runs { - if rs.operationRelease != nil { + // Awaiting is deliberately left parked across shutdown and performs no MCP + // work. A completed run has also settled its provider/tool operation even if + // a caller omitted FinishRun. Every other pin stays attached to + // removeRunState so runtime closure cannot overtake live work or admission. + settled := rs.awaiting.Load() || (rs.run != nil && rs.run.Outcome() == agent.RunOutcomeCompleted) + if settled && rs.operationRelease != nil { runOperationReleases = append(runOperationReleases, rs.operationRelease) rs.operationRelease = nil } } s.mu.Unlock() - for _, release := range teamOperationReleases { - release() - } for _, release := range runOperationReleases { release() } @@ -3465,6 +3456,17 @@ func (s *Service) CompactSession(ctx context.Context, id session.SessionID, call defer release() compactCtx, stopCompact, leaseHeld := s.mutationLeaseContext(ctx, id) defer stopCompact() + operationRelease := func() {} + if s.cfg.OperationPin != nil { + compactCtx, operationRelease, err = s.cfg.OperationPin(compactCtx) + if err != nil { + return agent.ManualCompactionResult{}, err + } + if operationRelease == nil { + operationRelease = func() {} + } + } + defer operationRelease() sess, _, err = s.managementTarget(ctx, id, false) if err != nil { return agent.ManualCompactionResult{}, err @@ -3472,7 +3474,7 @@ func (s *Service) CompactSession(ctx context.Context, id session.SessionID, call if err := admitRunPurpose(sess, runPurposeChat); err != nil { return agent.ManualCompactionResult{}, err } - eng, _, err := s.engineAndEnvironmentFor(ctx, sess) + eng, _, err := s.engineAndEnvironmentFor(compactCtx, sess) if err != nil { return agent.ManualCompactionResult{}, err } diff --git a/internal/adapter/server/session_mutation_inventory.go b/internal/adapter/server/session_mutation_inventory.go index 14b9596bac..5accc3b428 100644 --- a/internal/adapter/server/session_mutation_inventory.go +++ b/internal/adapter/server/session_mutation_inventory.go @@ -78,7 +78,7 @@ var sessionMutationInventory = map[string]SessionMutationEntry{ "driveSessionMigration": {SessionMutationLeaseOwned, "job checkpoints are job-lease-owned and each family rewrite delegates to migrateOneFamily"}, "CancelSessionMigration": {SessionMutationLeaseOwned, "migration job cancellation is protected by the backend job-scoped acquisition"}, "ApplySessionCleanup": {SessionMutationLeaseOwned, "each family deletion delegates to the run-entry and maintenance-lease retention path"}, - "deleteAbandonedMembers": {SessionMutationLeaseProven, "team creation acquires every member lease before publication and keeps it through abandoned-family cleanup"}, + "deleteAbandonedMembers": {SessionMutationLeaseProven, "team setup acquires every member lease before publication and keeps it through abandoned-family cleanup"}, "repairRunningAtRunEntry": {SessionMutationLeaseProven, "run-entry has acquired the session lease before crash-orphan repair save"}, "GetSession": {SessionMutationReadOnly, "loads and authorizes an authoritative snapshot without changing the durable family"}, "GetTranscript": {SessionMutationReadOnly, "projects an authorized snapshot without changing the durable family"}, diff --git a/internal/adapter/server/team.go b/internal/adapter/server/team.go index d5a507571f..852ed35d40 100644 --- a/internal/adapter/server/team.go +++ b/internal/adapter/server/team.go @@ -87,17 +87,24 @@ type MemberEngineFactory func(t *team.Team, spec agent.MemberSpec, routedModel s // (that would deadlock CleanupTeam-style introspection); RunTeam releases it the // instant the phase has flipped to teamRunning, after which the phase check in any // later SpawnTeammate rejects the spawn cleanly. -type teamState struct { - team *team.Team - sup *agent.Supervisor - base string - owner *session.Principal - phase teamPhase +type teamDeclarationMessage struct { + from string + to string + body string +} - // operationCtx carries the immutable direct-runtime pin selected before any - // member factory runs. operationRelease drains it after RunTeam or cleanup. - operationCtx context.Context - operationRelease func() +type teamState struct { + team *team.Team + sup *agent.Supervisor + base string + env tool.Environment + name string + goal string + budget int + specs []agent.MemberSpec + messages []teamDeclarationMessage + owner *session.Principal + phase teamPhase // run serialises a SpawnTeammate (AddMember writes the supervisor's member maps) // against a RunTeam start (sup.Run reads them). See the type doc above. @@ -105,9 +112,9 @@ type teamState struct { } // CreateTeamOnDefaultPlacement allocates a new agent team over the trusted default -// placement, enrols an optional initial roster, and returns its server-assigned -// id together with the enrolled roster. It builds the supervisor (binding the member-engine factory to -// the shared team), then adds each member before the team is registered. +// placement, stores an optional initial roster, and returns its server-assigned +// id together with that roster. When immutable-runtime publication is wired, the +// declarations intentionally remain engine-free until RunTeam acquires its pin. // // Enrolment is ATOMIC: if any member fails to enrol the whole team is abandoned — // it is never registered (no partial team leaks) and does not consume a MaxTeams @@ -159,38 +166,8 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ if s.cfg.MemberEngine == nil { return "", nil, ErrTeamsDisabled } - operationCtx := context.WithoutCancel(ctx) - operationRelease := func() {} - if s.cfg.OperationPin != nil { - var err error - operationCtx, operationRelease, err = s.cfg.OperationPin(operationCtx) - if err != nil { - return "", nil, err - } - if operationRelease == nil { - operationRelease = func() {} - } - } - pinTransferred := false - defer func() { - if !pinTransferred { - operationRelease() - } - }() - ctx = operationCtx - memberEngine := s.cfg.MemberEngine - if s.cfg.MemberEngineForOperation != nil { - memberEngine = s.cfg.MemberEngineForOperation(ctx) - if memberEngine == nil { - return "", nil, ErrTeamsDisabled - } - } workspace := base.Workspace().Root() - t := team.New(name) - factory := func(spec agent.MemberSpec, routedModel string) agent.MemberBuild { - return memberEngine(t, spec, routedModel) - } // Compute the team id FIRST (it needs only NewID, no dependency on the supervisor) // so the member-session prefix can namespace member ids by it — keeping the gRPC @@ -200,58 +177,6 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ // id-minting convention (and thereby in scope for the child-session GC). id := agent.TeamSessionPrefix + string(s.cfg.NewID()) - opts := []agent.SupervisorOption{ - agent.WithTeamGoal(goal), - agent.WithMemberSessionPrefix(agent.TeamSessionPrefix + id), - } - if s.cfg.RootAuthority != nil { - opts = append(opts, agent.WithRootAuthority(s.cfg.RootAuthority(session.SessionKindTeamMember))) - } - // Attribute members to the creating caller. CreateTeam runs with zero parent - // caps by design, so without this AddMember publishes durable member sessions - // with Owner == nil — unreadable by the team's own owner, and skipped by every - // retention path, so they can never be reaped. Appended unconditionally: - // WithTeamOwner no-ops on a nil principal, which is the ownerless path. - opts = append(opts, agent.WithTeamOwner(session.PrincipalFromContext(ctx))) - // The goal is the team's TRUSTED top-level instruction by default (the deployment - // owns the gRPC front door, so the goal's provenance is the operator/principal, - // not a peer). A multi-tenant / relay deployment that may interpolate untrusted - // end-user text into the goal flips Config.TeamGoalUntrusted to re-fence it as - // data. Peer messages and task descriptions stay fenced regardless. - if s.cfg.TeamGoalUntrusted { - opts = append(opts, agent.WithUntrustedGoal(true)) - } - if s.cfg.Forker != nil { - opts = append(opts, agent.WithForker(s.cfg.Forker)) - } - if s.cfg.ReadOnlyForker != nil { - opts = append(opts, agent.WithReadOnlyForker(s.cfg.ReadOnlyForker)) - } - opts = append(opts, agent.WithTeamReadLedgerFactory(func() tool.ReadLedger { return memledger.New() })) - if s.cfg.SharedBaseWorkspace != nil { - opts = append(opts, agent.WithTeamSharedBaseWorkspace(s.cfg.SharedBaseWorkspace)) - } - if s.cfg.TeamHooks != nil { - opts = append(opts, agent.WithTeamHooks(s.cfg.TeamHooks)) - } - if s.cfg.Store != nil { - opts = append(opts, agent.WithMemberStore(s.cfg.Store)) - } - if s.cfg.SessionLiveness != nil { - opts = append(opts, agent.WithMemberLiveness(s.cfg.SessionLiveness)) - } - // Clamp the per-request budget against the server's ceiling at create time: - // tighten-only, so the wire can never loosen the operator's bound. - if budget := agent.TightenTeamTokenBudget(s.cfg.TeamTokenBudget, maxTeamTokens); budget > 0 { - opts = append(opts, agent.WithTeamTokenBudget(budget)) - } - // The gRPC RunTeam direct path deliberately runs with ZERO parent caps: no - // surface-to-human seam AND no child-ask adjudicator (issue #31) — a member's - // unresolved permission ask headless-auto-denies exactly as before. The in-loop - // Team TOOL is the path that inherits the parent run's caps (surfacing and, when - // configured, the automated reviewer). - sup := agent.NewSupervisor(t, base, factory, opts...) - // Claim a registry slot BEFORE enrolling. Enrolment acquires each member's // cross-process lease and publishes a durable member snapshot, so checking the // cap afterwards would refuse the request having already stranded both: leases @@ -274,95 +199,70 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ } }() - // Enrol the initial roster BEFORE registering the team. A failure here abandons - // the whole team: the reservation is dropped, every acquired lease is released, - // every published member snapshot is deleted, and the un-registered supervisor - // is GC'd — so a refused create leaves nothing behind. - // - // The member's cross-process lease is acquired BEFORE AddMember, not after and - // not in RunTeam: AddMember publishes a durable SessionKindTeamMember snapshot, - // which is retention-eligible, so a lease taken afterwards leaves a window in - // which a peer replica can delete a live team's member — unbounded, and infinite - // for a team that is never run. Leasing first also means a refused lease writes - // nothing, so the abandon path leaves no orphaned member snapshot behind. - // Member ids are derivable here because the team id was computed above, before - // the supervisor. RunTeam's own acquire loop stays as a no-op backstop - // (acquireLease is idempotent for an id this service already holds). - if err := s.enrolInitialRoster(ctx, id, sup, members); err != nil { + state := &teamState{ + team: t, base: workspace, env: base, name: name, goal: goal, + budget: maxTeamTokens, specs: append([]agent.MemberSpec(nil), members...), + owner: session.PrincipalFromContext(ctx).Clone(), + } + if err := s.declareInitialRoster(t, members); err != nil { return "", nil, err } + if s.cfg.OperationPin == nil { + leased := make([]session.SessionID, 0, len(members)) + for _, spec := range members { + memberID := agent.MemberSessionID(id, spec.Name) + if err := s.acquireLease(ctx, memberID); err != nil { + for _, acquired := range leased { + s.releaseLease(acquired) + } + return "", nil, err + } + leased = append(leased, memberID) + } + builtTeam, sup, err := s.buildTeamForOperation(ctx, id, state) + if err != nil { + s.deleteAbandonedMembers(ctx, leased) + for _, acquired := range leased { + s.releaseLease(acquired) + } + return "", nil, err + } + state.team, state.sup = builtTeam, sup + } s.mu.Lock() // The slot was claimed above, so no capacity refusal can occur here — the cap // is enforced before any lease or durable write. - s.teams[id] = &teamState{ - team: t, sup: sup, base: workspace, owner: session.PrincipalFromContext(ctx).Clone(), - operationCtx: ctx, operationRelease: operationRelease, - } + s.teams[id] = state s.teamsReserving-- registered = true - pinTransferred = true s.mu.Unlock() - return id, t.Members(), nil + return id, state.team.Members(), nil } -// enrolInitialRoster adds every initial member, leaving NOTHING behind on -// failure: each member's cross-process lease is acquired before AddMember -// publishes its durable snapshot, and any failure releases the leases and -// deletes the snapshots taken so far. Extracted from CreateTeam to keep it under -// the gocyclo threshold, the same reason createPerSessionEngine was split out of -// createSession. The returned error is already classified for the wire. -func (s *Service) enrolInitialRoster(ctx context.Context, teamID string, sup *agent.Supervisor, members []agent.MemberSpec) error { - leased := make([]session.SessionID, 0, len(members)) - published := make([]session.SessionID, 0, len(members)) - unwind := func() { - // Published snapshots first, then leases: the lease is what stops a peer - // replica touching the record, so it is released last. - s.deleteAbandonedMembers(ctx, published) - for _, id := range leased { - s.releaseLease(id) - } - } +func (s *Service) declareInitialRoster(t *team.Team, members []agent.MemberSpec) error { for _, spec := range members { - memberID := agent.MemberSessionID(teamID, spec.Name) - if err := s.acquireLease(ctx, memberID); err != nil { - unwind() - return err + if spec.Name == "" { + return fmt.Errorf("%w: %v", ErrInvalidArgument, agent.ErrMemberNameRequired) } - leased = append(leased, memberID) - if err := sup.AddMember(ctx, spec); err != nil { - unwind() + if spec.Mutating && s.cfg.Forker == nil { + return fmt.Errorf("%w: %v", ErrFailedPrecondition, agent.ErrNoForker) + } + if err := t.AddMember(spec.Name, spec.AgentType); err != nil { return classifyAddMemberErr(err) } - published = append(published, memberID) } return nil } -// deleteAbandonedMembers removes the durable member snapshots an abandoned -// CreateTeam already published. Best-effort and deliberately quiet: the caller -// is already returning the failure that matters, and a store that cannot prune -// (no port.PrunableStore) simply leaves the records for retention — which can -// reach them, because they carry the creating caller's owner. -// -// It runs while this service still holds each member's lease, so no peer replica -// can be mid-flight on the same id. func (s *Service) deleteAbandonedMembers(ctx context.Context, ids []session.SessionID) { - if len(ids) == 0 { - return - } prunable, ok := s.cfg.Store.(port.PrunableStore) if !ok { return } for _, id := range ids { - if !s.mutationLeaseHeld(id) { - continue - } if err := s.deleteSessionFamily(ctx, id, prunable); err != nil && !errors.Is(err, port.ErrSessionNotFound) { - s.cfg.Diagnostics.Log(ctx, port.LevelWarn, - "abandoned team member snapshot could not be deleted; left for retention", - "session", string(id), "err", err.Error()) + s.cfg.Diagnostics.Log(ctx, port.LevelWarn, "abandoned team member snapshot could not be deleted; left for retention", "session", string(id), "err", err.Error()) } } } @@ -403,16 +303,25 @@ func (s *Service) SpawnTeammate(ctx context.Context, teamID string, spec agent.M if started { return team.Member{}, fmt.Errorf("%w: cannot spawn into a team that has started", ErrTeamRunning) } - // Lease before AddMember publishes the durable member snapshot — same ordering - // and same reason as CreateTeam's enrolment loop above. - memberID := agent.MemberSessionID(teamID, spec.Name) - if err := s.acquireLease(ctx, memberID); err != nil { - return team.Member{}, err + if spec.Name == "" { + return team.Member{}, fmt.Errorf("%w: %v", ErrInvalidArgument, agent.ErrMemberNameRequired) } - if err := ts.sup.AddMember(ctx, spec); err != nil { - s.releaseLease(memberID) + if spec.Mutating && s.cfg.Forker == nil { + return team.Member{}, fmt.Errorf("%w: %v", ErrFailedPrecondition, agent.ErrNoForker) + } + if s.cfg.OperationPin == nil { + memberID := agent.MemberSessionID(teamID, spec.Name) + if err := s.acquireLease(ctx, memberID); err != nil { + return team.Member{}, err + } + if err := ts.sup.AddMember(ctx, spec); err != nil { + s.releaseLease(memberID) + return team.Member{}, classifyAddMemberErr(err) + } + } else if err := ts.team.AddMember(spec.Name, spec.AgentType); err != nil { return team.Member{}, classifyAddMemberErr(err) } + ts.specs = append(ts.specs, spec) for _, m := range ts.team.Members() { if m.Name == spec.Name { return m, nil @@ -465,12 +374,17 @@ func (s *Service) SendTeammateMessage(ctx context.Context, teamID, from, to, bod if err != nil { return err } + ts.run.Lock() + defer ts.run.Unlock() if from == "" { from = team.OperatorSender } if err := ts.team.Send(from, to, body); err != nil { return fmt.Errorf("%w: %v", ErrInvalidArgument, err) } + if s.cfg.OperationPin != nil && ts.phase == teamCreated { + ts.messages = append(ts.messages, teamDeclarationMessage{from: from, to: to, body: body}) + } return nil } @@ -511,6 +425,65 @@ func (s *Service) CancelTeammate(ctx context.Context, teamID, member string) err return nil } +func (s *Service) buildTeamForOperation(ctx context.Context, teamID string, ts *teamState) (*team.Team, *agent.Supervisor, error) { + memberEngine := s.cfg.MemberEngine + if s.cfg.MemberEngineForOperation != nil { + memberEngine = s.cfg.MemberEngineForOperation(ctx) + } + if memberEngine == nil { + return nil, nil, ErrTeamsDisabled + } + t := team.New(ts.name) + factory := func(spec agent.MemberSpec, routedModel string) agent.MemberBuild { + return memberEngine(t, spec, routedModel) + } + opts := []agent.SupervisorOption{ + agent.WithTeamGoal(ts.goal), + agent.WithMemberSessionPrefix(agent.TeamSessionPrefix + teamID), + agent.WithTeamOwner(ts.owner), + agent.WithTeamReadLedgerFactory(func() tool.ReadLedger { return memledger.New() }), + } + if s.cfg.RootAuthority != nil { + opts = append(opts, agent.WithRootAuthority(s.cfg.RootAuthority(session.SessionKindTeamMember))) + } + if s.cfg.TeamGoalUntrusted { + opts = append(opts, agent.WithUntrustedGoal(true)) + } + if s.cfg.Forker != nil { + opts = append(opts, agent.WithForker(s.cfg.Forker)) + } + if s.cfg.ReadOnlyForker != nil { + opts = append(opts, agent.WithReadOnlyForker(s.cfg.ReadOnlyForker)) + } + if s.cfg.SharedBaseWorkspace != nil { + opts = append(opts, agent.WithTeamSharedBaseWorkspace(s.cfg.SharedBaseWorkspace)) + } + if s.cfg.TeamHooks != nil { + opts = append(opts, agent.WithTeamHooks(s.cfg.TeamHooks)) + } + if s.cfg.Store != nil { + opts = append(opts, agent.WithMemberStore(s.cfg.Store)) + } + if s.cfg.SessionLiveness != nil { + opts = append(opts, agent.WithMemberLiveness(s.cfg.SessionLiveness)) + } + if budget := agent.TightenTeamTokenBudget(s.cfg.TeamTokenBudget, ts.budget); budget > 0 { + opts = append(opts, agent.WithTeamTokenBudget(budget)) + } + sup := agent.NewSupervisor(t, ts.env, factory, opts...) + for _, spec := range ts.specs { + if err := sup.AddMember(ctx, spec); err != nil { + return nil, nil, classifyAddMemberErr(err) + } + } + for _, message := range ts.messages { + if err := t.Send(message.from, message.to, message.body); err != nil { + return nil, nil, fmt.Errorf("%w: restore team declaration message: %v", ErrInternal, err) + } + } + return t, sup, nil +} + // RunTeam drives the team to quiescence, invoking sink for every member event, // and returns the outcome. It blocks for the team's lifetime; the gRPC handler // runs it on the request goroutine and forwards events to the stream. @@ -531,15 +504,7 @@ func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.Te if err != nil { return agent.TeamOutcome{}, err } - if ts.operationCtx != nil { - runCtx, cancel := context.WithCancel(ts.operationCtx) - stop := context.AfterFunc(ctx, cancel) - defer func() { - stop() - cancel() - }() - ctx = runCtx - } else if s.cfg.OperationPin != nil { + if s.cfg.OperationPin != nil { pinned, release, pinErr := s.cfg.OperationPin(ctx) if pinErr != nil { return agent.TeamOutcome{}, pinErr @@ -568,36 +533,47 @@ func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.Te } ts.phase = teamRunning s.mu.Unlock() - ts.run.Unlock() - // Team members are durable sessions driven outside StartRunContent, so their - // cross-process ownership must be established here before Supervisor.Run - // starts their engines. acquireLease is idempotent for a session already held - // by this service and keeps the hold until CloseSession or service shutdown. - for _, member := range ts.team.Members() { - memberID := member.Session - if memberID == "" { - memberID = agent.MemberSessionID(teamID, member.Name) - } + leased := make([]session.SessionID, 0, len(ts.specs)) + for _, spec := range ts.specs { + memberID := agent.MemberSessionID(teamID, spec.Name) if err := s.acquireLease(ctx, memberID); err != nil { + for _, acquired := range leased { + s.releaseLease(acquired) + } + s.mu.Lock() + ts.phase = teamCreated + s.mu.Unlock() + ts.run.Unlock() + return agent.TeamOutcome{}, err + } + leased = append(leased, memberID) + } + + if s.cfg.OperationPin != nil { + runtimeTeam, runtimeSupervisor, err := s.buildTeamForOperation(ctx, teamID, ts) + if err != nil { + s.deleteAbandonedMembers(ctx, leased) + for _, acquired := range leased { + s.releaseLease(acquired) + } s.mu.Lock() ts.phase = teamCreated s.mu.Unlock() + ts.run.Unlock() return agent.TeamOutcome{}, err } + s.mu.Lock() + ts.team = runtimeTeam + ts.sup = runtimeSupervisor + s.mu.Unlock() } + ts.run.Unlock() defer func() { - var release func() s.mu.Lock() ts.phase = teamDone - release = ts.operationRelease - ts.operationRelease = nil - ts.operationCtx = nil s.mu.Unlock() - if release != nil { - release() - } }() return ts.sup.Run(ctx, sink), nil } @@ -630,13 +606,7 @@ func (s *Service) CleanupTeam(ctx context.Context, teamID string) error { return fmt.Errorf("%w: %q", ErrTeamRunning, teamID) } delete(s.teams, teamID) - releaseOperation := ts.operationRelease - ts.operationRelease = nil - ts.operationCtx = nil s.mu.Unlock() - if releaseOperation != nil { - releaseOperation() - } // Release every member lease this team acquired. Without this the lease and its // renewer goroutine outlive the team and are only reclaimed at process exit, so a diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go index c740b15a51..963253ce06 100644 --- a/internal/app/mcp_reconciler.go +++ b/internal/app/mcp_reconciler.go @@ -26,8 +26,6 @@ const ( maxMCPActiveListEntries = 10_000 maxMCPCandidatePages = 256 maxMCPCandidateBytes = 16 << 20 - maxMCPUnionGrantNames = 1_024 - maxMCPHistoricalGrantedNames = 16_384 maxMCPRetainedRuntimes = 4 maxMCPDiagnosticBytes = 512 maxMCPReconcileCycleDuration = 45 * time.Second @@ -124,6 +122,7 @@ type mcpSourceReconciler struct { cyclesDone atomic.Int64 nextGen atomic.Uint64 + preparingGen atomic.Uint64 candidateDirty atomic.Bool } @@ -253,7 +252,7 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { r.mu.Lock() current := r.current - unchanged := current != nil && reflect.DeepEqual(current.configs, configs) + unchanged := current != nil && equalMCPConfigs(current.configs, configs) r.mu.Unlock() candidateDirty := r.candidateDirty.Swap(false) if unchanged && !stale && !candidateDirty { @@ -265,17 +264,19 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { } generation := r.nextGen.Add(1) + r.preparingGen.Store(generation) dirty := func() { r.mu.Lock() isCurrent := r.current != nil && r.current.generation == generation r.mu.Unlock() - if isCurrent { + if isCurrent || r.preparingGen.Load() == generation { r.candidateDirty.Store(true) r.invalidate() } } candidate, err := r.build(cycleCtx, configs, dirty) if err != nil { + r.preparingGen.CompareAndSwap(generation, 0) result.stale = true result.diagnostics = appendBoundedDiagnostic(result.diagnostics, err.Error()) r.mu.Lock() @@ -284,12 +285,14 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { return result, err } if candidate == nil { + r.preparingGen.CompareAndSwap(generation, 0) return result, errors.New("MCP candidate builder returned nil") } candidate.generation = generation candidate.configs = cloneMCPConfigs(configs) candidate.inventory = cloneMCPInventory(inventory) if err := validateMCPCandidate(candidate); err != nil { + r.preparingGen.CompareAndSwap(generation, 0) candidate.close() result.stale = true result.diagnostics = appendBoundedDiagnostic(result.diagnostics, err.Error()) @@ -300,6 +303,7 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { old := r.current r.mu.Unlock() if equalMCPCandidate(old, candidate) { + r.preparingGen.CompareAndSwap(generation, 0) candidate.close() result.candidate = old return result, nil @@ -307,6 +311,7 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { r.mu.Lock() r.current = candidate r.mu.Unlock() + r.preparingGen.CompareAndSwap(generation, 0) if r.publish != nil && !r.publish(old, candidate) { r.mu.Lock() if r.current == candidate { @@ -441,6 +446,28 @@ func cloneMCPConfigs(in []mcp.ServerConfig) []mcp.ServerConfig { return out } +func equalMCPConfigs(a, b []mcp.ServerConfig) bool { + return reflect.DeepEqual(comparableMCPConfigs(a), comparableMCPConfigs(b)) +} + +func comparableMCPConfigs(in []mcp.ServerConfig) []mcp.ServerConfig { + out := cloneMCPConfigs(in) + for i := range out { + out[i].ListChanged = nil + out[i].CandidateBudget = nil + out[i].TokenSource = nil + out[i].HTTPClient = nil + if out[i].OAuth != nil { + oauth := *out[i].OAuth + oauth.Presenter = nil + oauth.CredentialStore = nil + oauth.CredentialReader = nil + out[i].OAuth = &oauth + } + } + return out +} + func cloneMCPInventory(in []mcpsource.SourceInfo) []mcpsource.SourceInfo { out := make([]mcpsource.SourceInfo, len(in)) for i, info := range in { @@ -480,7 +507,7 @@ func equalMCPCandidate(a, b *mcpReconcileCandidate) bool { if a == nil || b == nil { return a == b } - return reflect.DeepEqual(a.configs, b.configs) && reflect.DeepEqual(a.tools, b.tools) && reflect.DeepEqual(a.resources, b.resources) && reflect.DeepEqual(a.prompts, b.prompts) && reflect.DeepEqual(a.inventory, b.inventory) + return equalMCPConfigs(a.configs, b.configs) && reflect.DeepEqual(a.tools, b.tools) && reflect.DeepEqual(a.resources, b.resources) && reflect.DeepEqual(a.prompts, b.prompts) && reflect.DeepEqual(a.inventory, b.inventory) } func toolMetadata(tools []tool.Tool) []mcpToolMeta { @@ -493,23 +520,6 @@ func toolMetadata(tools []tool.Tool) []mcpToolMeta { return out } -func validateMCPGrantBounds(existing, additions []string) error { - if len(additions) > maxMCPUnionGrantNames { - return fmt.Errorf("MCP refresh additions exceed limit %d", maxMCPUnionGrantNames) - } - seen := make(map[string]struct{}, len(existing)+len(additions)) - for _, name := range existing { - seen[name] = struct{}{} - } - for _, name := range additions { - seen[name] = struct{}{} - } - if len(seen) > maxMCPHistoricalGrantedNames { - return fmt.Errorf("historical MCP grants exceed limit %d", maxMCPHistoricalGrantedNames) - } - return nil -} - func buildMCPReconcileCandidate(diagCfg Config) mcpCandidateBuilder { return func(ctx context.Context, configs []mcp.ServerConfig, changed func()) (*mcpReconcileCandidate, error) { bounded := cloneMCPConfigs(configs) diff --git a/internal/app/mcp_reconciler_test.go b/internal/app/mcp_reconciler_test.go index a3735ecc60..9a8153ef50 100644 --- a/internal/app/mcp_reconciler_test.go +++ b/internal/app/mcp_reconciler_test.go @@ -3,7 +3,6 @@ package app import ( "context" "errors" - "fmt" "net/http" "net/http/httptest" "sync" @@ -11,6 +10,7 @@ import ( "testing" "time" + "github.com/modelcontextprotocol/go-sdk/auth" mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/stacklok/mecatl/internal/adapter/mcp" @@ -133,7 +133,9 @@ func TestMCPSourceReconciliation_Scenario1_ProductionTriggerMatrix(t *testing.T) }) t.Run("toolhive-poll-and-stable-no-reconnect", func(t *testing.T) { - th := &reconciliationSource{name: "toolhive(default)", cfgs: []mcp.ServerConfig{{Name: "a", URL: "http://a/mcp"}}} + th := &reconciliationSource{name: "toolhive(default)", cfgs: []mcp.ServerConfig{{ + Name: "a", URL: "http://a/mcp", OAuth: &mcp.OAuthOptions{Presenter: mcp.OAuthPresenterFunc(func(context.Context, string) (*auth.AuthorizationResult, error) { return nil, nil })}, + }}} ticks := make(chan time.Time, 4) var builds atomic.Int64 r := newMCPSourceReconciler(mcpReconcilerOptions{ @@ -189,6 +191,28 @@ func TestMCPSourceReconciliation_Scenario1_ProductionTriggerMatrix(t *testing.T) } }) + t.Run("notification-while-preparing-queues-one-successor", func(t *testing.T) { + var builds atomic.Int64 + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "a", URL: "http://a/mcp"}}}}, + build: func(_ context.Context, configs []mcp.ServerConfig, changed func()) (*mcpReconcileCandidate, error) { + n := builds.Add(1) + if n == 1 { + changed() + } + return candidateFromConfigs(configs, uint64(n)), nil + }, + }) + t.Cleanup(r.Close) + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatal(err) + } + eventuallyReconcile(t, func() bool { return r.cycles() >= 2 }) + if got := builds.Load(); got != 2 { + t.Fatalf("pre-publication notification builds = %d, want one successor", got) + } + }) + t.Run("real-notification-refreshes-complete-snapshot", func(t *testing.T) { remote := mcpsdk.NewServer(&mcpsdk.Implementation{Name: "live", Version: "v1"}, nil) mcpsdk.AddTool(remote, &mcpsdk.Tool{Name: "initial"}, func(context.Context, *mcpsdk.CallToolRequest, struct{}) (*mcpsdk.CallToolResult, any, error) { @@ -224,7 +248,7 @@ func TestMCPSourceReconciliation_Scenario1_ProductionTriggerMatrix(t *testing.T) } func TestADR_0345_ReconciliationBoundsConsentAndShutdown(t *testing.T) { - if maxMCPReconcileSources <= 0 || maxMCPReconcileServers <= 0 || maxMCPActiveListEntries <= 0 || maxMCPCandidatePages <= 0 || maxMCPCandidateBytes <= 0 || maxMCPUnionGrantNames <= 0 || maxMCPHistoricalGrantedNames <= 0 || maxMCPRetainedRuntimes <= 0 || maxMCPReconcileCycleDuration <= 0 { + if maxMCPReconcileSources <= 0 || maxMCPReconcileServers <= 0 || maxMCPActiveListEntries <= 0 || maxMCPCandidatePages <= 0 || maxMCPCandidateBytes <= 0 || maxMCPRetainedRuntimes <= 0 || maxMCPReconcileCycleDuration <= 0 { t.Fatal("every reconciliation dimension must have an independent finite bound") } tooMany := make([]mcp.ServerConfig, maxMCPReconcileServers+1) @@ -261,23 +285,6 @@ func TestADR_0345_ReconciliationBoundsConsentAndShutdown(t *testing.T) { if err := validateMCPCandidate(&mcpReconcileCandidate{tools: make([]mcpToolMeta, maxMCPActiveListEntries), pages: maxMCPCandidatePages, bytes: maxMCPCandidateBytes}); err != nil { t.Fatalf("candidate boundary rejected: %v", err) } - if err := validateMCPGrantBounds(nil, make([]string, maxMCPUnionGrantNames)); err != nil { - t.Fatalf("union boundary rejected: %v", err) - } - if err := validateMCPGrantBounds(nil, make([]string, maxMCPUnionGrantNames+1)); err == nil { - t.Fatal("union over-bound accepted") - } - existing := make([]string, maxMCPHistoricalGrantedNames) - for i := range existing { - existing[i] = fmt.Sprintf("mcp__s__%d", i) - } - if err := validateMCPGrantBounds(existing, nil); err != nil { - t.Fatalf("historical boundary rejected: %v", err) - } - if err := validateMCPGrantBounds(existing, []string{"mcp__s__overflow"}); err == nil { - t.Fatal("historical over-bound accepted") - } - presenter := mcp.OAuthPresenterFunc(nil) cloned := cloneMCPConfigs([]mcp.ServerConfig{{OAuth: &mcp.OAuthOptions{Presenter: presenter}}}) if cloned[0].OAuth == nil || cloned[0].OAuth.Presenter != nil { diff --git a/internal/app/mcp_runtime_publication_test.go b/internal/app/mcp_runtime_publication_test.go index e908929adc..af86852475 100644 --- a/internal/app/mcp_runtime_publication_test.go +++ b/internal/app/mcp_runtime_publication_test.go @@ -281,9 +281,9 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T } runRuntimes.close() - // Direct RunTeam builds member engines before RunTeam starts, so team creation - // retains the operation pin. A publication between CreateTeam and RunTeam must - // not swap a referenced specialist onto the new manager. + // Direct teams retain declarations only until RunTeam. Publication between + // CreateTeam and RunTeam must retire the old runtime and build every member and + // referenced specialist from the operation pin acquired by RunTeam. const teamTool = "mcp__svc__echo" teamRuntimes := newMCPRuntimeSet(nil) teamOldManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "team-old:")) @@ -346,6 +346,9 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T if !teamRuntimes.publish(teamOld, teamNew) { t.Fatal("publish direct-team revision 2") } + if !teamOld.isClosed() { + t.Fatal("created-but-unrun direct team retained the retired runtime") + } if _, err := teamSvc.RunTeam(context.Background(), teamID, func(agent.TeamEvent) {}); err != nil { t.Fatal(err) } @@ -353,11 +356,8 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T if err != nil { t.Fatal(err) } - if got := latestToolResult(member, "team-call"); !strings.Contains(got, "team-old:work") { - t.Fatalf("direct RunTeam member did not retain its creation pin: %q", got) - } - if !teamOld.isClosed() { - t.Fatal("direct RunTeam runtime did not retire after team completion") + if got := latestToolResult(member, "team-call"); !strings.Contains(got, "team-new:work") { + t.Fatalf("direct RunTeam member did not use its run-time pin: %q", got) } newTeamID, _, err := teamSvc.CreateTeamOnDefaultPlacement(context.Background(), "current", "use the current service", 0, []agent.MemberSpec{{ Name: "lead", Lead: true, AgentType: "team-ref", InitialPrompt: "call the service once", From af083090acb0430c3d0895c8582cfd85c6d0d9c6 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 00:50:57 +0200 Subject: [PATCH 07/14] fix(mcp): correlate refresh transport responses Co-Authored-By: mecatl --- .../tasks/03-provider-model-inventory.md | 2 +- cmd/mecatui/client/mcp.go | 10 ++-- cmd/mecatui/ui/mcp.go | 3 +- cmd/mecatui/ui/mcp_refresh_routing_test.go | 58 ++++++++++++++++++- cmd/mecatui/ui/model.go | 3 +- cmd/mecatui/ui/update.go | 3 + .../operator-defined-llm-providers.md | 4 +- internal/adapter/server/http_affinity_test.go | 1 + 8 files changed, 73 insertions(+), 11 deletions(-) diff --git a/.claude/plans/operator-defined-llm-providers/tasks/03-provider-model-inventory.md b/.claude/plans/operator-defined-llm-providers/tasks/03-provider-model-inventory.md index e70c2d0174..622073d317 100644 --- a/.claude/plans/operator-defined-llm-providers/tasks/03-provider-model-inventory.md +++ b/.claude/plans/operator-defined-llm-providers/tasks/03-provider-model-inventory.md @@ -35,4 +35,4 @@ remain conservative. Do not introduce a static custom-model declaration or new c - verify: `TestOperatorDefinedLLMProviders_Scenario4_ListingFallback` - AC4.4: unknown live model metadata never overclaims image, audio, reasoning, output, or context-window capabilities. - - verify: `TestInvariant_custom_provider_live_metadata_conservative` + - verify: `TestInvariant_custom_provider_omitted_live_modalities_use_adapter` diff --git a/cmd/mecatui/client/mcp.go b/cmd/mecatui/client/mcp.go index 94f67db274..041b1ffc86 100644 --- a/cmd/mecatui/client/mcp.go +++ b/cmd/mecatui/client/mcp.go @@ -172,8 +172,10 @@ type MCPRefreshResult struct { // MCPRefreshMsg carries an explicit direct-source refresh result. type MCPRefreshMsg struct { - Result MCPRefreshResult - Err error + RequestToken uint64 + SessionID string + Result MCPRefreshResult + Err error } // MCPGroupsMsg carries a ListToolHiveGroups success. @@ -513,10 +515,10 @@ func ListMcpSourcesCmd(ctx context.Context, m MCP) tea.Cmd { } // RefreshMcpSourcesCmd invokes explicit direct-source refresh. -func RefreshMcpSourcesCmd(ctx context.Context, m MCPRefresher, sessionID string) tea.Cmd { +func RefreshMcpSourcesCmd(ctx context.Context, m MCPRefresher, sessionID string, requestToken uint64) tea.Cmd { return func() tea.Msg { result, err := m.RefreshMCP(ctx, sessionID) - return MCPRefreshMsg{Result: result, Err: err} + return MCPRefreshMsg{RequestToken: requestToken, SessionID: sessionID, Result: result, Err: err} } } diff --git a/cmd/mecatui/ui/mcp.go b/cmd/mecatui/ui/mcp.go index 1e6470ffc5..9eba92d6c1 100644 --- a/cmd/mecatui/ui/mcp.go +++ b/cmd/mecatui/ui/mcp.go @@ -36,7 +36,8 @@ func (m Model) runMCPRefresh() (tea.Model, tea.Cmd) { return m, nil } m.statusMsg = m.deps.Theme.Style("muted").Render("refreshing MCP tools…") - return m, client.RefreshMcpSourcesCmd(m.deps.Ctx, refresher, m.sessionID) + m.mcpRefreshRequestToken++ + return m, client.RefreshMcpSourcesCmd(m.deps.Ctx, refresher, m.sessionID, m.mcpRefreshRequestToken) } // openMCP opens the selected MCP surface and starts its initial RPC. diff --git a/cmd/mecatui/ui/mcp_refresh_routing_test.go b/cmd/mecatui/ui/mcp_refresh_routing_test.go index 865a108055..0142aa455d 100644 --- a/cmd/mecatui/ui/mcp_refresh_routing_test.go +++ b/cmd/mecatui/ui/mcp_refresh_routing_test.go @@ -45,7 +45,7 @@ func TestMCPSourceReconciliation_Scenario4_UnifiedCommandRoutingMatrix(t *testin }{ {name: "direct-only", caps: client.Capabilities{MCPRefresh: true}, withDirect: true, wantRefreshCommand: true, wantDirectCalls: 1}, {name: "broker-only", caps: client.Capabilities{WorkspaceEnrollment: true}, withBroker: true, wantRefreshCommand: true, wantAlias: true, wantBrokerCalls: 1}, - {name: "both-fail-closed", caps: client.Capabilities{MCPRefresh: true, WorkspaceEnrollment: true}, withDirect: true, withBroker: true, wantAlias: true}, + {name: "both-fail-closed", caps: client.Capabilities{MCPRefresh: true, WorkspaceEnrollment: true}, withDirect: true, withBroker: true, wantAlias: true, wantBrokerCalls: 1}, {name: "neither-fail-closed"}, {name: "direct-missing-collaborator", caps: client.Capabilities{MCPRefresh: true}}, {name: "broker-missing-collaborator", caps: client.Capabilities{WorkspaceEnrollment: true}}, @@ -66,7 +66,7 @@ func TestMCPSourceReconciliation_Scenario4_UnifiedCommandRoutingMatrix(t *testin if refreshOK != tc.wantRefreshCommand { t.Fatalf("mcp-refresh registered=%v want %v", refreshOK, tc.wantRefreshCommand) } - _, aliasOK := builtinByName(m.caps, m.wiredCollaborators(), "tools-connect") + alias, aliasOK := builtinByName(m.caps, m.wiredCollaborators(), "tools-connect") if aliasOK != tc.wantAlias { t.Fatalf("tools-connect registered=%v want %v", aliasOK, tc.wantAlias) } @@ -86,9 +86,63 @@ func TestMCPSourceReconciliation_Scenario4_UnifiedCommandRoutingMatrix(t *testin mm, _ = m.Update(msg) m = mm.(Model) } + if aliasOK { + mm, cmd := alias.run(m) + m = mm.(Model) + if cmd == nil { + t.Fatal("tools-connect returned nil command") + } + msg := cmd() + if batch, ok := msg.(tea.BatchMsg); ok { + if len(batch) == 0 { + t.Fatal("empty tools-connect command batch") + } + msg = batch[0]() + } + mm, _ = m.Update(msg) + m = mm.(Model) + } if direct.refreshes != tc.wantDirectCalls || broker.connects != tc.wantBrokerCalls { t.Fatalf("direct calls=%d broker calls=%d, want %d/%d", direct.refreshes, broker.connects, tc.wantDirectCalls, tc.wantBrokerCalls) } }) } } + +func TestMCPRefreshLateResponsesDoNotCrossSessionOrRequest(t *testing.T) { + direct := &refreshRoutingMCP{} + m, _ := builtinDispatchModel(t, client.Capabilities{MCPRefresh: true}, false) + m.deps.MCP = direct + m.caps.MCPRefresh = true + + mm, firstCmd := m.runMCPRefresh() + m = mm.(Model) + first := firstCmd().(client.MCPRefreshMsg) + mm, secondCmd := m.runMCPRefresh() + m = mm.(Model) + second := secondCmd().(client.MCPRefreshMsg) + if first.RequestToken == second.RequestToken || second.SessionID != m.sessionID { + t.Fatalf("refresh correlation first=%+v second=%+v session=%q", first, second, m.sessionID) + } + + m.statusMsg = "current request pending" + mm, _ = m.Update(first) + m = mm.(Model) + if m.statusMsg != "current request pending" { + t.Fatalf("stale request changed status: %q", m.statusMsg) + } + + wrongSession := second + wrongSession.SessionID = "another-session" + mm, _ = m.Update(wrongSession) + m = mm.(Model) + if m.statusMsg != "current request pending" { + t.Fatalf("wrong-session response changed status: %q", m.statusMsg) + } + + mm, _ = m.Update(second) + m = mm.(Model) + if m.statusMsg == "current request pending" { + t.Fatal("current refresh response was ignored") + } +} diff --git a/cmd/mecatui/ui/model.go b/cmd/mecatui/ui/model.go index 97dfeb3e2f..3bdc3642a9 100644 --- a/cmd/mecatui/ui/model.go +++ b/cmd/mecatui/ui/model.go @@ -497,7 +497,8 @@ type Model struct { sessionsActionRequestToken uint64 // mcpRequestToken identifies broker inventory work across MCP panel lifetimes. // A panel-local refresh generation alone restarts at one after reopen. - mcpRequestToken uint64 + mcpRequestToken uint64 + mcpRefreshRequestToken uint64 // freshSessionBinding is true only for a session created by this UI's initial // create flow or /clear successor, never for adopted, resumed, or handoff bindings. freshSessionBinding bool diff --git a/cmd/mecatui/ui/update.go b/cmd/mecatui/ui/update.go index cdef67ce22..c10d9ad012 100644 --- a/cmd/mecatui/ui/update.go +++ b/cmd/mecatui/ui/update.go @@ -697,6 +697,9 @@ func (m Model) updateLifecycle(msg tea.Msg) (tea.Model, tea.Cmd, bool) { mm, cmd := m.applyWorkspaceEnrollmentPollTick(msg) return mm, cmd, true case client.MCPRefreshMsg: + if msg.RequestToken != m.mcpRefreshRequestToken || msg.SessionID != m.sessionID { + return m, nil, true + } if msg.Err != nil { m.statusMsg = m.deps.Theme.Style("warning").Render("MCP refresh failed: " + sanitizeTerminal(msg.Err.Error())) } else if msg.Result.Changed { diff --git a/docs/acceptance/operator-defined-llm-providers.md b/docs/acceptance/operator-defined-llm-providers.md index 003691ee1b..4ff3f3c4f3 100644 --- a/docs/acceptance/operator-defined-llm-providers.md +++ b/docs/acceptance/operator-defined-llm-providers.md @@ -135,7 +135,7 @@ follows the live-catalog fallback and capability-truth discipline in - verify: `TestOperatorDefinedLLMProviders_Scenario4_ListingFallback` - AC4.4: unknown live model metadata never overclaims image, audio, reasoning, output, or context-window capabilities. - - verify: `TestInvariant_custom_provider_live_metadata_conservative` + - verify: `TestInvariant_custom_provider_omitted_live_modalities_use_adapter` --- @@ -240,7 +240,7 @@ session rehydration. - `TestADR_0238_BuiltinOverrideAllowlist` - `TestInvariant_custom_provider_authfile_strict` - `TestInvariant_custom_provider_has_no_builtin_private_options` -- `TestInvariant_custom_provider_live_metadata_conservative` +- `TestInvariant_custom_provider_omitted_live_modalities_use_adapter` - `TestOperatorDefinedLLMProviders_Scenario1_ValidDefinition` - `TestOperatorDefinedLLMProviders_Scenario2_SeparateAuthFileKeys` - `TestOperatorDefinedLLMProviders_Scenario3_DeclaredFlavorSelectsAdapter` diff --git a/internal/adapter/server/http_affinity_test.go b/internal/adapter/server/http_affinity_test.go index 620685d7ba..deb2bfd47a 100644 --- a/internal/adapter/server/http_affinity_test.go +++ b/internal/adapter/server/http_affinity_test.go @@ -74,6 +74,7 @@ func TestSessionAffinityAndHandoff_Scenario3_HTTPRouteInventory(t *testing.T) { {"rename", http.MethodPost, "/v1/sessions/route-id/rename", `{"title":"title"}`}, {"delete", http.MethodPost, "/v1/sessions/route-id/delete", ""}, {"compact", http.MethodPost, "/v1/sessions/route-id/compact", ""}, + {"mcp refresh", http.MethodPost, "/v1/sessions/route-id/mcp-refresh", ""}, {"workspace connect", http.MethodPost, "/v1/sessions/route-id/workspace-enrollment/connect", ""}, {"workspace retry", http.MethodPost, "/v1/sessions/route-id/workspace-enrollment/enrollment-1/retry", ""}, {"workspace cancel", http.MethodPost, "/v1/sessions/route-id/workspace-enrollment/enrollment-1/cancel", ""}, From 98f8c48f8cb6681f4590601d9d35534ee8fb7431 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 01:13:00 +0200 Subject: [PATCH 08/14] test(mcp): strengthen runtime publication coverage Co-authored-by: mecatl --- internal/app/mcp_reconciler_test.go | 49 ++++ internal/app/mcp_runtime_publication_test.go | 255 ++++++++++++++++++- 2 files changed, 299 insertions(+), 5 deletions(-) diff --git a/internal/app/mcp_reconciler_test.go b/internal/app/mcp_reconciler_test.go index 9a8153ef50..267ff08625 100644 --- a/internal/app/mcp_reconciler_test.go +++ b/internal/app/mcp_reconciler_test.go @@ -5,6 +5,7 @@ import ( "errors" "net/http" "net/http/httptest" + "strings" "sync" "sync/atomic" "testing" @@ -312,6 +313,54 @@ func TestADR_0345_ReconciliationBoundsConsentAndShutdown(t *testing.T) { } } +func TestMCPSourceReconciliation_Scenario2_FailedCompleteCandidateKeepsPreviousRuntime(t *testing.T) { + healthyURL, deletes := newMCPTestServerCounting(t) + source := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "healthy", URL: healthyURL}}} + runtimes := newMCPRuntimeSet(nil) + reconciler := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{source}, + build: buildMCPReconcileCandidate(Config{}), + publish: runtimes.publish, + }) + runtimes.setRetry(reconciler.invalidate) + t.Cleanup(func() { + reconciler.Close() + runtimes.close() + }) + + first, err := reconciler.Reconcile(context.Background()) + if err != nil { + t.Fatalf("healthy candidate: %v", err) + } + if first.candidate == nil || runtimes.currentRevision() != first.candidate.generation { + t.Fatalf("healthy candidate not published: result=%+v revision=%d", first, runtimes.currentRevision()) + } + previous := first.candidate + + broken := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + http.Error(w, "not an MCP response", http.StatusBadGateway) + })) + t.Cleanup(broken.Close) + source.set([]mcp.ServerConfig{{Name: "healthy", URL: healthyURL}, {Name: "broken", URL: broken.URL}}, nil) + failed, err := reconciler.Reconcile(context.Background()) + if err == nil || !failed.stale { + t.Fatalf("failed complete candidate = (%+v, %v), want stale error", failed, err) + } + if reconciler.current != previous || runtimes.currentRevision() != previous.generation { + t.Fatalf("failed candidate replaced previous runtime: current=%p previous=%p revision=%d", reconciler.current, previous, runtimes.currentRevision()) + } + if previous.isClosed() { + t.Fatal("failed candidate closed the previous usable runtime") + } + if atomic.LoadInt32(deletes) == 0 { + t.Fatal("partial healthy connection from failed candidate was not closed") + } + result, err := runtimes.CallTool(context.Background(), "healthy", "echo", []byte(`{"text":"still-live"}`)) + if err != nil || len(result.Content) != 1 || !strings.Contains(result.Content[0].Text, "still-live") { + t.Fatalf("previous runtime unusable after candidate failure: result=%+v err=%v", result, err) + } +} + func configURL(configs []mcp.ServerConfig, name string) string { for _, c := range configs { if c.Name == name { diff --git a/internal/app/mcp_runtime_publication_test.go b/internal/app/mcp_runtime_publication_test.go index af86852475..396c56073d 100644 --- a/internal/app/mcp_runtime_publication_test.go +++ b/internal/app/mcp_runtime_publication_test.go @@ -2,11 +2,15 @@ package app import ( "context" + "net/http" + "net/http/httptest" "strings" "sync/atomic" "testing" "time" + mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" + "github.com/stacklok/mecatl/engine/adapter/memstore" "github.com/stacklok/mecatl/engine/adapter/mockllm" "github.com/stacklok/mecatl/engine/adapter/nofs" @@ -116,12 +120,16 @@ func TestMCPSourceReconciliation_Scenario2_AllOrNothingPublication(t *testing.T) } func TestMCPSourceReconciliation_Scenario2_ProductionEngineRevisionMatrix(t *testing.T) { - provider := mockllm.New() + var requests []port.LLMRequest + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + requests = append(requests, req) + })}, mockllm.TextTurn("done"), mockllm.TextTurn("done"), mockllm.TextTurn("done"), mockllm.TextTurn("done"), mockllm.TextTurn("done")) reg := regForTest(provider, providerOpenAI, "test-model") store := memstore.New() policy := permpolicy.NewPolicy(defaultRules(), nil) runtimes := newMCPRuntimeSet(nil) - first := runtimeTestCandidate(1) + mainManager := connectMainManager(t, "main", newMCPTestServer(t)) + first := &mcpReconcileCandidate{manager: mainManager, generation: 1, tools: toolMetadata(mainManager.Tools())} if !runtimes.publish(nil, first) { t.Fatal("publish first runtime") } @@ -147,7 +155,8 @@ func TestMCPSourceReconciliation_Scenario2_ProductionEngineRevisionMatrix(t *tes } for _, row := range rows { t.Run(row.name, func(t *testing.T) { - result, buildErr := factory(ctx, row.sel, row.specs, row.profile, "", row.mode) + before := len(requests) + result, buildErr := factory(ctx, row.sel, row.specs, row.profile, "/ws", row.mode) if buildErr != nil { t.Fatal(buildErr) } @@ -155,6 +164,36 @@ func TestMCPSourceReconciliation_Scenario2_ProductionEngineRevisionMatrix(t *tes if result.RuntimeRevision != 1 { t.Fatalf("runtime revision = %d, want 1", result.RuntimeRevision) } + ref := session.EnvironmentRef{Kind: session.EnvKindLocal, ID: "/ws", Revision: "in-tree-v1"} + env := memEnvironment("/ws") + if row.profile == server.ProfileNoFS { + ref = session.EnvironmentRef{Kind: session.EnvKindNoFS, ID: "none", Revision: "in-tree-v1"} + env = testEnvironment(nofs.New(), nil) + } + sess := session.New(session.SessionID("matrix-"+row.name), row.mode, ref, session.Limits{}, time.Unix(0, 0)) + if err := sess.BindAuthority(session.Authority{CapabilitySet: governance.CapabilitySet{Tools: []string{"mcp__main__echo", "mcp__client__echo", "Read", "PresentPlan"}, FileSystem: row.profile != server.ProfileNoFS}, Provenance: "test", DefinitionIdentity: "test"}); err != nil { + t.Fatal(err) + } + run := result.Engine.Run(ctx, sess, env, agent.RunRequest{Text: "inspect catalog"}) + for range run.Events() { + } + if len(requests) != before+1 { + t.Fatalf("provider requests = %d, want one production engine request", len(requests)-before) + } + req := requests[before] + if row.mode == session.ModePlan { + if requestHasTool(req, "mcp__main__echo") || !requestHasTool(req, "PresentPlan") { + t.Fatal("plan-mode catalog did not replace mutating MCP availability with PresentPlan") + } + } else if !requestHasTool(req, "mcp__main__echo") { + t.Fatal("production catalog omitted the pinned global MCP tool") + } + if row.profile == server.ProfileNoFS && requestHasTool(req, "Read") { + t.Fatal("no-FS production catalog retained Read") + } + if row.name == "client-mcp" && !requestHasTool(req, "mcp__client__echo") { + t.Fatal("client-MCP production catalog omitted its session-local tool") + } }) } target := session.New("debug-target", session.ModeDefault, session.EnvironmentRef{Kind: session.EnvKindLocal, ID: "/target", Revision: "r1"}, session.Limits{}, time.Unix(0, 0)) @@ -378,6 +417,175 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T teamRuntimes.close() } +func TestMCPSourceReconciliation_Scenario2_OutOfRunReadPinsManager(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + oldManager := connectMainManager(t, "svc", newRuntimeSurfaceServer(t, "old-op", started, release)) + newManager := connectMainManager(t, "svc", newRuntimeSurfaceServer(t, "new-op", nil, nil)) + runtimes := newMCPRuntimeSet(nil) + oldRuntime := &mcpReconcileCandidate{manager: oldManager, generation: 1, tools: toolMetadata(oldManager.Tools())} + if !runtimes.publish(nil, oldRuntime) { + t.Fatal("publish old runtime") + } + svc, err := newTestServerService(server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog()}), + Store: memstore.New(), MCPProvider: runtimes, + }) + if err != nil { + t.Fatal(err) + } + defer svc.Close() + + readDone := make(chan mcp.ResourceContents, 1) + readErr := make(chan error, 1) + go func() { + contents, callErr := svc.ReadMcpResource(context.Background(), "svc", "test://doc") + readDone <- contents + readErr <- callErr + }() + select { + case <-started: + case <-time.After(time.Second): + t.Fatal("out-of-run read did not reach old manager") + } + newRuntime := &mcpReconcileCandidate{manager: newManager, generation: 2, tools: toolMetadata(newManager.Tools())} + if !runtimes.publish(oldRuntime, newRuntime) { + t.Fatal("publish replacement during out-of-run read") + } + if oldRuntime.isClosed() { + t.Fatal("out-of-run operation pin did not retain old manager") + } + close(release) + if contents, callErr := <-readDone, <-readErr; callErr != nil || contents.Text != "old-op-resource-body" { + t.Fatalf("paused out-of-run read = (%+v, %v), want old manager", contents, callErr) + } + if !oldRuntime.isClosed() { + t.Fatal("out-of-run operation pin did not drain after return") + } + contents, err := svc.ReadMcpResource(context.Background(), "svc", "test://doc") + if err != nil || contents.Text != "new-op-resource-body" { + t.Fatalf("next out-of-run read = (%+v, %v), want new manager", contents, err) + } + runtimes.close() +} + +func TestMCPSourceReconciliation_Scenario2_InheritedRootPinCoversResourceAndPromptSurfaces(t *testing.T) { + oldReadStarted := make(chan struct{}) + oldReadRelease := make(chan struct{}) + oldManager := connectMainManager(t, "svc", newRuntimeSurfaceServer(t, "old", oldReadStarted, oldReadRelease)) + newManager := connectMainManager(t, "svc", newRuntimeSurfaceServer(t, "new", nil, nil)) + runtimes := newMCPRuntimeSet(nil) + oldRuntime := &mcpReconcileCandidate{ + manager: oldManager, generation: 1, tools: toolMetadata(oldManager.Tools()), + resources: []mcp.Resource{{Server: "svc", URI: "test://doc", Description: "old-resource"}}, + prompts: []mcp.Prompt{{Server: "svc", Name: "version", Description: "old-prompt"}}, + } + if !runtimes.publish(nil, oldRuntime) { + t.Fatal("publish old runtime") + } + svc, err := newTestServerService(server.Config{ + Engine: agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog()}), + Store: memstore.New(), MCPProvider: runtimes, + }) + if err != nil { + t.Fatal(err) + } + defer svc.Close() + + pinned, releaseRoot, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + readDone := make(chan struct { + contents mcp.ResourceContents + err error + }, 1) + go func() { + contents, readErr := svc.ReadMcpResource(pinned, "svc", "test://doc") + readDone <- struct { + contents mcp.ResourceContents + err error + }{contents, readErr} + }() + select { + case <-oldReadStarted: + case <-time.After(time.Second): + t.Fatal("old resource operation did not reach the manager") + } + + newRuntime := &mcpReconcileCandidate{ + manager: newManager, generation: 2, tools: toolMetadata(newManager.Tools()), + resources: []mcp.Resource{{Server: "svc", URI: "test://doc", Description: "new-resource"}}, + prompts: []mcp.Prompt{{Server: "svc", Name: "version", Description: "new-prompt"}}, + } + if !runtimes.publish(oldRuntime, newRuntime) { + t.Fatal("publish new runtime while old operation is paused") + } + if oldRuntime.isClosed() { + t.Fatal("publication closed the manager used by a paused operation") + } + close(oldReadRelease) + oldRead := <-readDone + if oldRead.err != nil || oldRead.contents.Text != "old-resource-body" { + t.Fatalf("paused read = (%+v, %v), want old runtime", oldRead.contents, oldRead.err) + } + + resources, err := svc.ListMcpResources(pinned, "svc") + if err != nil || len(resources) != 1 || resources[0].Description != "old-resource" { + t.Fatalf("root-pinned resource list = (%+v, %v), want old runtime", resources, err) + } + prompts, err := svc.ListMcpPrompts(pinned, "svc") + if err != nil || len(prompts) != 1 || prompts[0].Description != "old-prompt" { + t.Fatalf("root-pinned prompt list = (%+v, %v), want old runtime", prompts, err) + } + gotPrompt, err := svc.GetMcpPrompt(pinned, "svc", "version", nil) + if err != nil || len(gotPrompt.Messages) != 1 || gotPrompt.Messages[0].Text != "old-prompt-body" { + t.Fatalf("root-pinned prompt get = (%+v, %v), want old runtime", gotPrompt, err) + } + if oldRuntime.isClosed() { + t.Fatal("inherited root pin drained before the root operation ended") + } + releaseRoot() + if !oldRuntime.isClosed() { + t.Fatal("old manager did not close after the inherited root pin drained") + } + + resources, err = svc.ListMcpResources(context.Background(), "svc") + if err != nil || len(resources) != 1 || resources[0].Description != "new-resource" { + t.Fatalf("next resource list = (%+v, %v), want new runtime", resources, err) + } + gotPrompt, err = svc.GetMcpPrompt(context.Background(), "svc", "version", nil) + if err != nil || len(gotPrompt.Messages) != 1 || gotPrompt.Messages[0].Text != "new-prompt-body" { + t.Fatalf("next prompt get = (%+v, %v), want new runtime", gotPrompt, err) + } + runtimes.close() +} + +func newRuntimeSurfaceServer(t *testing.T, version string, readStarted chan<- struct{}, readRelease <-chan struct{}) string { + t.Helper() + srv := mcpsdk.NewServer(&mcpsdk.Implementation{Name: version, Version: "v1"}, nil) + mcpsdk.AddTool(srv, &mcpsdk.Tool{Name: "echo"}, func(context.Context, *mcpsdk.CallToolRequest, mcpEchoArgs) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{}, nil, nil + }) + srv.AddResource(&mcpsdk.Resource{URI: "test://doc", Name: "doc", Description: version + "-resource"}, func(ctx context.Context, req *mcpsdk.ReadResourceRequest) (*mcpsdk.ReadResourceResult, error) { + if readStarted != nil { + close(readStarted) + select { + case <-readRelease: + case <-ctx.Done(): + return nil, ctx.Err() + } + } + return &mcpsdk.ReadResourceResult{Contents: []*mcpsdk.ResourceContents{{URI: req.Params.URI, Text: version + "-resource-body"}}}, nil + }) + srv.AddPrompt(&mcpsdk.Prompt{Name: "version", Description: version + "-prompt"}, func(context.Context, *mcpsdk.GetPromptRequest) (*mcpsdk.GetPromptResult, error) { + return &mcpsdk.GetPromptResult{Messages: []*mcpsdk.PromptMessage{{Role: "user", Content: &mcpsdk.TextContent{Text: version + "-prompt-body"}}}}, nil + }) + httpServer := httptest.NewServer(mcpsdk.NewStreamableHTTPHandler(func(*http.Request) *mcpsdk.Server { return srv }, nil)) + t.Cleanup(httpServer.Close) + return httpServer.URL +} + func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *testing.T) { const ( name = "mcp__svc__echo" @@ -407,7 +615,7 @@ func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *te mockllm.TextTurn("removed observed"), mockllm.ToolCallTurn(session.NewToolCall("unknown", "mcp__svc__never-granted", []byte(`{}`))), mockllm.TextTurn("unknown observed"), - mockllm.ToolCallTurn(session.NewToolCall("reappeared", name, []byte(`{"text":"again"}`))), + mockllm.ToolCallTurn(session.NewToolCall("reappeared", name, []byte(`{"text":7}`))), mockllm.TextTurn("reappeared observed"), ) reg := regForTest(provider, providerOpenAI, "test-model") @@ -476,7 +684,7 @@ func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *te if err := sess.Reopen(); err != nil { t.Fatal(err) } - secondManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "second")) + secondManager := connectMainManager(t, "svc", newMCPContractDriftServer(t)) second := &mcpReconcileCandidate{manager: secondManager, generation: 3, tools: toolMetadata(secondManager.Tools())} if !runtimes.publish(empty, second) { t.Fatal("publish exact-name reappearance") @@ -492,12 +700,49 @@ func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *te if !reappearedAdvertised { t.Fatal("reappeared exact name was not restored to model specs") } + var driftedMeta *mcpToolMeta + for i := range second.tools { + if second.tools[i].Name == name { + driftedMeta = &second.tools[i] + } + } + if driftedMeta == nil || !driftedMeta.ReadOnly || driftedMeta.Description != "drifted contract" || !strings.Contains(driftedMeta.Schema, "integer") { + t.Fatalf("same-name schema/read-only drift was not published: %+v", driftedMeta) + } + for _, req := range requests[beforeReappearance:] { + if requestHasTool(req, "mcp__svc__fresh") { + t.Fatal("automatic publication advertised a newly named tool outside durable authority") + } + for _, spec := range req.Tools { + if spec.Name == name && (spec.Description != "drifted contract" || !strings.Contains(string(spec.Schema), "integer")) { + t.Fatalf("model saw stale same-name contract after publication: %+v", spec) + } + } + } if got := sess.Authority.CapabilitySet.Tools; len(got) != 1 || got[0] != name { t.Fatalf("same-name endpoint drift changed durable grant: %v", got) } runtimes.close() } +func newMCPContractDriftServer(t *testing.T) string { + t.Helper() + srv := mcpsdk.NewServer(&mcpsdk.Implementation{Name: "drift", Version: "v2"}, nil) + mcpsdk.AddTool(srv, &mcpsdk.Tool{ + Name: "echo", Description: "drifted contract", + InputSchema: map[string]any{"type": "object", "properties": map[string]any{"text": map[string]any{"type": "integer"}}}, + Annotations: &mcpsdk.ToolAnnotations{ReadOnlyHint: true}, + }, func(_ context.Context, _ *mcpsdk.CallToolRequest, _ any) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{Content: []mcpsdk.Content{&mcpsdk.TextContent{Text: "second contract"}}}, nil, nil + }) + mcpsdk.AddTool(srv, &mcpsdk.Tool{Name: "fresh", Description: "new ungranted name"}, func(context.Context, *mcpsdk.CallToolRequest, struct{}) (*mcpsdk.CallToolResult, any, error) { + return &mcpsdk.CallToolResult{}, nil, nil + }) + httpServer := httptest.NewServer(mcpsdk.NewStreamableHTTPHandler(func(*http.Request) *mcpsdk.Server { return srv }, nil)) + t.Cleanup(httpServer.Close) + return httpServer.URL +} + func requestHasTool(req port.LLMRequest, name string) bool { for _, spec := range req.Tools { if spec.Name == name { From e30b852fa55cfd33d8fb447d42c1b307bc52e98e Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 01:43:09 +0200 Subject: [PATCH 09/14] test(mcp): cover runtime operation entry points Co-Authored-By: mecatl --- .../app/mcp_runtime_entry_consistency_test.go | 543 ++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 internal/app/mcp_runtime_entry_consistency_test.go diff --git a/internal/app/mcp_runtime_entry_consistency_test.go b/internal/app/mcp_runtime_entry_consistency_test.go new file mode 100644 index 0000000000..79b85ba899 --- /dev/null +++ b/internal/app/mcp_runtime_entry_consistency_test.go @@ -0,0 +1,543 @@ +package app + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "sync" + "testing" + "time" + + mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp" + + "github.com/stacklok/mecatl/engine/adapter/memstore" + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/adapter/permpolicy" + "github.com/stacklok/mecatl/engine/agent" + "github.com/stacklok/mecatl/engine/governance" + "github.com/stacklok/mecatl/engine/port" + "github.com/stacklok/mecatl/engine/prompt" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/agents" + "github.com/stacklok/mecatl/internal/adapter/hookexec" + "github.com/stacklok/mecatl/internal/adapter/mcp" + "github.com/stacklok/mecatl/internal/adapter/server" +) + +const entryRuntimeTool = "mcp__svc__echo" + +type oldEntryArgs struct { + Text string `json:"text"` + OldOnly string `json:"old_only,omitempty"` +} + +type newEntryArgs struct { + Text string `json:"text"` + NewOnly string `json:"new_only,omitempty"` +} + +func newEntryRuntimeServer(t *testing.T, version string, started chan<- struct{}, release <-chan struct{}) string { + t.Helper() + srv := mcpsdk.NewServer(&mcpsdk.Implementation{Name: version, Version: "v1"}, nil) + var once sync.Once + wait := func(ctx context.Context) error { + if started == nil { + return nil + } + once.Do(func() { close(started) }) + select { + case <-release: + return nil + case <-ctx.Done(): + return ctx.Err() + } + } + if version == "old" { + mcpsdk.AddTool(srv, &mcpsdk.Tool{Name: "echo", Description: "old runtime schema"}, func(ctx context.Context, _ *mcpsdk.CallToolRequest, in oldEntryArgs) (*mcpsdk.CallToolResult, any, error) { + if err := wait(ctx); err != nil { + return nil, nil, err + } + return &mcpsdk.CallToolResult{Content: []mcpsdk.Content{&mcpsdk.TextContent{Text: "old:" + in.Text}}}, nil, nil + }) + } else { + mcpsdk.AddTool(srv, &mcpsdk.Tool{Name: "echo", Description: "new runtime schema"}, func(ctx context.Context, _ *mcpsdk.CallToolRequest, in newEntryArgs) (*mcpsdk.CallToolResult, any, error) { + if err := wait(ctx); err != nil { + return nil, nil, err + } + return &mcpsdk.CallToolResult{Content: []mcpsdk.Content{&mcpsdk.TextContent{Text: "new:" + in.Text}}}, nil, nil + }) + } + srv.AddPrompt(&mcpsdk.Prompt{Name: "version", Description: version + " runtime prompt"}, func(ctx context.Context, _ *mcpsdk.GetPromptRequest) (*mcpsdk.GetPromptResult, error) { + if err := wait(ctx); err != nil { + return nil, err + } + return &mcpsdk.GetPromptResult{Messages: []*mcpsdk.PromptMessage{{Role: "user", Content: &mcpsdk.TextContent{Text: version + " prompt body"}}}}, nil + }) + httpServer := httptest.NewServer(mcpsdk.NewStreamableHTTPHandler(func(*http.Request) *mcpsdk.Server { return srv }, nil)) + t.Cleanup(httpServer.Close) + return httpServer.URL +} + +type entryRuntimeHarness struct { + t *testing.T + ctx context.Context + store *memstore.Store + runtimes *mcpRuntimeSet + old *mcpReconcileCandidate + new *mcpReconcileCandidate + factory server.SessionEngineFactory + shared *agent.Engine + cfg Config +} + +func newEntryRuntimeHarness(t *testing.T, provider port.LLMProvider, oldStarted chan<- struct{}, oldRelease <-chan struct{}, configure func(*Config)) *entryRuntimeHarness { + t.Helper() + oldManager := connectMainManager(t, "svc", newEntryRuntimeServer(t, "old", oldStarted, oldRelease)) + newManager := connectMainManager(t, "svc", newEntryRuntimeServer(t, "new", nil, nil)) + runtimes := newMCPRuntimeSet(nil) + oldRuntime := &mcpReconcileCandidate{manager: oldManager, generation: 1, tools: toolMetadata(oldManager.Tools()), prompts: []mcp.Prompt{{Server: "svc", Name: "version", Description: "old runtime prompt"}}} + newRuntime := &mcpReconcileCandidate{manager: newManager, generation: 2, tools: toolMetadata(newManager.Tools()), prompts: []mcp.Prompt{{Server: "svc", Name: "version", Description: "new runtime prompt"}}} + if !runtimes.publish(nil, oldRuntime) { + t.Fatal("publish old runtime") + } + store := memstore.New() + cfg := Config{Model: "test-model", Workspace: t.TempDir(), MCPPrompts: true} + if configure != nil { + configure(&cfg) + } + var err error + cfg.authorityEvaluator, _, err = selectAuthorityEvaluator("local", "") + if err != nil { + t.Fatal(err) + } + reg := regForTest(provider, providerOpenAI, cfg.Model) + policy := permpolicy.NewPolicy(defaultRules(), nil) + assets := catalogAssets{mcpRuntimes: runtimes, agentReg: agents.NewRegistry(nil)} + factory := sessionEngineFactory(cfg, reg, provider, store, policy, hookexec.New(nil), runtimes, prompt.RootAssembler{}, assets, nil) + pinned, release, err := runtimes.pin(context.Background()) + if err != nil { + t.Fatal(err) + } + sharedResult, err := factory(pinned, server.ProviderSelector{}, nil, server.ProfileDefault, cfg.Workspace, session.ModeDefault) + release() + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + _ = sharedResult.Close() + runtimes.close() + }) + return &entryRuntimeHarness{t: t, ctx: context.Background(), store: store, runtimes: runtimes, old: oldRuntime, new: newRuntime, factory: factory, shared: sharedResult.Engine, cfg: cfg} +} + +func (h *entryRuntimeHarness) service() *server.Service { + h.t.Helper() + names := []string{entryRuntimeTool, "Parallel", "Team"} + for name := range agent.MemberToolNames() { + names = append(names, name) + } + svc, err := newTestServerService(server.Config{ + Engine: h.shared, Store: h.store, SessionEngine: h.factory, + SharedEngineRoot: h.cfg.Workspace, SharedEngineRevision: 1, + OperationPin: h.runtimes.pin, OperationRevision: mcpRuntimeRevision, MCPProvider: h.runtimes, + RootAuthority: func(session.SessionKind) session.Authority { + return session.Authority{CapabilitySet: governance.CapabilitySet{Tools: names, FileSystem: true, RemainingDelegationDepth: 2}, Provenance: "test", DefinitionIdentity: "test"} + }, + }) + if err != nil { + h.t.Fatal(err) + } + h.t.Cleanup(svc.Close) + return svc +} + +func publishEntryRuntime(t *testing.T, h *entryRuntimeHarness) { + t.Helper() + if !h.runtimes.publish(h.old, h.new) { + t.Fatal("publish new runtime") + } +} + +func drainEntryRun(t *testing.T, svc *server.Service, id session.SessionID, run *agent.Run) []session.Event { + t.Helper() + var events []session.Event + for ev := range run.Events() { + events = append(events, ev) + if ev.Type == session.EvPermissionAsk && ev.Ask != nil { + run.Approve(ev.Ask.AskID, session.VerdictAllowOnce) + } + } + svc.FinishRun(id, run) + return events +} + +func parallelChildID(t *testing.T, events []session.Event) session.SessionID { + t.Helper() + for _, ev := range events { + if ev.Type == session.EvParallelBranch && ev.Parallel != nil && ev.Parallel.ChildID != "" { + return session.SessionID(ev.Parallel.ChildID) + } + } + t.Fatal("run omitted Parallel branch identity") + return "" +} + +func teamMemberSessionID(t *testing.T, events []session.Event) session.SessionID { + t.Helper() + for _, ev := range events { + if ev.Type == session.EvTeamMember && ev.Team != nil && ev.Team.MemberSessionID != "" { + return session.SessionID(ev.Team.MemberSessionID) + } + } + t.Fatal("run omitted Team member identity") + return "" +} + +func assertEntrySchema(t *testing.T, req port.LLMRequest, marker string) { + t.Helper() + for _, spec := range req.Tools { + if spec.Name == entryRuntimeTool { + if !strings.Contains(string(spec.Schema), marker) { + t.Fatalf("%s schema = %s, want marker %q", spec.Name, spec.Schema, marker) + } + return + } + } + t.Fatalf("request omitted %s", entryRuntimeTool) +} + +func TestMCPRuntimeConsistency_FailedStepRetryPinsOperationEntry(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + var once sync.Once + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + once.Do(func() { + assertEntrySchema(t, req, "old_only") + close(started) + <-release + }) + })}, + mockllm.ToolCallTurn(session.NewToolCall("retry-old", entryRuntimeTool, json.RawMessage(`{"text":"retry"}`))), + mockllm.TextTurn("retry complete"), + mockllm.ToolCallTurn(session.NewToolCall("retry-new", entryRuntimeTool, json.RawMessage(`{"text":"next"}`))), + mockllm.TextTurn("next complete"), + ) + h := newEntryRuntimeHarness(t, provider, nil, nil, nil) + svc := h.service() + sess, err := svc.CreateSession(h.ctx, session.ModeDefault, session.Limits{MaxTurns: 8}) + if err != nil { + t.Fatal(err) + } + if err := sess.RecordUserPrompt("original", nil); err != nil { + t.Fatal(err) + } + if err := sess.BeginTurn(); err != nil { + t.Fatal(err) + } + if err := sess.Fail(); err != nil { + t.Fatal(err) + } + if err := sess.RecordFailureMetadata(session.RetryDispositionRetryable, session.StreamProgressPrecommit); err != nil { + t.Fatal(err) + } + if err := h.store.Save(h.ctx, sess); err != nil { + t.Fatal(err) + } + runCh := make(chan *agent.Run, 1) + errCh := make(chan error, 1) + go func() { + run, retryErr := svc.RetryFailedRun(h.ctx, sess.ID) + runCh <- run + errCh <- retryErr + }() + <-started + publishEntryRuntime(t, h) + if h.old.isClosed() { + t.Fatal("failed-step retry released its old operation pin before model dispatch") + } + close(release) + run, err := <-runCh, <-errCh + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, run) + got, err := h.store.Load(h.ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + if result := latestToolResult(got, "retry-old"); !strings.Contains(result, "old:retry") { + t.Fatalf("retry tool result = %q, want old runtime", result) + } + next, err := svc.StartRun(h.ctx, sess.ID, "next operation") + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, next) + got, _ = h.store.Load(h.ctx, sess.ID) + if result := latestToolResult(got, "retry-new"); !strings.Contains(result, "new:next") { + t.Fatalf("next tool result = %q, want new runtime", result) + } +} + +func TestMCPRuntimeConsistency_RestoredAwaitingApprovalPinsOperationEntry(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("await-old", entryRuntimeTool, json.RawMessage(`{"text":"approved"}`))), + mockllm.TextTurn("approved complete"), + mockllm.ToolCallTurn(session.NewToolCall("await-new", entryRuntimeTool, json.RawMessage(`{"text":"next"}`))), + mockllm.TextTurn("next complete"), + ) + h := newEntryRuntimeHarness(t, provider, started, release, nil) + svc1 := h.service() + sess, err := svc1.CreateSession(h.ctx, session.ModeDefault, session.Limits{MaxTurns: 8}) + if err != nil { + t.Fatal(err) + } + run1, err := svc1.StartRun(h.ctx, sess.ID, "call the service") + if err != nil { + t.Fatal(err) + } + var askID string + for ev := range run1.Events() { + if ev.Type == session.EvPermissionAsk && ev.Ask != nil { + askID = ev.Ask.AskID + svc1.Persist(h.ctx, sess.ID) + break + } + } + if askID == "" { + t.Fatal("MCP call did not park awaiting approval") + } + svc1.FinishRun(sess.ID, run1) + svc1.Close() + svc2 := h.service() + runCh := make(chan *agent.Run, 1) + errCh := make(chan error, 1) + go func() { + run, approveErr := svc2.ApproveRun(h.ctx, sess.ID, askID, session.VerdictAllowOnce, "") + runCh <- run + errCh <- approveErr + }() + select { + case <-started: + case <-time.After(time.Second): + t.Fatal("restored approval did not execute the old manager") + } + publishEntryRuntime(t, h) + if h.old.isClosed() { + t.Fatal("restored approval released its operation pin during the pending call") + } + close(release) + run2, err := <-runCh, <-errCh + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc2, sess.ID, run2) + got, _ := h.store.Load(h.ctx, sess.ID) + if result := latestToolResult(got, "await-old"); !strings.Contains(result, "old:approved") { + t.Fatalf("restored approval result = %q, want old runtime", result) + } + next, err := svc2.StartRun(h.ctx, sess.ID, "next operation") + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc2, sess.ID, next) + got, _ = h.store.Load(h.ctx, sess.ID) + if result := latestToolResult(got, "await-new"); !strings.Contains(result, "new:next") { + t.Fatalf("next approval-path result = %q, want new runtime", result) + } +} + +func TestMCPRuntimeConsistency_ParallelToolInheritsRootOperationPin(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + var once sync.Once + nextOperation := make(chan struct{}) + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + if requestHasTool(req, "Parallel") { + marker := "old_only" + select { + case <-nextOperation: + marker = "new_only" + default: + } + assertEntrySchema(t, req, marker) + return + } + once.Do(func() { + close(started) + <-release + }) + })}, + mockllm.ToolCallTurn(session.NewToolCall("parallel-old", "Parallel", json.RawMessage(`{"tasks":["inspect the workspace"],"join":"all"}`))), + mockllm.TextTurn("old branch complete"), mockllm.TextTurn("old parent complete"), + mockllm.ToolCallTurn(session.NewToolCall("parallel-new", entryRuntimeTool, json.RawMessage(`{"text":"parallel"}`))), + mockllm.TextTurn("new parent complete"), + ) + h := newEntryRuntimeHarness(t, provider, nil, nil, func(cfg *Config) { cfg.EnableParallel = true }) + svc := h.service() + sess, err := svc.CreateSession(h.ctx, session.ModeDefault, session.Limits{MaxTurns: 12}) + if err != nil { + t.Fatal(err) + } + run, err := svc.StartRun(h.ctx, sess.ID, "parallel old") + if err != nil { + t.Fatal(err) + } + eventsCh := make(chan []session.Event, 1) + go func() { eventsCh <- drainEntryRun(t, svc, sess.ID, run) }() + <-started + publishEntryRuntime(t, h) + if h.old.isClosed() { + t.Fatal("Parallel root operation did not retain the old runtime") + } + close(release) + events := <-eventsCh + if _, err := h.store.Load(h.ctx, parallelChildID(t, events)); err != nil { + t.Fatal(err) + } + close(nextOperation) + next, err := svc.StartRun(h.ctx, sess.ID, "use the current MCP runtime") + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, next) + got, err := h.store.Load(h.ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + if result := latestToolResult(got, "parallel-new"); !strings.Contains(result, "new:parallel") { + t.Fatalf("operation after Parallel result = %q, want new runtime", result) + } +} + +func TestMCPRuntimeConsistency_InLoopTeamToolInheritsRootOperationPin(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + var once sync.Once + nextOperation := make(chan struct{}) + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + if requestHasTool(req, "Team") { + marker := "old_only" + select { + case <-nextOperation: + marker = "new_only" + default: + } + assertEntrySchema(t, req, marker) + return + } + once.Do(func() { + close(started) + <-release + }) + })}, + mockllm.ToolCallTurn(session.NewToolCall("team-old", "Team", json.RawMessage(`{"goal":"inspect once","members":[{"name":"lead","role":"inspect the workspace"}]}`))), + mockllm.TextTurn("old member complete"), mockllm.TextTurn("old team report"), mockllm.TextTurn("old parent complete"), + mockllm.ToolCallTurn(session.NewToolCall("team-new", entryRuntimeTool, json.RawMessage(`{"text":"team"}`))), + mockllm.TextTurn("new parent complete"), + ) + h := newEntryRuntimeHarness(t, provider, nil, nil, func(cfg *Config) { cfg.EnableTeams = true }) + svc := h.service() + sess, err := svc.CreateSession(h.ctx, session.ModeDefault, session.Limits{MaxTurns: 14}) + if err != nil { + t.Fatal(err) + } + run, err := svc.StartRun(h.ctx, sess.ID, "team old") + if err != nil { + t.Fatal(err) + } + eventsCh := make(chan []session.Event, 1) + go func() { eventsCh <- drainEntryRun(t, svc, sess.ID, run) }() + <-started + publishEntryRuntime(t, h) + if h.old.isClosed() { + t.Fatal("in-loop Team root operation did not retain the old runtime") + } + close(release) + events := <-eventsCh + if _, err := h.store.Load(h.ctx, teamMemberSessionID(t, events)); err != nil { + t.Fatal(err) + } + close(nextOperation) + next, err := svc.StartRun(h.ctx, sess.ID, "use the current MCP runtime") + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, next) + got, err := h.store.Load(h.ctx, sess.ID) + if err != nil { + t.Fatal(err) + } + if result := latestToolResult(got, "team-new"); !strings.Contains(result, "new:team") { + t.Fatalf("operation after in-loop Team result = %q, want new runtime", result) + } +} + +func TestMCPRuntimeConsistency_InRunPromptExpansionUsesOperationPin(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + var requests []port.LLMRequest + var mu sync.Mutex + provider := mockllm.NewWith([]mockllm.Option{mockllm.WithRequestObserver(func(req port.LLMRequest) { + mu.Lock() + requests = append(requests, req) + mu.Unlock() + })}, mockllm.TextTurn("old expansion complete"), mockllm.TextTurn("new expansion complete")) + h := newEntryRuntimeHarness(t, provider, started, release, nil) + svc := h.service() + sess, err := svc.CreateSession(h.ctx, session.ModeDefault, session.Limits{MaxTurns: 4}) + if err != nil { + t.Fatal(err) + } + runCh := make(chan *agent.Run, 1) + errCh := make(chan error, 1) + go func() { + run, runErr := svc.StartRun(h.ctx, sess.ID, "/mcp__svc__version") + runCh <- run + errCh <- runErr + }() + select { + case <-started: + case <-time.After(time.Second): + t.Fatal("in-run prompt expansion did not reach the old manager") + } + publishEntryRuntime(t, h) + if h.old.isClosed() { + t.Fatal("prompt expansion released the root operation pin during GetPrompt") + } + close(release) + run, err := <-runCh, <-errCh + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, run) + next, err := svc.StartRun(h.ctx, sess.ID, "/mcp__svc__version") + if err != nil { + t.Fatal(err) + } + drainEntryRun(t, svc, sess.ID, next) + mu.Lock() + defer mu.Unlock() + if len(requests) != 2 { + t.Fatalf("provider requests = %d, want 2", len(requests)) + } + if !requestContainsText(requests[0], "old prompt body") { + t.Fatalf("active operation prompt = %+v, want old expansion", requests[0].Messages) + } + if !requestContainsText(requests[1], "new prompt body") { + t.Fatalf("next operation prompt = %+v, want new expansion", requests[1].Messages) + } +} + +func requestContainsText(req port.LLMRequest, want string) bool { + for _, msg := range req.Messages { + if strings.Contains(msg.Text, want) { + return true + } + } + return false +} From 9594dd7c22af7b635897e119d0e09fba193dfc35 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 02:09:06 +0200 Subject: [PATCH 10/14] test(mcp): strengthen explicit refresh acceptance Co-Authored-By: OpenAI Codex --- internal/adapter/server/mcp_refresh_test.go | 114 ++++++++++++++++++ .../server/mcp_refresh_transport_test.go | 52 +++++++- internal/app/mcp_refresh_acceptance_test.go | 110 +++++++++++++++++ 3 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 internal/app/mcp_refresh_acceptance_test.go diff --git a/internal/adapter/server/mcp_refresh_test.go b/internal/adapter/server/mcp_refresh_test.go index 68bfc3f9fa..3e262a1ad9 100644 --- a/internal/adapter/server/mcp_refresh_test.go +++ b/internal/adapter/server/mcp_refresh_test.go @@ -3,6 +3,8 @@ package server_test import ( "context" "errors" + "fmt" + "strings" "sync" "testing" "time" @@ -15,6 +17,7 @@ import ( "github.com/stacklok/mecatl/engine/port" "github.com/stacklok/mecatl/engine/session" "github.com/stacklok/mecatl/engine/tool" + "github.com/stacklok/mecatl/internal/adapter/mcp" "github.com/stacklok/mecatl/internal/adapter/server" ) @@ -240,6 +243,50 @@ func TestMCPSourceReconciliation_Scenario4_ServiceRefreshMutationMatrix(t *testi } }) + t.Run("no-fs-and-unrelated-authority-preserved", func(t *testing.T) { + store := &refreshStore{Store: memstore.New()} + eng := agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), Model: "test"}) + svc, err := newPlacementTestService(server.Config{ + Engine: eng, Store: store, OwnershipEnforced: true, + SessionEngine: func(context.Context, server.ProviderSelector, []mcp.ServerConfig, server.SessionProfile, string, session.PermissionMode) (server.SessionEngineResult, error) { + return server.SessionEngineResult{Engine: eng}, nil + }, + RootAuthority: func(session.SessionKind) session.Authority { + return session.Authority{CapabilitySet: governance.CapabilitySet{ + Tools: []string{"Read", "mcp__client__keep"}, RemainingDelegationDepth: 3, + }, Provenance: "test"} + }, + MCPRefresh: func(context.Context) (server.MCPRefreshSnapshot, error) { + return server.MCPRefreshSnapshot{Revision: 8, ToolNames: []string{"mcp__direct__new"}}, nil + }, + }) + if err != nil { + t.Fatalf("NewService: %v", err) + } + sess, err := svc.CreateSessionWithProfile(ownerCtx, session.ModeDefault, session.Limits{}, server.ProviderSelector{}, server.ProfileNoFS) + if err != nil { + t.Fatalf("CreateSessionWithProfile: %v", err) + } + before, _ := sess.BoundAuthority() + store.mu.Lock() + store.saves = 0 + store.mu.Unlock() + if _, err := svc.RefreshMcpSources(ownerCtx, sess.ID); err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + afterSession, err := store.Store.Load(context.Background(), sess.ID) + if err != nil { + t.Fatalf("Load: %v", err) + } + after, _ := afterSession.BoundAuthority() + if after.CapabilitySet.FileSystem || after.CapabilitySet.DirectWrite || after.CapabilitySet.RemainingDelegationDepth != before.CapabilitySet.RemainingDelegationDepth { + t.Fatalf("unrelated no-FS authority changed: before=%+v after=%+v", before, after) + } + if !after.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__client__keep", "mcp__direct__new"}}) { + t.Fatalf("client/unrelated authority not preserved: %+v", after) + } + }) + t.Run("ineligible-state-and-taxonomy", func(t *testing.T) { cases := []struct { name string @@ -311,6 +358,73 @@ func TestMCPSourceReconciliation_Scenario4_ServiceRefreshMutationMatrix(t *testi } }) + t.Run("concurrent-callers-fresh-load-under-run-entry-exclusion", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + const callers = 8 + start := make(chan struct{}) + errs := make(chan error, callers) + for range callers { + go func() { + <-start + _, err := svc.RefreshMcpSources(ownerCtx, id) + errs <- err + }() + } + close(start) + for range callers { + if err := <-errs; err != nil { + t.Fatalf("concurrent refresh: %v", err) + } + } + if store.saveCount() != 1 { + t.Fatalf("concurrent stable union saved %d times, want 1", store.saveCount()) + } + }) + + t.Run("active-run-excluded-at-local-linearization-point", func(t *testing.T) { + svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) + run, err := svc.StartRun(ownerCtx, id, "keep registered") + if err != nil { + t.Fatalf("StartRun: %v", err) + } + if _, err := svc.RefreshMcpSources(ownerCtx, id); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("refresh during registered run err=%v", err) + } + for range run.Events() { + } + svc.FinishRun(id, run) + if store.saveCount() != 0 { + t.Fatalf("refresh during run saved %d times", store.saveCount()) + } + }) + + t.Run("actual-service-grant-count-and-name-byte-bounds", func(t *testing.T) { + t.Run("union-count-bound", func(t *testing.T) { + names := make([]string, 1_025) + for i := range names { + names[i] = fmt.Sprintf("mcp__bounded__tool_%04d", i) + } + svc, store, id := newFixture(t, names, nil, false, nil) + if _, err := svc.RefreshMcpSources(ownerCtx, id); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("err=%v want ErrFailedPrecondition", err) + } + if store.saveCount() != 0 { + t.Fatalf("over-bound union saved %d times", store.saveCount()) + } + }) + + t.Run("tool-name-byte-bound", func(t *testing.T) { + name := strings.Repeat("x", 257) + svc, store, id := newFixture(t, []string{name}, nil, false, nil) + if _, err := svc.RefreshMcpSources(ownerCtx, id); !errors.Is(err, server.ErrFailedPrecondition) { + t.Fatalf("err=%v want ErrFailedPrecondition", err) + } + if store.saveCount() != 0 { + t.Fatalf("invalid-name union saved %d times", store.saveCount()) + } + }) + }) + t.Run("owner-concealment", func(t *testing.T) { svc, store, id := newFixture(t, []string{"mcp__new__call"}, nil, false, nil) _, err := svc.RefreshMcpSources(foreignCtx, id) diff --git a/internal/adapter/server/mcp_refresh_transport_test.go b/internal/adapter/server/mcp_refresh_transport_test.go index 8c726eaa3f..94d6412b21 100644 --- a/internal/adapter/server/mcp_refresh_transport_test.go +++ b/internal/adapter/server/mcp_refresh_transport_test.go @@ -27,15 +27,25 @@ func TestMCPSourceReconciliation_Scenario4_DirectTransportStatusMatrix(t *testin Revision: 41, Stale: true, Reconciling: true, } eng := agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), Model: "test"}) + store := memstore.New() svc, err := newPlacementTestService(server.Config{ - Engine: eng, Store: memstore.New(), + Engine: eng, Store: store, RootAuthority: func(session.SessionKind) session.Authority { return session.Authority{CapabilitySet: governance.CapabilitySet{Tools: []string{"Read"}}, Provenance: "test"} }, MCPRefresh: func(context.Context) (server.MCPRefreshSnapshot, error) { refreshCalls++ statusSnapshot.Revision = 99 // a coalesced successor may publish before delivery - return server.MCPRefreshSnapshot{Revision: 42, Changed: refreshCalls == 1, ToolNames: []string{"Read"}}, nil + switch refreshCalls { + case 1: + return server.MCPRefreshSnapshot{Revision: 42, Changed: true, ToolNames: []string{"Read"}}, nil + case 3: + return server.MCPRefreshSnapshot{Revision: 43, ToolNames: []string{"Read", "mcp__new__authority"}}, nil + case 4: + return server.MCPRefreshSnapshot{Revision: 44, Changed: true, ToolNames: []string{"Read", "mcp__new__both"}}, nil + default: + return server.MCPRefreshSnapshot{Revision: 42, ToolNames: []string{"Read"}}, nil + } }, MCPStatus: func() server.MCPSourceStatus { return statusSnapshot }, }) @@ -90,6 +100,44 @@ func TestMCPSourceReconciliation_Scenario4_DirectTransportStatusMatrix(t *testin t.Fatalf("second no-op refresh revision=%d changed=%v", body.GetRevision(), body.GetChanged()) } + // Authority-only and runtime+authority changes both report changed through the + // actual routers, while retaining the request-local pinned revision even though + // the cached status has already advanced to 99. + authorityOnly, err := client.RefreshMcpSources(context.Background(), &mecatlv1.RefreshMcpSourcesRequest{SessionId: string(sess.ID)}) + if err != nil { + t.Fatalf("authority-only gRPC refresh: %v", err) + } + if authorityOnly.GetRevision() != 43 || !authorityOnly.GetChanged() { + t.Fatalf("authority-only response=%+v", authorityOnly) + } + bothReq, err := http.NewRequest(http.MethodPost, httpSrv.URL+"/v1/sessions/"+string(sess.ID)+"/mcp-refresh", nil) + if err != nil { + t.Fatal(err) + } + bothResp, err := httpSrv.Client().Do(bothReq) + if err != nil { + t.Fatalf("both-change HTTP refresh: %v", err) + } + defer bothResp.Body.Close() + if bothResp.StatusCode != http.StatusOK { + t.Fatalf("both-change status=%d", bothResp.StatusCode) + } + var bothBody mecatlv1.RefreshMcpSourcesResponse + if err := json.NewDecoder(bothResp.Body).Decode(&bothBody); err != nil { + t.Fatalf("decode both-change response: %v", err) + } + if bothBody.GetRevision() != 44 || !bothBody.GetChanged() { + t.Fatalf("both-change revision=%d changed=%v", bothBody.GetRevision(), bothBody.GetChanged()) + } + persisted, err := store.Load(context.Background(), sess.ID) + if err != nil { + t.Fatalf("load refreshed session: %v", err) + } + authority, _ := persisted.BoundAuthority() + if !authority.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__new__authority", "mcp__new__both"}}) { + t.Fatalf("transport refresh did not preserve both grants: %+v", authority) + } + badReq, err := http.NewRequest(http.MethodPost, httpSrv.URL+"/v1/sessions/"+string(sess.ID)+"/mcp-refresh", bytes.NewBufferString(`{"ignored":true}`)) if err != nil { t.Fatal(err) diff --git a/internal/app/mcp_refresh_acceptance_test.go b/internal/app/mcp_refresh_acceptance_test.go new file mode 100644 index 0000000000..4e8a8b6439 --- /dev/null +++ b/internal/app/mcp_refresh_acceptance_test.go @@ -0,0 +1,110 @@ +package app + +import ( + "context" + "path/filepath" + "slices" + "strings" + "testing" + + "github.com/stacklok/mecatl/engine/adapter/mockllm" + "github.com/stacklok/mecatl/engine/session" + "github.com/stacklok/mecatl/internal/adapter/mcp" +) + +// TestMCPSourceReconciliation_Scenario4_RealBuildPublicationAndExplicitGrant +// covers the production Build-owned reconciler and Service grant path together. +// The session predates the published MCP runtime, so publication alone must not +// widen its durable authority; explicit refresh then makes the same live tool +// executable without rebuilding the process. +func TestMCPSourceReconciliation_Scenario4_RealBuildPublicationAndExplicitGrant(t *testing.T) { + ctx := session.WithPrincipal(context.Background(), &session.Principal{Issuer: "test", Subject: "owner", GrantType: session.GrantTypeUser}) + workspace := t.TempDir() + storeDir := filepath.Join(t.TempDir(), "sessions") + + before, err := buildIsolated(t, ctx, Config{ + Workspace: workspace, StoreDir: storeDir, UseMock: true, NoSoul: true, + }) + if err != nil { + t.Fatalf("Build before MCP publication: %v", err) + } + persisted, err := before.Service.CreateSession(ctx, session.ModeDefault, defaultLimits()) + if err != nil { + before.Close() + t.Fatalf("CreateSession: %v", err) + } + before.Close() + + provider := mockllm.New( + mockllm.ToolCallTurn(session.NewToolCall("before-refresh", "mcp__live__echo", []byte(`{"text":"before"}`))), + mockllm.TextTurn("before complete"), + mockllm.ToolCallTurn(session.NewToolCall("after-refresh", "mcp__live__echo", []byte(`{"text":"after"}`))), + mockllm.TextTurn("after complete"), + ) + built, err := buildIsolated(t, ctx, Config{ + Workspace: workspace, StoreDir: storeDir, MockProvider: provider, NoSoul: true, + AllowAllTools: true, + MCPServers: []mcp.ServerConfig{{Name: "live", URL: newMCPTestServer(t)}}, + }) + if err != nil { + t.Fatalf("Build with published MCP runtime: %v", err) + } + defer built.Close() + + run, err := built.Service.StartRun(ctx, persisted.ID, "call newly published tool before grant") + if err != nil { + t.Fatalf("StartRun before refresh: %v", err) + } + if got := drainRun(run); got != "before complete" { + t.Fatalf("before-refresh final text = %q", got) + } + built.Service.FinishRun(persisted.ID, run) + beforeRefresh, err := built.Service.GetSession(ctx, persisted.ID) + if err != nil { + t.Fatalf("GetSession before refresh: %v", err) + } + assertMCPRefreshToolResult(t, beforeRefresh, "before-refresh", "absent from the capability set") + + result, err := built.Service.RefreshMcpSources(ctx, persisted.ID) + if err != nil { + t.Fatalf("RefreshMcpSources: %v", err) + } + if result.Revision == 0 || !result.Changed { + t.Fatalf("refresh result = %+v, want pinned nonzero revision and authority change", result) + } + granted, err := built.Service.GetSession(ctx, persisted.ID) + if err != nil { + t.Fatalf("GetSession after refresh: %v", err) + } + authority, bound := granted.BoundAuthority() + if !bound || !slices.Contains(authority.CapabilitySet.Tools, "mcp__live__echo") { + t.Fatalf("authority after explicit refresh = %+v, bound=%v", authority, bound) + } + + run, err = built.Service.StartRun(ctx, persisted.ID, "call newly granted tool") + if err != nil { + t.Fatalf("StartRun after refresh: %v", err) + } + if got := drainRun(run); got != "after complete" { + t.Fatalf("after-refresh final text = %q", got) + } + built.Service.FinishRun(persisted.ID, run) + afterRefresh, err := built.Service.GetSession(ctx, persisted.ID) + if err != nil { + t.Fatalf("GetSession after execution: %v", err) + } + assertMCPRefreshToolResult(t, afterRefresh, "after-refresh", "echo:after") +} + +func assertMCPRefreshToolResult(t *testing.T, sess *session.Session, callID, contains string) { + t.Helper() + for _, msg := range sess.Conversation.Messages { + if msg.ToolResult != nil && msg.ToolResult.CallID == session.ToolCallID(callID) { + if !strings.Contains(msg.ToolResult.Content, contains) { + t.Fatalf("tool result %q = %q, want substring %q", callID, msg.ToolResult.Content, contains) + } + return + } + } + t.Fatalf("no tool result for call %q", callID) +} From e0ec0f080b5bce134954ef230411d8ec543e6b1b Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 03:13:05 +0200 Subject: [PATCH 11/14] fix: preserve pinned MCP runtime ownership Co-Authored-By: OpenAI Codex --- internal/adapter/server/mcp_refresh_test.go | 55 ++++++++ internal/adapter/server/service.go | 3 + internal/adapter/server/team.go | 4 +- internal/app/build.go | 3 + internal/app/mcp_reconciler.go | 56 ++++---- internal/app/mcp_reconciler_test.go | 42 ++++++ internal/app/mcp_runtime_publication_test.go | 129 ++++++++++++++++--- internal/app/root_authority.go | 30 ++++- 8 files changed, 276 insertions(+), 46 deletions(-) diff --git a/internal/adapter/server/mcp_refresh_test.go b/internal/adapter/server/mcp_refresh_test.go index 3e262a1ad9..cb6f3ee3c0 100644 --- a/internal/adapter/server/mcp_refresh_test.go +++ b/internal/adapter/server/mcp_refresh_test.go @@ -399,6 +399,61 @@ func TestMCPSourceReconciliation_Scenario4_ServiceRefreshMutationMatrix(t *testi }) t.Run("actual-service-grant-count-and-name-byte-bounds", func(t *testing.T) { + t.Run("historical-authority-bound", func(t *testing.T) { + makeNames := func(n int) []string { + names := make([]string, n) + for i := range names { + names[i] = fmt.Sprintf("historical_tool_%05d", i) + } + return names + } + newHistoricalFixture := func(t *testing.T, initial, active []string) (*server.Service, *refreshStore, session.SessionID) { + t.Helper() + store := &refreshStore{Store: memstore.New()} + eng := agent.NewEngine(agent.Deps{LLM: mockllm.New(), Catalog: tool.NewCatalog(), Policy: permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil), Model: "test"}) + svc, err := newPlacementTestService(server.Config{ + Engine: eng, Store: store, OwnershipEnforced: true, + RootAuthority: func(session.SessionKind) session.Authority { + return session.Authority{CapabilitySet: governance.CapabilitySet{Tools: append([]string(nil), initial...)}, Provenance: "test"} + }, + MCPRefresh: func(context.Context) (server.MCPRefreshSnapshot, error) { + return server.MCPRefreshSnapshot{Revision: 7, ToolNames: append([]string(nil), active...)}, nil + }, + }) + if err != nil { + t.Fatal(err) + } + sess, err := svc.CreateSession(ownerCtx, session.ModeDefault, session.Limits{}) + if err != nil { + t.Fatal(err) + } + store.mu.Lock() + store.saves = 0 + store.mu.Unlock() + return svc, store, sess.ID + } + + atBound := makeNames(16_384) + svc, store, id := newHistoricalFixture(t, atBound, atBound[:1]) + got, err := svc.RefreshMcpSources(ownerCtx, id) + if err != nil || got.Changed || store.saveCount() != 0 { + t.Fatalf("at bound result=%+v err=%v saves=%d", got, err, store.saveCount()) + } + + overBound := makeNames(16_385) + svc, store, id = newHistoricalFixture(t, overBound, overBound[:1]) + if _, err := svc.RefreshMcpSources(ownerCtx, id); !errors.Is(err, server.ErrFailedPrecondition) || store.saveCount() != 0 { + t.Fatalf("over bound err=%v saves=%d", err, store.saveCount()) + } + + legacyAbove512 := makeNames(513) + svc, store, id = newHistoricalFixture(t, legacyAbove512, []string{"mcp__new__call"}) + got, err = svc.RefreshMcpSources(ownerCtx, id) + if err != nil || !got.Changed || store.saveCount() != 1 { + t.Fatalf("valid >512 result=%+v err=%v saves=%d", got, err, store.saveCount()) + } + }) + t.Run("union-count-bound", func(t *testing.T) { names := make([]string, 1_025) for i := range names { diff --git a/internal/adapter/server/service.go b/internal/adapter/server/service.go index d945ffaf27..2e06d1cfa4 100644 --- a/internal/adapter/server/service.go +++ b/internal/adapter/server/service.go @@ -357,6 +357,9 @@ type Config struct { // this callback with its assembled catalog. Carryover forks copy their source // authority instead of invoking it. RootAuthority func(session.SessionKind) session.Authority + // RootAuthorityForOperation mints authority from the runtime pinned in ctx for + // direct operations that build roots after their operation boundary. + RootAuthorityForOperation func(context.Context, session.SessionKind) session.Authority // DefaultMode is applied when a CreateSession request leaves mode // unspecified. Defaults to session.ModeDefault when empty. DefaultMode session.PermissionMode diff --git a/internal/adapter/server/team.go b/internal/adapter/server/team.go index 852ed35d40..012a24b112 100644 --- a/internal/adapter/server/team.go +++ b/internal/adapter/server/team.go @@ -443,7 +443,9 @@ func (s *Service) buildTeamForOperation(ctx context.Context, teamID string, ts * agent.WithTeamOwner(ts.owner), agent.WithTeamReadLedgerFactory(func() tool.ReadLedger { return memledger.New() }), } - if s.cfg.RootAuthority != nil { + if s.cfg.RootAuthorityForOperation != nil { + opts = append(opts, agent.WithRootAuthority(s.cfg.RootAuthorityForOperation(ctx, session.SessionKindTeamMember))) + } else if s.cfg.RootAuthority != nil { opts = append(opts, agent.WithRootAuthority(s.cfg.RootAuthority(session.SessionKindTeamMember))) } if s.cfg.TeamGoalUntrusted { diff --git a/internal/app/build.go b/internal/app/build.go index 56a75d099a..4bfea3ef18 100644 --- a/internal/app/build.go +++ b/internal/app/build.go @@ -2232,6 +2232,9 @@ func Build(ctx context.Context, cfg Config) (*Built, error) { RootAuthority: func(kind session.SessionKind) session.Authority { return mintRuntimeRootAuthority(assets.rootCatalog, assets.mcpRuntimes, kind) }, + RootAuthorityForOperation: func(ctx context.Context, kind session.SessionKind) session.Authority { + return mintOperationRootAuthority(ctx, assets.rootCatalog, assets.mcpRuntimes, kind) + }, SharedEngineRoot: cfg.Workspace, // the launch root; a session on a DIFFERENT root routes through the per-session factory (issue #102, docs/adr/0032) // ADR 0237 applied to outbound MCP: the same deployment-policy discipline — // decided by the cmd/ main from its listener topology, passed through here, diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go index 963253ce06..69b7b9fbc2 100644 --- a/internal/app/mcp_reconciler.go +++ b/internal/app/mcp_reconciler.go @@ -113,12 +113,13 @@ type mcpSourceReconciler struct { after func(time.Duration) <-chan time.Time trigger chan struct{} - mu sync.Mutex - waiters []chan mcpReconcileReply - lkg map[string]mcpSourceSnapshot - current *mcpReconcileCandidate - status serveradapter.MCPSourceStatus - closed bool + mu sync.Mutex + waiters []chan mcpReconcileReply + lkg map[string]mcpSourceSnapshot + current *mcpReconcileCandidate + ownsCurrent bool + status serveradapter.MCPSourceStatus + closed bool cyclesDone atomic.Int64 nextGen atomic.Uint64 @@ -308,26 +309,29 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { result.candidate = old return result, nil } - r.mu.Lock() - r.current = candidate - r.mu.Unlock() r.preparingGen.CompareAndSwap(generation, 0) - if r.publish != nil && !r.publish(old, candidate) { - r.mu.Lock() - if r.current == candidate { - r.current = old + if r.publish != nil { + if !r.publish(old, candidate) { + candidate.close() + result.candidate = old + result.stale = true + result.diagnostics = appendBoundedDiagnostic(result.diagnostics, "MCP runtime publication is pending integration") + return result, nil } + r.mu.Lock() + r.current = candidate + r.ownsCurrent = false r.mu.Unlock() - candidate.close() - result.candidate = old - result.stale = true - result.diagnostics = appendBoundedDiagnostic(result.diagnostics, "MCP runtime publication is pending integration") - return result, nil - } - // A publication hook owns displaced-runtime retirement. Without one, preserve - // the reconciler's original immediate-close behavior for unit embeddings. - if old != nil && r.publish == nil { - old.close() + } else { + r.mu.Lock() + r.current = candidate + r.ownsCurrent = true + r.mu.Unlock() + // Without a publication hook, preserve the reconciler's original + // immediate-close behavior for unit embeddings. + if old != nil { + old.close() + } } result.candidate = candidate result.changed = true @@ -401,9 +405,13 @@ func (r *mcpSourceReconciler) Close() { r.wg.Wait() r.mu.Lock() current := r.current + owned := r.ownsCurrent r.current = nil + r.ownsCurrent = false r.mu.Unlock() - current.close() + if owned { + current.close() + } }) } diff --git a/internal/app/mcp_reconciler_test.go b/internal/app/mcp_reconciler_test.go index 1e6b18609e..9b286b6a1b 100644 --- a/internal/app/mcp_reconciler_test.go +++ b/internal/app/mcp_reconciler_test.go @@ -41,6 +41,48 @@ func candidateFromConfigs(configs []mcp.ServerConfig, generation uint64) *mcpRec return &mcpReconcileCandidate{configs: cloneMCPConfigs(configs), generation: generation} } +func TestMCPSourceReconcilerCloseOwnership(t *testing.T) { + t.Run("accepted-publication-transfers-ownership", func(t *testing.T) { + runtimes := newMCPRuntimeSet(nil) + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "live", URL: "http://live/mcp"}}}}, + build: func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, 1), nil + }, + publish: runtimes.publish, + }) + result, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatal(err) + } + r.Close() + if result.candidate.isClosed() { + t.Fatal("reconciler closed runtime-set-owned current candidate") + } + runtimes.close() + if !result.candidate.isClosed() { + t.Fatal("runtime set did not close accepted candidate") + } + }) + + t.Run("default-publication-retains-reconciler-ownership", func(t *testing.T) { + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{&reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "live", URL: "http://live/mcp"}}}}, + build: func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, 1), nil + }, + }) + result, err := r.Reconcile(context.Background()) + if err != nil { + t.Fatal(err) + } + r.Close() + if !result.candidate.isClosed() { + t.Fatal("reconciler leaked its current candidate") + } + }) +} + func TestMCPSourceReconciliation_Scenario1_OrderedSourcesLKGAndEmpty(t *testing.T) { static := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "same", URL: "http://static/mcp"}}} toolhive := &reconciliationSource{name: "toolhive(default)", cfgs: []mcp.ServerConfig{{Name: "same", URL: "http://toolhive/mcp"}, {Name: "dynamic", URL: "http://dynamic/mcp"}}} diff --git a/internal/app/mcp_runtime_publication_test.go b/internal/app/mcp_runtime_publication_test.go index 396c56073d..34df7becdc 100644 --- a/internal/app/mcp_runtime_publication_test.go +++ b/internal/app/mcp_runtime_publication_test.go @@ -2,6 +2,7 @@ package app import ( "context" + "fmt" "net/http" "net/http/httptest" "strings" @@ -320,13 +321,13 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T } runRuntimes.close() - // Direct teams retain declarations only until RunTeam. Publication between - // CreateTeam and RunTeam must retire the old runtime and build every member and - // referenced specialist from the operation pin acquired by RunTeam. + // Direct teams retain declarations only until RunTeam. Publication after + // RunTeam pins but before member construction must build every member and + // referenced specialist, including root authority, from that operation pin. const teamTool = "mcp__svc__echo" teamRuntimes := newMCPRuntimeSet(nil) teamOldManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "team-old:")) - teamOld := &mcpReconcileCandidate{manager: teamOldManager, generation: 1, tools: toolMetadata(teamOldManager.Tools())} + teamOld := &mcpReconcileCandidate{manager: teamOldManager, generation: 1, tools: append(toolMetadata(teamOldManager.Tools()), mcpToolMeta{Name: "mcp__old__only"})} if !teamRuntimes.publish(nil, teamOld) { t.Fatal("publish direct-team revision 1") } @@ -350,24 +351,31 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T Name: "team-ref", Description: "uses the pinned referenced service", Origin: tool.AgentOriginExplicit, MCPServers: []agents.AgentMCPServer{{Name: "svc"}}, }}) - teamAssets := catalogAssets{mcpRuntimes: teamRuntimes, agentReg: teamDefs} + teamAssets := catalogAssets{rootCatalog: tool.NewCatalog(), mcpRuntimes: teamRuntimes, agentReg: teamDefs} var teamServerCfg server.Config applyTeamConfig(&teamServerCfg, teamCfg, teamReg, teamProvider, teamOldManager, teamDefs, nil, teamAssets) teamStore := memstore.New() - rootNames := []string{teamTool} - for name := range agent.MemberToolNames() { - rootNames = append(rootNames, name) - } teamServerCfg.Engine = initial teamServerCfg.Store = teamStore teamServerCfg.SharedEngineRoot = teamCfg.Workspace teamServerCfg.OperationPin = teamRuntimes.pin teamServerCfg.OperationRevision = mcpRuntimeRevision - teamServerCfg.RootAuthority = func(session.SessionKind) session.Authority { - return session.Authority{ - CapabilitySet: governance.CapabilitySet{Tools: rootNames, FileSystem: true}, - Provenance: "test", DefinitionIdentity: "test", + teamServerCfg.RootAuthority = func(kind session.SessionKind) session.Authority { + return mintRuntimeRootAuthority(teamAssets.rootCatalog, teamRuntimes, kind) + } + teamServerCfg.RootAuthorityForOperation = func(ctx context.Context, kind session.SessionKind) session.Authority { + return mintOperationRootAuthority(ctx, teamAssets.rootCatalog, teamRuntimes, kind) + } + operationFactory := teamServerCfg.MemberEngineForOperation + factoryPinned := make(chan struct{}) + releaseFactory := make(chan struct{}) + var blockedFactory atomic.Bool + teamServerCfg.MemberEngineForOperation = func(ctx context.Context) server.MemberEngineFactory { + if blockedFactory.CompareAndSwap(false, true) { + close(factoryPinned) + <-releaseFactory } + return operationFactory(ctx) } teamSvc, err := newTestServerService(teamServerCfg) if err != nil { @@ -381,22 +389,37 @@ func TestMCPSourceReconciliation_Scenario2_RuntimeConsistencyMatrix(t *testing.T t.Fatal(err) } teamNewManager := connectMainManager(t, "svc", newMCPTestServerPrefixed(t, "team-new:")) - teamNew := &mcpReconcileCandidate{manager: teamNewManager, generation: 2, tools: toolMetadata(teamNewManager.Tools())} + teamNew := &mcpReconcileCandidate{manager: teamNewManager, generation: 2, tools: append(toolMetadata(teamNewManager.Tools()), mcpToolMeta{Name: "mcp__new__only"})} + runDone := make(chan error, 1) + go func() { + _, runErr := teamSvc.RunTeam(context.Background(), teamID, func(agent.TeamEvent) {}) + runDone <- runErr + }() + select { + case <-factoryPinned: + case <-time.After(time.Second): + t.Fatal("direct RunTeam did not pin before member construction") + } if !teamRuntimes.publish(teamOld, teamNew) { t.Fatal("publish direct-team revision 2") } - if !teamOld.isClosed() { - t.Fatal("created-but-unrun direct team retained the retired runtime") + if teamOld.isClosed() { + t.Fatal("direct-team operation pin did not retain old runtime") } - if _, err := teamSvc.RunTeam(context.Background(), teamID, func(agent.TeamEvent) {}); err != nil { + close(releaseFactory) + if err := <-runDone; err != nil { t.Fatal(err) } member, err := teamStore.Load(context.Background(), agent.MemberSessionID(teamID, "lead")) if err != nil { t.Fatal(err) } - if got := latestToolResult(member, "team-call"); !strings.Contains(got, "team-new:work") { - t.Fatalf("direct RunTeam member did not use its run-time pin: %q", got) + if got := latestToolResult(member, "team-call"); !strings.Contains(got, "team-old:work") { + t.Fatalf("direct RunTeam member did not use its pinned runtime: %q", got) + } + memberAuthority, ok := member.BoundAuthority() + if !ok || !memberAuthority.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__old__only"}}) || memberAuthority.CapabilitySet.Contains(governance.CapabilitySet{Tools: []string{"mcp__new__only"}}) { + t.Fatalf("direct RunTeam member authority did not use pinned names: %+v", memberAuthority) } newTeamID, _, err := teamSvc.CreateTeamOnDefaultPlacement(context.Background(), "current", "use the current service", 0, []agent.MemberSpec{{ Name: "lead", Lead: true, AgentType: "team-ref", InitialPrompt: "call the service once", @@ -586,6 +609,74 @@ func newRuntimeSurfaceServer(t *testing.T, version string, readStarted chan<- st return httpServer.URL } +func TestBuiltCloseWaitsForPinnedMCPTransport(t *testing.T) { + started := make(chan struct{}) + release := make(chan struct{}) + remote := mcpsdk.NewServer(&mcpsdk.Implementation{Name: "close-order", Version: "v1"}, nil) + remote.AddResource(&mcpsdk.Resource{URI: "test://blocked", Name: "blocked"}, func(ctx context.Context, req *mcpsdk.ReadResourceRequest) (*mcpsdk.ReadResourceResult, error) { + close(started) + select { + case <-release: + case <-ctx.Done(): + return nil, ctx.Err() + } + return &mcpsdk.ReadResourceResult{Contents: []*mcpsdk.ResourceContents{{URI: req.Params.URI, Text: "settled"}}}, nil + }) + var transportCloses atomic.Int32 + sdkHandler := mcpsdk.NewStreamableHTTPHandler(func(*http.Request) *mcpsdk.Server { return remote }, nil) + httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodDelete { + transportCloses.Add(1) + } + sdkHandler.ServeHTTP(w, r) + })) + defer httpServer.Close() + + built, err := buildIsolated(t, context.Background(), Config{ + Workspace: t.TempDir(), UseMock: true, NoSoul: true, + MCPServers: []mcp.ServerConfig{{Name: "svc", URL: httpServer.URL}}, + }) + if err != nil { + t.Fatal(err) + } + readDone := make(chan error, 1) + go func() { + contents, readErr := built.Service.ReadMcpResource(context.Background(), "svc", "test://blocked") + if readErr == nil && contents.Text != "settled" { + readErr = fmt.Errorf("contents = %q", contents.Text) + } + readDone <- readErr + }() + select { + case <-started: + case <-time.After(time.Second): + t.Fatal("resource read did not reach blocked transport") + } + closeDone := make(chan struct{}) + go func() { + built.Close() + close(closeDone) + }() + select { + case <-closeDone: + t.Fatal("Built.Close returned before the pinned MCP transport settled") + case <-time.After(20 * time.Millisecond): + } + close(release) + if err := <-readDone; err != nil { + t.Fatal(err) + } + select { + case <-closeDone: + case <-time.After(time.Second): + t.Fatal("Built.Close hung after the pinned transport settled") + } + built.Close() + if got := transportCloses.Load(); got != 1 { + t.Fatalf("transport close callbacks = %d, want 1", got) + } +} + func TestMCPSourceReconciliation_Scenario3_NameAuthorityAvailabilityMatrix(t *testing.T) { const ( name = "mcp__svc__echo" diff --git a/internal/app/root_authority.go b/internal/app/root_authority.go index 829bc08c9b..cfe3f3cd39 100644 --- a/internal/app/root_authority.go +++ b/internal/app/root_authority.go @@ -1,6 +1,7 @@ package app import ( + "context" "fmt" "os" "sort" @@ -152,6 +153,31 @@ func mintRuntimeRootAuthority(catalog *tool.Catalog, runtimes *mcpRuntimeSet, ki if runtimes == nil || kind == session.SessionKindDebug { return mintRootAuthority(catalog, nil, kind) } + return mintDirectRuntimeRootAuthority(catalog, kind, runtimes.currentToolNames(), runtimes.currentResourceServers()) +} + +func mintOperationRootAuthority(ctx context.Context, catalog *tool.Catalog, runtimes *mcpRuntimeSet, kind session.SessionKind) session.Authority { + candidate := mcpRuntimeCandidate(ctx) + if runtimes == nil || candidate == nil || kind == session.SessionKindDebug { + return mintRuntimeRootAuthority(catalog, runtimes, kind) + } + toolNames := make([]string, 0, len(candidate.tools)) + for _, meta := range candidate.tools { + toolNames = append(toolNames, meta.Name) + } + seen := make(map[string]struct{}) + resourceServers := make([]string, 0) + for _, resource := range candidate.resources { + if _, ok := seen[resource.Server]; ok { + continue + } + seen[resource.Server] = struct{}{} + resourceServers = append(resourceServers, resource.Server) + } + return mintDirectRuntimeRootAuthority(catalog, kind, toolNames, resourceServers) +} + +func mintDirectRuntimeRootAuthority(catalog *tool.Catalog, kind session.SessionKind, toolNames, resourceServers []string) session.Authority { authority := mintRootAuthority(catalog, nil, kind) names := authority.CapabilitySet.Tools[:0] for _, name := range authority.CapabilitySet.Tools { @@ -160,8 +186,8 @@ func mintRuntimeRootAuthority(catalog *tool.Catalog, runtimes *mcpRuntimeSet, ki } names = append(names, name) } - names = append(names, runtimes.currentToolNames()...) - for _, server := range runtimes.currentResourceServers() { + names = append(names, toolNames...) + for _, server := range resourceServers { names = append(names, governance.MCPResourceCapability(server)) } authority.CapabilitySet.Tools = names From 278ffac2798c540c221502cb59fb4926ec2e86fe Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 03:27:26 +0200 Subject: [PATCH 12/14] fix: publish active MCP source inventory Co-Authored-By: Mecatl --- internal/app/mcp_reconciler.go | 41 ++++++++--- internal/app/mcp_reconciler_test.go | 104 ++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 8 deletions(-) diff --git a/internal/app/mcp_reconciler.go b/internal/app/mcp_reconciler.go index 69b7b9fbc2..13623a04b6 100644 --- a/internal/app/mcp_reconciler.go +++ b/internal/app/mcp_reconciler.go @@ -198,20 +198,26 @@ func (r *mcpSourceReconciler) loop() { r.status.Reconciling = true r.mu.Unlock() result, err := r.cycle() - r.mu.Lock() - r.status.Sources = cloneMCPInventory(result.inventory) - r.status.Stale = result.stale - r.status.Reconciling = false - if result.candidate != nil { - r.status.Revision = result.candidate.generation - } - r.mu.Unlock() + r.publishStatus(result) r.cyclesDone.Add(1) replyMCPWaiters(waiters, result, err) } } } +func (r *mcpSourceReconciler) publishStatus(result mcpReconcileResult) { + r.mu.Lock() + defer r.mu.Unlock() + r.status.Sources = nil + r.status.Revision = 0 + if r.current != nil { + r.status.Sources = publishedMCPInventory(r.current.inventory, result.inventory) + r.status.Revision = r.current.generation + } + r.status.Stale = result.stale + r.status.Reconciling = false +} + func mcpPollDelay() time.Duration { span := maxMCPPollInterval - minMCPPollInterval if span <= 0 { @@ -250,6 +256,12 @@ func (r *mcpSourceReconciler) cycle() (mcpReconcileResult, error) { r.mu.Unlock() return result, err } + if stale { + r.mu.Lock() + result.candidate = r.current + r.mu.Unlock() + return result, nil + } r.mu.Lock() current := r.current @@ -486,6 +498,19 @@ func cloneMCPInventory(in []mcpsource.SourceInfo) []mcpsource.SourceInfo { return out } +func publishedMCPInventory(published, observed []mcpsource.SourceInfo) []mcpsource.SourceInfo { + inventory := cloneMCPInventory(published) + for i := range inventory { + for _, observation := range observed { + if inventory[i].Name == observation.Name { + inventory[i].Diagnostics = append([]string(nil), observation.Diagnostics...) + break + } + } + } + return inventory +} + func appendBoundedDiagnostic(dst []string, raw string) []string { safe := mcp.RedactText(strings.Join(strings.Fields(raw), " ")) if len(safe) > maxMCPDiagnosticBytes { diff --git a/internal/app/mcp_reconciler_test.go b/internal/app/mcp_reconciler_test.go index 9b286b6a1b..b051d59a4d 100644 --- a/internal/app/mcp_reconciler_test.go +++ b/internal/app/mcp_reconciler_test.go @@ -16,6 +16,7 @@ import ( "github.com/stacklok/mecatl/internal/adapter/mcp" mcpsource "github.com/stacklok/mecatl/internal/adapter/mcp/source" + serveradapter "github.com/stacklok/mecatl/internal/adapter/server" ) type reconciliationSource struct { @@ -355,6 +356,109 @@ func TestADR_0346_ReconciliationBoundsConsentAndShutdown(t *testing.T) { } } +func TestMCPSourceReconciliation_StatusPublishesOnlyActiveCandidateInventory(t *testing.T) { + for _, tc := range []struct { + name string + build func([]mcp.ServerConfig) (*mcpReconcileCandidate, error) + publish func(*mcpReconcileCandidate, *mcpReconcileCandidate) bool + sourceErr error + }{ + { + name: "source failure", + sourceErr: errors.New("source unavailable"), + }, + { + name: "build failure", + build: func([]mcp.ServerConfig) (*mcpReconcileCandidate, error) { + return nil, errors.New("build failed") + }, + }, + { + name: "validation failure", + build: func(configs []mcp.ServerConfig) (*mcpReconcileCandidate, error) { + return &mcpReconcileCandidate{configs: cloneMCPConfigs(configs), tools: make([]mcpToolMeta, maxMCPActiveListEntries+1)}, nil + }, + }, + { + name: "publication deferred", + build: func(configs []mcp.ServerConfig) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, 0), nil + }, + publish: func(*mcpReconcileCandidate, *mcpReconcileCandidate) bool { return false }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + source := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "a", URL: "http://a/mcp"}}} + build := func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return candidateFromConfigs(configs, 0), nil + } + r := newMCPSourceReconciler(mcpReconcilerOptions{sources: []mcpsource.Source{source}, build: build}) + t.Cleanup(r.Close) + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatalf("initial reconcile: %v", err) + } + initial := r.statusSnapshot() + if initial.Revision == 0 || sourceStatusServerNames(initial) != "a" { + t.Fatalf("initial status = %+v", initial) + } + + source.set([]mcp.ServerConfig{{Name: "b", URL: "http://b/mcp"}}, tc.sourceErr) + if tc.build != nil { + r.build = func(_ context.Context, configs []mcp.ServerConfig, _ func()) (*mcpReconcileCandidate, error) { + return tc.build(configs) + } + } + r.publish = tc.publish + _, _ = r.Reconcile(context.Background()) + failed := r.statusSnapshot() + if failed.Revision != initial.Revision || sourceStatusServerNames(failed) != "a" || !failed.Stale { + t.Fatalf("failed status = %+v, want active candidate A marked stale", failed) + } + if tc.sourceErr != nil && !strings.Contains(strings.Join(failed.Sources[0].Diagnostics, " "), "source consultation failed") { + t.Fatalf("source failure diagnostic missing from status: %+v", failed) + } + + r.build = build + r.publish = nil + source.set([]mcp.ServerConfig{{Name: "b", URL: "http://b/mcp"}}, nil) + if _, err := r.Reconcile(context.Background()); err != nil { + t.Fatalf("later reconcile: %v", err) + } + success := r.statusSnapshot() + if success.Revision == initial.Revision || sourceStatusServerNames(success) != "b" || success.Stale { + t.Fatalf("successful status = %+v, want published candidate B", success) + } + }) + } +} + +func TestMCPSourceReconciliation_StatusIsEmptyWithoutAnActiveCandidate(t *testing.T) { + source := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "unpublished", URL: "http://unpublished/mcp"}}} + r := newMCPSourceReconciler(mcpReconcilerOptions{ + sources: []mcpsource.Source{source}, + build: func(context.Context, []mcp.ServerConfig, func()) (*mcpReconcileCandidate, error) { + return nil, errors.New("build failed") + }, + }) + t.Cleanup(r.Close) + if _, err := r.Reconcile(context.Background()); err == nil { + t.Fatal("initial failed reconcile unexpectedly succeeded") + } + if status := r.statusSnapshot(); status.Revision != 0 || len(status.Sources) != 0 || !status.Stale { + t.Fatalf("initial failed status = %+v, want empty stale status", status) + } +} + +func sourceStatusServerNames(status serveradapter.MCPSourceStatus) string { + var names []string + for _, source := range status.Sources { + for _, server := range source.Servers { + names = append(names, server.Name) + } + } + return strings.Join(names, ",") +} + func TestMCPSourceReconciliation_Scenario2_FailedCompleteCandidateKeepsPreviousRuntime(t *testing.T) { healthyURL, deletes := newMCPTestServerCounting(t) source := &reconciliationSource{name: "static", cfgs: []mcp.ServerConfig{{Name: "healthy", URL: healthyURL}}} From 32b915ddc71935eba0a4b9e7f23439d4b951a0c5 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 03:43:15 +0200 Subject: [PATCH 13/14] docs: record MCP reconciliation completion Co-Authored-By: Mecatl --- docs/acceptance/README.md | 2 +- docs/acceptance/mcp-source-reconciliation.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/acceptance/README.md b/docs/acceptance/README.md index 65fae7b1c5..4b9051c3b0 100644 --- a/docs/acceptance/README.md +++ b/docs/acceptance/README.md @@ -152,7 +152,7 @@ PR after verification. There is no cleanup or status-only PR. attributable Linux and macOS command/job temporary storage with a permission-visible system escape and deterministic crash-residue reaping. Status: landed. - [Session title generation and token usage](session-title-generation.md) — mecatui `/title`, an opt-in routed model title after up to three genuine prompts, and durable title-model token attribution. Status: draft. -- [MCP source reconciliation](mcp-source-reconciliation.md) — bounded ToolHive polling, MCP notifications, and manual refresh publish immutable direct MCP runtimes while preserving exact-name authority; explicit owner refresh unions additions. Status: proposed. +- [MCP source reconciliation](mcp-source-reconciliation.md) — bounded ToolHive polling, MCP notifications, and manual refresh publish immutable direct MCP runtimes while preserving exact-name authority; explicit owner refresh unions additions. Status: landed in the stacked implementation candidate; authoritative only after human merge. - [Mecatui-owned configurable terminal titles](mecatui-terminal-title-controller.md) — replaces Bubble Tea title emission with a renderer-serialized OSC 0 controller, user-global plain-text title templates over display-safe status facts, explicit disablement precedence, and live-run `/session` identity access. Status: proposed. - [Per-upstream MCP broker OAuth grants](mcp-broker-multi-upstream-oauth.md) — accept multiple broker OAuth upstreams while keeping grants, callback state, authenticated discovery, and workspace-enrollment progression backend-scoped. Status: draft. - [Broker MCP status](broker-mcp-status.md) — approved owner-scoped broker connector diff --git a/docs/acceptance/mcp-source-reconciliation.md b/docs/acceptance/mcp-source-reconciliation.md index 83e5ffc495..9fe5096d84 100644 --- a/docs/acceptance/mcp-source-reconciliation.md +++ b/docs/acceptance/mcp-source-reconciliation.md @@ -4,7 +4,7 @@ **Work classification:** Architectural — changes process-wide MCP publication, runtime ownership, a public refresh control, and one importable aggregate API. **Decision record:** [ADR 0346](../adr/0346-mcp-source-reconciliation.md) **Phase:** Minimal stale direct/global MCP source reconciliation -**Status:** proposed, 2026-09-16. Directing-human decisions are settled; ready for amended Plan / Interface review. +**Status:** landed in this implementation candidate, 2026-09-17. The transition becomes authoritative only when a human merges the stacked implementation after the Plan / Interface PR; it does not claim the behavior is currently shipped. **Baseline synchronization:** merged `origin/main` at `6c75a42d9cad502685a42f5418f2bc99b9ae6376`; the proposed technical contract is unchanged, while its Proposed ADR and two ADR-named verification functions moved from 0345 to 0346 because incoming main allocated 0345. **Delivery:** Split. Runtime publication and additive public controls require contract review. The directing human explicitly authorizes a stacked implementation PR before this Plan PR merges, based on the exact amended plan commit and targeting `plan/mcp-source-reconciliation`; this does not approve or merge either PR, and contract-drift gates remain. **Expected tasks:** deferred to orchestration after parent advisory review. @@ -116,6 +116,10 @@ Direct refresh reconciles shared state first, then adds only missing active dire 6. `task generate`, `task lint`, `task test`, `task api:check`, `task docs`, `task site:build`, `task ac-trace-strict`, and `go run ./cmd/mecademo` pass at implementation completion. 7. The implementation PR remains stacked until plan merge, reports exact interface conformance, and has no unwaived review blocker. This plan tracks #1511 but does not close it. +## Completion proof + +All 12 `verify:` targets under AC1.1–AC4.3 pass on the implementation candidate. `task ac-trace-strict` resolves every target, and the aggregate gates in Definition of done item 6 pass on the same tree; the final panel records zero ship blockers and zero reviewer failures. + ## Deferred decisions and known risks - Exact poll, cooldown, source/server/tool/list, connect, and retirement bounds are finite tested implementation constants. From ece4671ec5b5e88980f101038e56ee4ac6e5de64 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 17 Sep 2026 04:11:41 +0200 Subject: [PATCH 14/14] fix: advertise deferred team member session IDs Co-Authored-By: Mecatl --- engine/team/team.go | 4 +- internal/adapter/server/team.go | 10 +++- internal/adapter/server/team_test.go | 78 ++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/engine/team/team.go b/engine/team/team.go index 61ec5bc32c..2cda036839 100644 --- a/engine/team/team.go +++ b/engine/team/team.go @@ -106,8 +106,8 @@ type Member struct { // AgentType is the optional agent-definition name this member adopts (its // scoped tools / model / prompt); empty for a generic member. AgentType string - // Session is the id of the running session backing this member (empty until - // the supervisor wires it). + // Session is the stable id reserved for the runtime session backing this + // member. It may be advertised before that runtime is materialized. Session session.SessionID // State is the member's lifecycle state. State MemberState diff --git a/internal/adapter/server/team.go b/internal/adapter/server/team.go index 012a24b112..f3792308f6 100644 --- a/internal/adapter/server/team.go +++ b/internal/adapter/server/team.go @@ -204,7 +204,7 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ budget: maxTeamTokens, specs: append([]agent.MemberSpec(nil), members...), owner: session.PrincipalFromContext(ctx).Clone(), } - if err := s.declareInitialRoster(t, members); err != nil { + if err := s.declareInitialRoster(t, id, members); err != nil { return "", nil, err } if s.cfg.OperationPin == nil { @@ -240,7 +240,7 @@ func (s *Service) createTeamInEnvironment(ctx context.Context, base tool.Environ return id, state.team.Members(), nil } -func (s *Service) declareInitialRoster(t *team.Team, members []agent.MemberSpec) error { +func (s *Service) declareInitialRoster(t *team.Team, teamID string, members []agent.MemberSpec) error { for _, spec := range members { if spec.Name == "" { return fmt.Errorf("%w: %v", ErrInvalidArgument, agent.ErrMemberNameRequired) @@ -251,6 +251,9 @@ func (s *Service) declareInitialRoster(t *team.Team, members []agent.MemberSpec) if err := t.AddMember(spec.Name, spec.AgentType); err != nil { return classifyAddMemberErr(err) } + if err := t.SetMemberSession(spec.Name, agent.MemberSessionID(teamID, spec.Name)); err != nil { + return fmt.Errorf("%w: advertise member session: %v", ErrInternal, err) + } } return nil } @@ -321,6 +324,9 @@ func (s *Service) SpawnTeammate(ctx context.Context, teamID string, spec agent.M } else if err := ts.team.AddMember(spec.Name, spec.AgentType); err != nil { return team.Member{}, classifyAddMemberErr(err) } + if err := ts.team.SetMemberSession(spec.Name, agent.MemberSessionID(teamID, spec.Name)); err != nil { + return team.Member{}, fmt.Errorf("%w: advertise member session: %v", ErrInternal, err) + } ts.specs = append(ts.specs, spec) for _, m := range ts.team.Members() { if m.Name == spec.Name { diff --git a/internal/adapter/server/team_test.go b/internal/adapter/server/team_test.go index 32121cd3b7..8350561563 100644 --- a/internal/adapter/server/team_test.go +++ b/internal/adapter/server/team_test.go @@ -162,6 +162,84 @@ func TestMemberSessionIDRoundTripsGRPCPath(t *testing.T) { } } +func TestDeclaredTeamMembersAdvertiseCanonicalSessionIDsBeforeRun(t *testing.T) { + allow := permpolicy.NewPolicy(permpolicy.AllowAllFloorRules(), nil) + memberEngine := func(tm *team.Team, spec agent.MemberSpec, _ string) agent.MemberBuild { + cat := tool.NewCatalog() + for _, tl := range agent.MemberTools(tm, spec.Name, nil) { + cat.MustRegister(tl) + } + return agent.MemberBuild{Engine: agent.NewEngine(agent.Deps{ + LLM: mockllm.New(mockllm.TextTurn("done")), Catalog: cat, Policy: allow, Model: "mock", + })} + } + store := memstore.New() + svc, err := newPlacementTeamTestService(server.Config{ + Engine: agent.NewEngine(agent.Deps{ + LLM: mockllm.New(mockllm.TextTurn("x")), Catalog: tool.NewCatalog(), Policy: allow, Model: "mock", + }), + Store: store, Now: func() time.Time { return time.Unix(0, 0) }, MemberEngine: memberEngine, + OperationPin: func(ctx context.Context) (context.Context, func(), error) { + return ctx, nil, nil + }, + }) + if err != nil { + t.Fatalf("new service: %v", err) + } + h := server.NewHarnessServer(svc) + ctx := context.Background() + created, err := h.CreateTeam(ctx, newCreateTeamWith("/ws", + &mecatlv1.TeammateSpec{Name: "lead", Lead: true, InitialPrompt: "go"}, + )) + if err != nil { + t.Fatalf("CreateTeam: %v", err) + } + teamID := created.GetTeamId() + wantLead := string(agent.MemberSessionID(teamID, "lead")) + if got := created.GetMembers()[0].GetSessionId(); got != wantLead { + t.Fatalf("CreateTeam lead session_id = %q, want %q", got, wantLead) + } + + spawned, err := h.SpawnTeammate(ctx, newSpawn(teamID, "worker", false, "")) + if err != nil { + t.Fatalf("SpawnTeammate: %v", err) + } + wantWorker := string(agent.MemberSessionID(teamID, "worker")) + if got := spawned.GetMember().GetSessionId(); got != wantWorker { + t.Fatalf("SpawnTeammate worker session_id = %q, want %q", got, wantWorker) + } + + listed, err := h.ListTeam(ctx, &mecatlv1.ListTeamRequest{TeamId: teamID}) + if err != nil { + t.Fatalf("ListTeam: %v", err) + } + want := []string{wantLead, wantWorker} + for i, member := range listed.GetMembers() { + if got := member.GetSessionId(); got != want[i] { + t.Errorf("ListTeam member %q session_id = %q, want %q", member.GetName(), got, want[i]) + } + if _, err := store.Load(ctx, session.SessionID(want[i])); !errors.Is(err, port.ErrSessionNotFound) { + t.Errorf("declared member %q was materialized before RunTeam: %v", want[i], err) + } + } + + if _, err := svc.RunTeam(ctx, teamID, func(agent.TeamEvent) {}); err != nil { + t.Fatalf("RunTeam: %v", err) + } + listed, err = h.ListTeam(ctx, &mecatlv1.ListTeamRequest{TeamId: teamID}) + if err != nil { + t.Fatalf("ListTeam after RunTeam: %v", err) + } + for i, member := range listed.GetMembers() { + if got := member.GetSessionId(); got != want[i] { + t.Errorf("ListTeam after RunTeam member %q session_id = %q, want %q", member.GetName(), got, want[i]) + } + if _, err := store.Load(ctx, session.SessionID(want[i])); err != nil { + t.Errorf("persisted member %q: %v", want[i], err) + } + } +} + // usageTurn builds a single mock member turn that carries token usage via a // UsageChunk — the shared spend knob the team-budget tests tune to cross (or not // cross) a budget bound.